commit
e7d31be953
19 changed files with 1407 additions and 147 deletions
51
js/Map.js
51
js/Map.js
|
|
@ -45,65 +45,67 @@ BR.Map = {
|
|||
maxNativeZoom: 19,
|
||||
maxZoom: maxZoom,
|
||||
subdomains: ['server', 'services'],
|
||||
attribution: '<a target="_blank" href="http://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9">Esri World Imagery</a>'
|
||||
attribution: '<a target="_blank" href="http://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9">' + i18next.t('credits.esri-tiles') + '</a>'
|
||||
});
|
||||
|
||||
var cycling = L.tileLayer('https://tile.waymarkedtrails.org/cycling/{z}/{x}/{y}.png', {
|
||||
maxNativeZoom: 18,
|
||||
opacity: 0.7,
|
||||
maxZoom: maxZoom,
|
||||
attribution: '<a target="_blank" href="http://cycling.waymarkedtrails.org/#?map={zoom}!{lat}!{lon}">Cycling</a>'
|
||||
attribution: '<a target="_blank" href="http://cycling.waymarkedtrails.org/#?map={zoom}!{lat}!{lon}">' + i18next.t('map.cycling') + '</a>'
|
||||
});
|
||||
var hiking = L.tileLayer('https://tile.waymarkedtrails.org/hiking/{z}/{x}/{y}.png', {
|
||||
maxNativeZoom: 18,
|
||||
opacity: 0.7,
|
||||
maxZoom: maxZoom,
|
||||
attribution: '<a target="_blank" href="http://hiking.waymarkedtrails.org/#?map={zoom}!{lat}!{lon}">Hiking</a>'
|
||||
attribution: '<a target="_blank" href="http://hiking.waymarkedtrails.org/#?map={zoom}!{lat}!{lon}">' + i18next.t('map.hiking') + '</a>'
|
||||
});
|
||||
|
||||
map = new L.Map('map', {
|
||||
zoomControl: false, // add it manually so that we can translate it
|
||||
worldCopyJump: true
|
||||
});
|
||||
L.control.zoom({
|
||||
zoomInTitle: i18next.t('map.zoomInTitle'),
|
||||
zoomOutTitle: i18next.t('map.zoomOutTitle'),
|
||||
}).addTo(map);
|
||||
if (!map.restoreView()) {
|
||||
map.setView([50.99, 9.86], 6);
|
||||
}
|
||||
|
||||
// two attribution lines by adding two controls, prevents ugly wrapping on
|
||||
// small screens, better separates static from layer-specific attribution
|
||||
var osmAttribution = $(map.getContainer()).outerWidth() >= 400 ? i18next.t('map.attribution-osm-long') : i18next.t('map.attribution-osm-short');
|
||||
map.attributionControl.setPrefix(
|
||||
'© <a target="_blank" href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>' +
|
||||
($(map.getContainer()).outerWidth() >= 400 ? ' contributers' : '') +
|
||||
' · <a href="" data-toggle="modal" data-target="#credits">Copyright</a>' +
|
||||
' · <a target="_blank" href="http://brouter.de/privacypolicy.html">Privacy</a>');
|
||||
'© <a target="_blank" href="https://www.openstreetmap.org/copyright">' + osmAttribution + '</a>' +
|
||||
' · <a href="" data-toggle="modal" data-target="#credits">' + i18next.t('map.copyright') + '</a>' +
|
||||
' · <a target="_blank" href="http://brouter.de/privacypolicy.html">' + i18next.t('map.privacy') + '</a>');
|
||||
|
||||
new L.Control.PermalinkAttribution().addTo(map);
|
||||
map.attributionControl.setPrefix(false);
|
||||
|
||||
var baseLayers = {
|
||||
'OpenStreetMap': osm,
|
||||
'OpenStreetMap.de': osmde,
|
||||
'OpenTopoMap': topo,
|
||||
'OpenCycleMap (Thunderf.)': cycle,
|
||||
'Outdoors (Thunderforest)': outdoors,
|
||||
'Esri World Imagery': esri
|
||||
};
|
||||
var overlays = {
|
||||
'Cycling (Waymarked Trails)': cycling,
|
||||
'Hiking (Waymarked Trails)': hiking
|
||||
};
|
||||
var baseLayers = {}
|
||||
baseLayers[i18next.t('map.layer.osm')] = osm;
|
||||
baseLayers[i18next.t('map.layer.osmde')] = osmde;
|
||||
baseLayers[i18next.t('map.layer.topo')] = topo;
|
||||
baseLayers[i18next.t('map.layer.cycle')] = cycle;
|
||||
baseLayers[i18next.t('map.layer.outdoors')] = outdoors;
|
||||
baseLayers[i18next.t('map.layer.esri')] = esri;
|
||||
var overlays = {}
|
||||
overlays[i18next.t('map.layer.cycling')] = cycling;
|
||||
overlays[i18next.t('map.layer.hiking')] = hiking;
|
||||
|
||||
if (BR.keys.bing) {
|
||||
baseLayers['Bing Aerial'] = new BR.BingLayer(BR.keys.bing);
|
||||
baseLayers[i18next.t('map.layer.bing')] = new BR.BingLayer(BR.keys.bing);
|
||||
}
|
||||
|
||||
if (BR.keys.digitalGlobe) {
|
||||
var recent = new L.tileLayer('https://{s}.tiles.mapbox.com/v4/digitalglobe.nal0g75k/{z}/{x}/{y}.png?access_token=' + BR.keys.digitalGlobe, {
|
||||
minZoom: 1,
|
||||
maxZoom: 19,
|
||||
attribution: '© <a href="https://www.digitalglobe.com/platforms/mapsapi">DigitalGlobe</a> ('
|
||||
+ '<a href="https://bit.ly/mapsapiview">Terms of Use</a>)'
|
||||
attribution: i18next.t('credits.digitalglobe-license')
|
||||
});
|
||||
baseLayers['DigitalGlobe Recent Imagery'] = recent;
|
||||
baseLayers[i18next.t('map.layer.digitalglobe')] = recent;
|
||||
}
|
||||
|
||||
if (BR.conf.clearBaseLayers) {
|
||||
|
|
@ -131,6 +133,9 @@ BR.Map = {
|
|||
var secureContext = 'isSecureContext' in window ? isSecureContext : location.protocol === 'https:';
|
||||
if (secureContext) {
|
||||
L.control.locate({
|
||||
strings: {
|
||||
title: i18next.t('map.locate-me')
|
||||
},
|
||||
icon: 'fa fa-location-arrow',
|
||||
iconLoading: 'fa fa-spinner fa-pulse',
|
||||
}).addTo(map);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ BR.Util = {
|
|||
},
|
||||
|
||||
getError: function(xhr) {
|
||||
var msg = 'no response from server';
|
||||
var msg = i18next.t('warning.no-response');
|
||||
if (xhr.responseText) {
|
||||
msg = xhr.responseText;
|
||||
} else if (xhr.status || xhr.statusText) {
|
||||
|
|
|
|||
|
|
@ -25,10 +25,13 @@ BR.Layers = L.Class.extend({
|
|||
info: false,
|
||||
searching: false,
|
||||
paging: false,
|
||||
language: {
|
||||
emptyTable: i18next.t("sidebar.layers.table.empty")
|
||||
},
|
||||
columns: [
|
||||
{ title: "Name" },
|
||||
{ title: "URL" },
|
||||
{ title: "Type" }
|
||||
{ title: i18next.t("sidebar.layers.table.name") },
|
||||
{ title: i18next.t("sidebar.layers.table.URL") },
|
||||
{ title: i18next.t("sidebar.layers.table.type") }
|
||||
]
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ BR.Message = L.Class.extend({
|
|||
|
||||
showError: function (err) {
|
||||
if (err == 'Error: target island detected for section 0\n') {
|
||||
err = 'Error: cannot find a route for given points. Maybe try to move them closer to roads?';
|
||||
err = i18next.t('warning.no-route-found');
|
||||
}
|
||||
this._show(err, 'error');
|
||||
},
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ BR.OpacitySlider = L.Control.extend({
|
|||
};
|
||||
|
||||
$(container).html(input);
|
||||
$(container).attr('title', 'Set transparency of route track and markers');
|
||||
$(container).attr('title', i18next.t('map.opacity-slider'));
|
||||
|
||||
input.slider({
|
||||
min: 0,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ BR.RoutingOptions = L.Evented.extend({
|
|||
for (var i = 0; i < profiles.length; i++) {
|
||||
var option = document.createElement("option");
|
||||
option.value = profiles[i];
|
||||
option.text = profiles[i];
|
||||
option.text = i18next.t("navbar.profile." + profiles[i]);
|
||||
profiles_list.appendChild(option);
|
||||
}
|
||||
// set default value, used as indicator for empty custom profile
|
||||
|
|
|
|||
44
js/index.js
44
js/index.js
|
|
@ -59,7 +59,7 @@
|
|||
routing.draw(false);
|
||||
control.state('activate-draw');
|
||||
},
|
||||
title: 'Stop drawing route (ESC key)'
|
||||
title: i18next.t('map.draw-route-stop')
|
||||
}, {
|
||||
stateName: 'activate-draw',
|
||||
icon: 'fa-pencil',
|
||||
|
|
@ -67,7 +67,7 @@
|
|||
routing.draw(true);
|
||||
control.state('deactivate-draw');
|
||||
},
|
||||
title: 'Draw route (D key)'
|
||||
title: i18next.t('map.draw-route-start')
|
||||
}]
|
||||
});
|
||||
|
||||
|
|
@ -76,11 +76,11 @@
|
|||
function () {
|
||||
bootbox.prompt({
|
||||
size: 'small',
|
||||
title: "Delete route?",
|
||||
title: i18next.t('map.delete-route'),
|
||||
inputType: 'checkbox',
|
||||
inputOptions: [
|
||||
{
|
||||
text: ' also delete all no-go areas',
|
||||
text: i18next.t('map.delete-nogo-areas'),
|
||||
value: 'nogo'
|
||||
}
|
||||
],
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
}
|
||||
});
|
||||
},
|
||||
'Clear route'
|
||||
i18next.t('map.clear-route')
|
||||
);
|
||||
|
||||
function updateRoute(evt) {
|
||||
|
|
@ -122,6 +122,11 @@
|
|||
profile.update(evt.options);
|
||||
});
|
||||
|
||||
BR.NogoAreas.MSG_BUTTON = i18next.t("map.nogo.draw");
|
||||
BR.NogoAreas.MSG_BUTTON_CANCEL = i18next.t("map.nogo.cancel");
|
||||
BR.NogoAreas.MSG_CREATE = i18next.t("map.nogo.click-drag");
|
||||
BR.NogoAreas.MSG_DISABLED = i18next.t("map.nogo.edit");
|
||||
BR.NogoAreas.MSG_ENABLED = i18next.t("map.nogo.help");
|
||||
nogos = new BR.NogoAreas();
|
||||
nogos.on('update', updateRoute);
|
||||
|
||||
|
|
@ -145,8 +150,7 @@
|
|||
options: routingOptions.getOptions()
|
||||
});
|
||||
if (!saveWarningShown) {
|
||||
profile.message.showWarning('<strong>Note:</strong> Uploaded custom profiles are only cached temporarily on the server.'
|
||||
+ '<br/>Please save your edits to your local PC.');
|
||||
profile.message.showWarning(i18next.t('warning.temporary-profile'));
|
||||
saveWarningShown = true;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -241,12 +245,14 @@
|
|||
nogos.preventRoutePointOnCreate(routing);
|
||||
|
||||
if (BR.keys.strava) {
|
||||
const stravaControl = new L.Control.StravaSegments(
|
||||
{
|
||||
const stravaControl = L.control.stravaSegments({
|
||||
runningTitle: i18next.t('map.strava-running'),
|
||||
bikingTitle: i18next.t('map.strava-biking'),
|
||||
loadingTitle: i18next.t('map.loading'),
|
||||
stravaToken: BR.keys.strava
|
||||
})
|
||||
.addTo(map);
|
||||
layersControl.addOverlay(stravaControl.stravaLayer, "Strava segments");
|
||||
layersControl.addOverlay(stravaControl.stravaLayer, i18next.t('map.layer.strava-segments'));
|
||||
}
|
||||
|
||||
map.addControl(new BR.OpacitySlider({
|
||||
|
|
@ -352,8 +358,20 @@
|
|||
});
|
||||
}
|
||||
|
||||
mapContext = BR.Map.initMap();
|
||||
verifyTouchStyle(mapContext);
|
||||
initApp(mapContext);
|
||||
i18next
|
||||
.use(window.i18nextXHRBackend)
|
||||
.use(window.i18nextBrowserLanguageDetector)
|
||||
.init({
|
||||
fallbackLng: 'en',
|
||||
backend: {
|
||||
loadPath: 'locales/{{lng}}.json',
|
||||
}
|
||||
}, function(err, t) {
|
||||
jqueryI18next.init(i18next, $);
|
||||
$('html').localize();
|
||||
|
||||
mapContext = BR.Map.initMap();
|
||||
verifyTouchStyle(mapContext);
|
||||
initApp(mapContext);
|
||||
});
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ L.BRouter = L.Class.extend({
|
|||
xhr = new XMLHttpRequest();
|
||||
|
||||
if (!url) {
|
||||
return cb(new Error('Error getting route URL'));
|
||||
return cb(new Error(i18next.t('warning.cannot-get-route')));
|
||||
}
|
||||
|
||||
xhr.open('GET', url, true);
|
||||
|
|
@ -179,7 +179,7 @@ L.BRouter = L.Class.extend({
|
|||
xhr.onload = L.bind(this._handleProfileResponse, this, xhr, cb);
|
||||
xhr.onerror = function(evt) {
|
||||
var xhr = this;
|
||||
cb('Upload error: ' + xhr.statusText);
|
||||
cb(i18next.t('warning.upload-error', {error: xhr.statusText}));
|
||||
};
|
||||
|
||||
// send profile text only, as text/plain;charset=UTF-8
|
||||
|
|
@ -193,7 +193,7 @@ L.BRouter = L.Class.extend({
|
|||
response = JSON.parse(xhr.responseText);
|
||||
cb(response.error, response.profileid);
|
||||
} else {
|
||||
cb('Profile error: no or empty response from server');
|
||||
cb(i18next.t('warning.profile-error'));
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue