Compare commits

...

10 commits

Author SHA1 Message Date
Thomas Brockmöller
d69a38f1b6 add overpass query for railway station
Some checks are pending
build / build (push) Waiting to run
2024-10-22 10:48:16 +02:00
Marcus Jaschen
59a14356f7 use i18next interpolation instead of concatenating strings 2024-10-21 20:32:29 +02:00
Marcus Jaschen
8c21a88b15 update JSDoc
add hyphens between parameter name and description
2024-10-21 20:32:29 +02:00
Marcus Jaschen
a285751416 Add “Maximum Speed” to analysis sidebar
It shows the distribution of maximum speeds for all ways on the
current route (if that data is available, otherwise it’s summed up
under “unknown”).

`maxspeed:forward` and `maxspeed:backward` is respected in conjunction
with `reversedirection`.

Hovering/clicking table rows to highlight matching segments on the
route work the identical to the other analysis tables.

Additionally, all tags in the analysis tab (way type, surface,
smoothness) are translateable now. The values were added to `en.json`.

Some HTML is rendered with template literals now, instead of
concatenating strings.

Variable declarations were changed from `var` to `const`/`let`.
2024-10-21 20:32:29 +02:00
Simon Legner
76f31aeb2b refact: use shorthand method and property syntax 2024-10-19 13:44:15 +02:00
Marcus Jaschen
babd154596 allow additional GeoJSON MIME type
The MIME type for GeoJSON registered with IANA is application/geo+json`,
replacing the old value `application/vnd.geo+json`. The change was
published with RFC 7946 in 2016.

BRouter reponses changed to `application/geo+json` in recent versions.

With this commit BRouter-Web accepts either of both MIME type strings in
BRouter responses.
2024-10-14 20:30:53 +02:00
Marcus Jaschen
6b24a8790e add 'break' to switch to prevent fall-through 2024-07-02 18:23:19 +02:00
renovate[bot]
67547f3494 Update dependency @maplibre/maplibre-gl-leaflet to v0.0.20 2024-06-01 16:32:14 +02:00
alexcojocaru
12dc322a54 Disable gradient normalization in profile; add legend 2024-06-01 16:30:36 +02:00
alexcojocaru
135340781d Update the geo-data-exchange dependency with support for gradient normalization 2024-06-01 16:30:36 +02:00
50 changed files with 959 additions and 656 deletions

View file

@ -350,10 +350,6 @@ table.dataTable.track-analysis-table tfoot td {
padding-top: 4px; padding-top: 4px;
} }
.track-analysis-title {
text-transform: capitalize;
}
.track-analysis-distance { .track-analysis-distance {
text-align: right; text-align: right;
} }
@ -970,12 +966,8 @@ table.dataTable.display tbody tr:hover.selected {
/* /*
* Heightgraph customizations; * Heightgraph customizations;
* since the legend and the gradient types are in the way, hide them;
* since there's only the gradient layer, hide the layer selector. * since there's only the gradient layer, hide the layer selector.
*/ */
.legend-hover {
display: none;
}
#selectionText { #selectionText {
display: none; display: none;
} }

View file

@ -19,9 +19,9 @@
touch = touchScreenDetectable ? touchScreen : L.Browser.touch; touch = touchScreenDetectable ? touchScreen : L.Browser.touch;
BR.Browser = { BR.Browser = {
touchScreen: touchScreen, touchScreen,
touchScreenDetectable: touchScreenDetectable, touchScreenDetectable,
touch: touch, touch,
download: download:
'Blob' in window && 'Blob' in window &&
'FileReader' in window && 'FileReader' in window &&

View file

@ -6,7 +6,7 @@ BR.LayersConfig = L.Class.extend({
// hardcoded, built-in layers with an id set (for URL hash) // hardcoded, built-in layers with an id set (for URL hash)
builtInLayers: ['route-quality'], builtInLayers: ['route-quality'],
initialize: function (map) { initialize(map) {
this._map = map; this._map = map;
this._overpassLoadingIndicator = new BR.Message('overpass_loading_indicator', { alert: false }); this._overpassLoadingIndicator = new BR.Message('overpass_loading_indicator', { alert: false });
this._overpassActiveRequestCount = 0; this._overpassActiveRequestCount = 0;
@ -17,7 +17,7 @@ BR.LayersConfig = L.Class.extend({
this._addLanguageDefaultLayer(); this._addLanguageDefaultLayer();
}, },
loadDefaultLayers: function () { loadDefaultLayers() {
if (BR.Util.localStorageAvailable()) { if (BR.Util.localStorageAvailable()) {
var item = localStorage.getItem('map/defaultLayers'); var item = localStorage.getItem('map/defaultLayers');
if (item) { if (item) {
@ -28,21 +28,21 @@ BR.LayersConfig = L.Class.extend({
} }
}, },
storeDefaultLayers: function (baseLayers, overlays) { storeDefaultLayers(baseLayers, overlays) {
if (BR.Util.localStorageAvailable()) { if (BR.Util.localStorageAvailable()) {
var defaultLayers = { var defaultLayers = {
baseLayers: baseLayers, baseLayers,
overlays: overlays, overlays,
}; };
localStorage.setItem('map/defaultLayers', JSON.stringify(defaultLayers)); localStorage.setItem('map/defaultLayers', JSON.stringify(defaultLayers));
} }
}, },
_replaceLegacyIds: function (idList) { _replaceLegacyIds(idList) {
return idList.map((id) => (id in this.legacyNameToIdMap ? this.legacyNameToIdMap[id] : id)); return idList.map((id) => (id in this.legacyNameToIdMap ? this.legacyNameToIdMap[id] : id));
}, },
_addLeafletProvidersLayers: function () { _addLeafletProvidersLayers() {
var includeList = BR.confLayers.leafletProvidersIncludeList; var includeList = BR.confLayers.leafletProvidersIncludeList;
for (var i = 0; i < includeList.length; i++) { for (var i = 0; i < includeList.length; i++) {
@ -50,7 +50,7 @@ BR.LayersConfig = L.Class.extend({
var obj = { var obj = {
geometry: null, geometry: null,
properties: { properties: {
id: id, id,
name: id.replace('.', ' '), name: id.replace('.', ' '),
dataSource: 'leaflet-providers', dataSource: 'leaflet-providers',
}, },
@ -60,7 +60,7 @@ BR.LayersConfig = L.Class.extend({
} }
}, },
_customizeLayers: function () { _customizeLayers() {
var propertyOverrides = BR.confLayers.getPropertyOverrides(); var propertyOverrides = BR.confLayers.getPropertyOverrides();
for (var id in propertyOverrides) { for (var id in propertyOverrides) {
@ -92,7 +92,7 @@ BR.LayersConfig = L.Class.extend({
BR.layerIndex['ignf-scan25'].geometry = BR.confLayers.franceBbox; BR.layerIndex['ignf-scan25'].geometry = BR.confLayers.franceBbox;
}, },
_addLanguageDefaultLayer: function () { _addLanguageDefaultLayer() {
// language code -> layer id // language code -> layer id
var languageLayersMap = {}; var languageLayersMap = {};
var i; var i;
@ -120,7 +120,7 @@ BR.LayersConfig = L.Class.extend({
} }
}, },
isDefaultLayer: function (id, overlay) { isDefaultLayer(id, overlay) {
var result = false; var result = false;
if (overlay) { if (overlay) {
result = this.defaultOverlays.indexOf(id) > -1; result = this.defaultOverlays.indexOf(id) > -1;
@ -130,15 +130,15 @@ BR.LayersConfig = L.Class.extend({
return result; return result;
}, },
getBaseLayers: function () { getBaseLayers() {
return this._getLayers(this.defaultBaseLayers); return this._getLayers(this.defaultBaseLayers);
}, },
getOverlays: function () { getOverlays() {
return this._getLayers(this.defaultOverlays); return this._getLayers(this.defaultOverlays);
}, },
_getLayers: function (ids) { _getLayers(ids) {
var layers = {}; var layers = {};
for (var i = 0; i < ids.length; i++) { for (var i = 0; i < ids.length; i++) {
@ -161,7 +161,7 @@ BR.LayersConfig = L.Class.extend({
// own convention: key placeholder with prefix // own convention: key placeholder with prefix
// e.g. ?api_key={keys_openrouteservice} // e.g. ?api_key={keys_openrouteservice}
getKeyName: function (url) { getKeyName(url) {
var result = null; var result = null;
// L.Util.template only matches [\w_-] // L.Util.template only matches [\w_-]
var prefix = 'keys_'; var prefix = 'keys_';
@ -174,7 +174,7 @@ BR.LayersConfig = L.Class.extend({
if (found) { if (found) {
name = found[1]; name = found[1];
result = { result = {
name: name, name,
urlVar: prefix + name, urlVar: prefix + name,
}; };
} }
@ -182,18 +182,18 @@ BR.LayersConfig = L.Class.extend({
return result; return result;
}, },
_showOverpassLoadingIndicator: function () { _showOverpassLoadingIndicator() {
this._overpassActiveRequestCount++; this._overpassActiveRequestCount++;
this._overpassLoadingIndicator.showLoading(i18next.t('layers.overpass-loading-indicator')); this._overpassLoadingIndicator.showLoading(i18next.t('layers.overpass-loading-indicator'));
}, },
_hideOverpassLoadingIndicator: function () { _hideOverpassLoadingIndicator() {
if (--this._overpassActiveRequestCount === 0) { if (--this._overpassActiveRequestCount === 0) {
this._overpassLoadingIndicator.hide(); this._overpassLoadingIndicator.hide();
} }
}, },
getOverpassIconUrl: function (icon) { getOverpassIconUrl(icon) {
const iconPrefix = /^(maki|temaki|fas)-/; const iconPrefix = /^(maki|temaki|fas)-/;
let iconUrl = null; let iconUrl = null;
@ -205,7 +205,7 @@ BR.LayersConfig = L.Class.extend({
return iconUrl; return iconUrl;
}, },
createOverpassLayer: function (query, icon) { createOverpassLayer(query, icon) {
let markerSign = '<i class="fa fa-search icon-white" style="width: 25px;"></i>'; let markerSign = '<i class="fa fa-search icon-white" style="width: 25px;"></i>';
const iconUrl = this.getOverpassIconUrl(icon); const iconUrl = this.getOverpassIconUrl(icon);
@ -216,7 +216,7 @@ BR.LayersConfig = L.Class.extend({
return Object.assign( return Object.assign(
new OverpassLayer({ new OverpassLayer({
overpassFrontend: this.overpassFrontend, overpassFrontend: this.overpassFrontend,
query: query, query,
minZoom: 12, minZoom: 12,
feature: { feature: {
title: '{{ tags.name }}', title: '{{ tags.name }}',
@ -244,7 +244,7 @@ BR.LayersConfig = L.Class.extend({
); );
}, },
renderOverpassPopupBody: function (overpassData) { renderOverpassPopupBody(overpassData) {
let output = ''; let output = '';
output += '<table class="overpass-tags">'; output += '<table class="overpass-tags">';
@ -301,11 +301,11 @@ BR.LayersConfig = L.Class.extend({
return output; return output;
}, },
createOpenStreetMapNotesLayer: function () { createOpenStreetMapNotesLayer() {
return new leafletOsmNotes(); return new leafletOsmNotes();
}, },
createMvtLayer: function (props, options) { createMvtLayer(props, options) {
// remove key, only provided with local style to not add layer when not configured, see _getLayers // remove key, only provided with local style to not add layer when not configured, see _getLayers
const styleId = props.url?.split('?')[0]; const styleId = props.url?.split('?')[0];
if (styleId in BR.layerIndex) { if (styleId in BR.layerIndex) {
@ -322,7 +322,7 @@ BR.LayersConfig = L.Class.extend({
return BR.maplibreGlLazyLoader(options); return BR.maplibreGlLazyLoader(options);
}, },
_replaceMvtTileKey: function (style) { _replaceMvtTileKey(style) {
if (!style) return; if (!style) return;
// Sources can be specified by `url` (string) or `tiles` (array), we handle // Sources can be specified by `url` (string) or `tiles` (array), we handle
@ -348,7 +348,7 @@ BR.LayersConfig = L.Class.extend({
} }
}, },
createGeoJsonLayer: function (props) { createGeoJsonLayer(props) {
const layer = L.geoJSON(undefined, BR.Track.getGeoJsonOptions()); const layer = L.geoJSON(undefined, BR.Track.getGeoJsonOptions());
fetch(props.url).then(async (response) => { fetch(props.url).then(async (response) => {
const geojson = await response.json(); const geojson = await response.json();
@ -357,7 +357,7 @@ BR.LayersConfig = L.Class.extend({
return layer; return layer;
}, },
createLayer: function (layerData) { createLayer(layerData) {
var props = layerData.properties; var props = layerData.properties;
var url = props.url; var url = props.url;
var layer; var layer;

View file

@ -1,5 +1,5 @@
BR.Map = { BR.Map = {
initMap: function () { initMap() {
var map, layersControl; var map, layersControl;
L.setOptions(this, { L.setOptions(this, {
@ -20,7 +20,7 @@ BR.Map = {
zoomControl: false, // add it manually so that we can translate it zoomControl: false, // add it manually so that we can translate it
worldCopyJump: true, worldCopyJump: true,
minZoom: 0, minZoom: 0,
maxZoom: maxZoom, maxZoom,
}); });
if (BR.Util.getResponsiveBreakpoint() >= '3md') { if (BR.Util.getResponsiveBreakpoint() >= '3md') {
@ -142,12 +142,12 @@ BR.Map = {
BR.debug.map = map; BR.debug.map = map;
return { return {
map: map, map,
layersControl: layersControl, layersControl,
}; };
}, },
_renderLayerCredits: function (layers) { _renderLayerCredits(layers) {
var dl = document.getElementById('credits-maps'); var dl = document.getElementById('credits-maps');
var i, obj, dt, dd, attribution; var i, obj, dt, dd, attribution;

View file

@ -1,5 +1,5 @@
BR.Util = { BR.Util = {
get: function (url, cb) { get(url, cb) {
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
xhr.open('GET', url, true); xhr.open('GET', url, true);
@ -20,7 +20,7 @@ BR.Util = {
} }
}, },
getError: function (xhr) { getError(xhr) {
var msg = i18next.t('warning.no-response'); var msg = i18next.t('warning.no-response');
if (xhr.responseText) { if (xhr.responseText) {
msg = xhr.responseText; msg = xhr.responseText;
@ -30,7 +30,7 @@ BR.Util = {
return new Error(msg); return new Error(msg);
}, },
getJson: function (url, context, cb) { getJson(url, context, cb) {
BR.Util.get(url, function (err, data) { BR.Util.get(url, function (err, data) {
if (err) { if (err) {
BR.message.showError('Error getting ' + context + ': ' + err); BR.message.showError('Error getting ' + context + ': ' + err);
@ -48,7 +48,7 @@ BR.Util = {
}); });
}, },
getGeoJson: function (url, context, cb) { getGeoJson(url, context, cb) {
BR.Util.getJson(url, context, function (err, data) { BR.Util.getJson(url, context, function (err, data) {
if (err) return cb(err); if (err) return cb(err);
@ -70,7 +70,7 @@ BR.Util = {
// https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#Testing_for_support_vs_availability // https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#Testing_for_support_vs_availability
// by Mozilla Contributors, with modifications; // by Mozilla Contributors, with modifications;
// Any copyright is dedicated to the Public Domain. https://creativecommons.org/publicdomain/zero/1.0/ // Any copyright is dedicated to the Public Domain. https://creativecommons.org/publicdomain/zero/1.0/
localStorageAvailable: function () { localStorageAvailable() {
try { try {
var storage = window.localStorage, var storage = window.localStorage,
x = '__storage_test__'; x = '__storage_test__';
@ -83,7 +83,7 @@ BR.Util = {
}, },
// see https://stackoverflow.com/a/37141090/1906123 // see https://stackoverflow.com/a/37141090/1906123
getResponsiveBreakpoint: function () { getResponsiveBreakpoint() {
var envs = { '1xs': 'd-none', '2sm': 'd-sm-none', '3md': 'd-md-none', '4lg': 'd-lg-none', '5xl': 'd-xl-none' }; var envs = { '1xs': 'd-none', '2sm': 'd-sm-none', '3md': 'd-md-none', '4lg': 'd-lg-none', '5xl': 'd-xl-none' };
var env = ''; var env = '';
@ -101,7 +101,7 @@ BR.Util = {
return env; return env;
}, },
keyboardShortcutsAllowed: function (keyEvent) { keyboardShortcutsAllowed(keyEvent) {
// Skip auto-repeating key events // Skip auto-repeating key events
if (keyEvent.repeat) { if (keyEvent.repeat) {
return false; return false;
@ -134,13 +134,13 @@ BR.Util = {
// this method must only be used to sanitize for textContent. // this method must only be used to sanitize for textContent.
// do NOT use it to sanitize any attribute, // do NOT use it to sanitize any attribute,
// see https://web.archive.org/web/20121208091505/http://benv.ca/2012/10/4/you-are-probably-misusing-DOM-text-methods/ // see https://web.archive.org/web/20121208091505/http://benv.ca/2012/10/4/you-are-probably-misusing-DOM-text-methods/
sanitizeHTMLContent: function (str) { sanitizeHTMLContent(str) {
var temp = document.createElement('div'); var temp = document.createElement('div');
temp.textContent = str; temp.textContent = str;
return temp.innerHTML; return temp.innerHTML;
}, },
isCountry: function (country, language) { isCountry(country, language) {
// de-DE | fr-FR // de-DE | fr-FR
var lang = i18next.languages[0].split('-'); var lang = i18next.languages[0].split('-');

View file

@ -1,10 +1,10 @@
BR.WhatsNew = { BR.WhatsNew = {
newOnly: undefined, newOnly: undefined,
init: function () { init() {
var self = this; var self = this;
self.dismissableMessage = new BR.Message('whats_new_message', { self.dismissableMessage = new BR.Message('whats_new_message', {
onClosed: function () { onClosed() {
document.getElementsByClassName('version')[0].classList.remove('version-new'); document.getElementsByClassName('version')[0].classList.remove('version-new');
if (BR.Util.localStorageAvailable()) { if (BR.Util.localStorageAvailable()) {
localStorage.setItem('changelogVersion', self.getLatestVersion()); localStorage.setItem('changelogVersion', self.getLatestVersion());
@ -29,21 +29,21 @@ BR.WhatsNew = {
} }
}, },
getLatestVersion: function () { getLatestVersion() {
return BR.changelog.match('<h2 id="(.*)">')[1]; return BR.changelog.match('<h2 id="(.*)">')[1];
}, },
getCurrentVersion: function () { getCurrentVersion() {
if (!BR.Util.localStorageAvailable()) return null; if (!BR.Util.localStorageAvailable()) return null;
return localStorage.getItem('changelogVersion'); return localStorage.getItem('changelogVersion');
}, },
hasNewVersions: function () { hasNewVersions() {
return this.getCurrentVersion() && this.getCurrentVersion() !== this.getLatestVersion(); return this.getCurrentVersion() && this.getCurrentVersion() !== this.getLatestVersion();
}, },
prepare: function (newOnly) { prepare(newOnly) {
if (newOnly === this.newOnly) { if (newOnly === this.newOnly) {
// do not rebuild modal content unnecessarily // do not rebuild modal content unnecessarily
return; return;

View file

@ -1,5 +1,5 @@
BR.ControlLayers = L.Control.Layers.extend({ BR.ControlLayers = L.Control.Layers.extend({
getActiveLayers: function () { getActiveLayers() {
var result = []; var result = [];
for (var i = 0; i < this._layers.length; i++) { for (var i = 0; i < this._layers.length; i++) {
@ -16,7 +16,7 @@ BR.ControlLayers = L.Control.Layers.extend({
return result; return result;
}, },
getActiveBaseLayer: function () { getActiveBaseLayer() {
var activeLayers = this.getActiveLayers(); var activeLayers = this.getActiveLayers();
for (var i = 0; i < activeLayers.length; i++) { for (var i = 0; i < activeLayers.length; i++) {
var obj = activeLayers[i]; var obj = activeLayers[i];
@ -28,7 +28,7 @@ BR.ControlLayers = L.Control.Layers.extend({
return null; return null;
}, },
removeActiveLayers: function () { removeActiveLayers() {
var removed = []; var removed = [];
for (var i = 0; i < this._layers.length; i++) { for (var i = 0; i < this._layers.length; i++) {
@ -42,7 +42,7 @@ BR.ControlLayers = L.Control.Layers.extend({
return removed; return removed;
}, },
getLayer: function (name) { getLayer(name) {
for (var i = 0; i < this._layers.length; i++) { for (var i = 0; i < this._layers.length; i++) {
var obj = this._layers[i]; var obj = this._layers[i];
if (obj.name === name) { if (obj.name === name) {
@ -53,19 +53,19 @@ BR.ControlLayers = L.Control.Layers.extend({
return null; return null;
}, },
getBaseLayers: function () { getBaseLayers() {
return this._layers.filter(function (obj) { return this._layers.filter(function (obj) {
return !obj.overlay; return !obj.overlay;
}); });
}, },
activateLayer: function (obj) { activateLayer(obj) {
if (!this._map.hasLayer(obj.layer)) { if (!this._map.hasLayer(obj.layer)) {
this._map.addLayer(obj.layer); this._map.addLayer(obj.layer);
} }
}, },
activateFirstLayer: function () { activateFirstLayer() {
for (var i = 0; i < this._layers.length; i++) { for (var i = 0; i < this._layers.length; i++) {
var obj = this._layers[i]; var obj = this._layers[i];
if (!obj.overlay) { if (!obj.overlay) {
@ -75,14 +75,14 @@ BR.ControlLayers = L.Control.Layers.extend({
} }
}, },
activateBaseLayerIndex: function (index) { activateBaseLayerIndex(index) {
var baseLayers = this.getBaseLayers(); var baseLayers = this.getBaseLayers();
var obj = baseLayers[index]; var obj = baseLayers[index];
this.activateLayer(obj); this.activateLayer(obj);
}, },
_addLayer: function (layer, name, overlay) { _addLayer(layer, name, overlay) {
L.Control.Layers.prototype._addLayer.call(this, layer, name, overlay); L.Control.Layers.prototype._addLayer.call(this, layer, name, overlay);
// override z-index assignment to fix that base layers added later // override z-index assignment to fix that base layers added later

View file

@ -7,7 +7,7 @@ BR.Export = L.Class.extend({
}, },
}, },
initialize: function (router, pois, profile) { initialize(router, pois, profile) {
this.router = router; this.router = router;
this.pois = pois; this.pois = pois;
this.profile = profile; this.profile = profile;
@ -38,7 +38,7 @@ BR.Export = L.Class.extend({
this.update([]); this.update([]);
}, },
update: function (latLngs, segments) { update(latLngs, segments) {
this.latLngs = latLngs; this.latLngs = latLngs;
this.segments = segments; this.segments = segments;
@ -49,7 +49,7 @@ BR.Export = L.Class.extend({
} }
}, },
_warnDownload: function () { _warnDownload() {
const hasBeeline = BR.Routing.hasBeeline(this.segments); const hasBeeline = BR.Routing.hasBeeline(this.segments);
const isFit = $('#format-fit').prop('checked'); const isFit = $('#format-fit').prop('checked');
$('#export-download-warning').prop('hidden', !hasBeeline && !isFit); $('#export-download-warning').prop('hidden', !hasBeeline && !isFit);
@ -63,14 +63,14 @@ BR.Export = L.Class.extend({
document.getElementById('serverExport').title = title; document.getElementById('serverExport').title = title;
}, },
_turnInstructionInfo: function () { _turnInstructionInfo() {
const turnInstructionMode = +this.profile.getProfileVar('turnInstructionMode'); const turnInstructionMode = +this.profile.getProfileVar('turnInstructionMode');
$('.format-turns-enabled') $('.format-turns-enabled')
.prop('hidden', turnInstructionMode <= 1) .prop('hidden', turnInstructionMode <= 1)
.attr('title', i18next.t('export.turns_enabled')); .attr('title', i18next.t('export.turns_enabled'));
}, },
_getMimeType: function (format) { _getMimeType(format) {
const mimeTypeMap = { const mimeTypeMap = {
gpx: 'application/gpx+xml;charset=utf-8', gpx: 'application/gpx+xml;charset=utf-8',
kml: 'application/vnd.google-earth.kml+xml;charset=utf-8', kml: 'application/vnd.google-earth.kml+xml;charset=utf-8',
@ -82,7 +82,7 @@ BR.Export = L.Class.extend({
return mimeTypeMap[format]; return mimeTypeMap[format];
}, },
_triggerDownload: function (url, name) { _triggerDownload(url, name) {
const link = document.createElement('a'); const link = document.createElement('a');
link.href = url; link.href = url;
if (name) { if (name) {
@ -95,11 +95,11 @@ BR.Export = L.Class.extend({
link.remove(); link.remove();
}, },
_exportServer: function (e) { _exportServer(e) {
this._export(e, true); this._export(e, true);
}, },
_export: function (e, server = false) { _export(e, server = false) {
var exportForm = document.forms['export']; var exportForm = document.forms['export'];
var format = exportForm['format'].value || $('#export-format input:radio:checked').val(); var format = exportForm['format'].value || $('#export-format input:radio:checked').val();
var name = exportForm['trackname'].value; var name = exportForm['trackname'].value;
@ -138,7 +138,7 @@ BR.Export = L.Class.extend({
} }
}, },
_formatTrack: function (format, name, includeWaypoints) { _formatTrack(format, name, includeWaypoints) {
const track = BR.Export._concatTotalTrack(this.segments); const track = BR.Export._concatTotalTrack(this.segments);
if (name) { if (name) {
track.features[0].properties.name = name; track.features[0].properties.name = name;
@ -166,7 +166,7 @@ BR.Export = L.Class.extend({
console.error('Export format not implemented: ' + format); console.error('Export format not implemented: ' + format);
}, },
_addPois: function (track) { _addPois(track) {
const markers = this.pois.getMarkers(); const markers = this.pois.getMarkers();
for (const poi of markers) { for (const poi of markers) {
const properties = { name: poi.name, type: 'poi' }; const properties = { name: poi.name, type: 'poi' };
@ -175,7 +175,7 @@ BR.Export = L.Class.extend({
} }
}, },
_addRouteWaypoints: function (track) { _addRouteWaypoints(track) {
for (const [i, latLng] of this.latLngs.entries()) { for (const [i, latLng] of this.latLngs.entries()) {
let name = 'via' + i; let name = 'via' + i;
let type = 'via'; let type = 'via';
@ -192,7 +192,7 @@ BR.Export = L.Class.extend({
} }
}, },
_validationMessage: function () { _validationMessage() {
var trackname = this.trackname; var trackname = this.trackname;
var replaceRegex = new RegExp('[^' + this.tracknameAllowedChars + ']', 'g'); var replaceRegex = new RegExp('[^' + this.tracknameAllowedChars + ']', 'g');
@ -205,11 +205,11 @@ BR.Export = L.Class.extend({
} }
}, },
_selectTrackname: function () { _selectTrackname() {
trackname.setSelectionRange(0, trackname.value.lastIndexOf(BR.Browser.download ? ' (' : ' - ')); trackname.setSelectionRange(0, trackname.value.lastIndexOf(BR.Browser.download ? ' (' : ' - '));
}, },
_generateTrackname: function () { _generateTrackname() {
var trackname = this.trackname; var trackname = this.trackname;
this._getCityAtPosition( this._getCityAtPosition(
this.latLngs[0], this.latLngs[0],
@ -225,14 +225,14 @@ BR.Export = L.Class.extend({
trackname.value = null; trackname.value = null;
} else if (from === to) { } else if (from === to) {
trackname.value = i18next.t('export.route-loop', { trackname.value = i18next.t('export.route-loop', {
from: from, from,
distance: distance, distance,
}); });
} else { } else {
trackname.value = i18next.t('export.route-from-to', { trackname.value = i18next.t('export.route-from-to', {
from: from, from,
to: to, to,
distance: distance, distance,
}); });
} }
@ -249,7 +249,7 @@ BR.Export = L.Class.extend({
); );
}, },
_getCityAtPosition: function (lonlat, cb) { _getCityAtPosition(lonlat, cb) {
var url = L.Util.template( var url = L.Util.template(
'https://nominatim.openstreetmap.org/reverse?lon={lng}&lat={lat}&format=json', 'https://nominatim.openstreetmap.org/reverse?lon={lng}&lat={lat}&format=json',
lonlat lonlat
@ -268,7 +268,7 @@ BR.Export = L.Class.extend({
); );
}, },
_keydownListener: function (e) { _keydownListener(e) {
if ( if (
BR.Util.keyboardShortcutsAllowed(e) && BR.Util.keyboardShortcutsAllowed(e) &&
e.keyCode === this.options.shortcut.export && e.keyCode === this.options.shortcut.export &&

View file

@ -1,10 +1,10 @@
BR.Itinerary = L.Class.extend({ BR.Itinerary = L.Class.extend({
initialize: function () { initialize() {
this._content = document.getElementById('itinerary'); this._content = document.getElementById('itinerary');
this.update(); this.update();
}, },
update: function (polyline, segments) { update(polyline, segments) {
var i, var i,
j, j,
iter, iter,

View file

@ -1,5 +1,5 @@
BR.Layers = L.Class.extend({ BR.Layers = L.Class.extend({
_loadLayers: function () { _loadLayers() {
this._customLayers = {}; this._customLayers = {};
if (BR.Util.localStorageAvailable()) { if (BR.Util.localStorageAvailable()) {
@ -28,7 +28,7 @@ BR.Layers = L.Class.extend({
} }
}, },
_loadTable: function () { _loadTable() {
var layersData = []; var layersData = [];
for (layer in this._customLayers) { for (layer in this._customLayers) {
var layerProps = this._customLayers[layer].layerData.properties; var layerProps = this._customLayers[layer].layerData.properties;
@ -65,7 +65,7 @@ BR.Layers = L.Class.extend({
}); });
}, },
init: function (map, layersControl, baseLayers, overlays) { init(map, layersControl, baseLayers, overlays) {
this._layersControl = layersControl; this._layersControl = layersControl;
this._map = map; this._map = map;
this._layers = {}; this._layers = {};
@ -95,7 +95,7 @@ BR.Layers = L.Class.extend({
}; };
}, },
_remove: function (evt) { _remove(evt) {
var row = this._layersTable.row('.selected').data(); var row = this._layersTable.row('.selected').data();
if (row != null) { if (row != null) {
var name = row[0]; var name = row[0];
@ -107,7 +107,7 @@ BR.Layers = L.Class.extend({
} }
}, },
_addFromInput: function (layerProps) { _addFromInput(layerProps) {
var layer_name = L.DomUtil.get('layer_name').value; var layer_name = L.DomUtil.get('layer_name').value;
var layer_url = L.DomUtil.get('layer_url').value; var layer_url = L.DomUtil.get('layer_url').value;
@ -123,14 +123,14 @@ BR.Layers = L.Class.extend({
if (layer_name.length > 0 && layer_url.length > 0) this._addLayer(layerData); if (layer_name.length > 0 && layer_url.length > 0) this._addLayer(layerData);
}, },
_addBaseLayer: function (evt) { _addBaseLayer(evt) {
var layerProps = { var layerProps = {
type: 'tms', type: 'tms',
url: L.DomUtil.get('layer_url').value, url: L.DomUtil.get('layer_url').value,
}; };
this._addFromInput(layerProps); this._addFromInput(layerProps);
}, },
_addOverlay: function (evt) { _addOverlay(evt) {
var layerProps = { var layerProps = {
type: 'tms', type: 'tms',
url: L.DomUtil.get('layer_url').value, url: L.DomUtil.get('layer_url').value,
@ -138,7 +138,7 @@ BR.Layers = L.Class.extend({
}; };
this._addFromInput(layerProps); this._addFromInput(layerProps);
}, },
_addOverpassQuery: function (evt) { _addOverpassQuery(evt) {
var layerProps = { var layerProps = {
overlay: true, overlay: true,
dataSource: 'OverpassAPI', dataSource: 'OverpassAPI',
@ -147,7 +147,7 @@ BR.Layers = L.Class.extend({
this._addFromInput(layerProps); this._addFromInput(layerProps);
}, },
_createTmsProps: function (props) { _createTmsProps(props) {
var tmsProps = { var tmsProps = {
type: 'tms', type: 'tms',
...props, ...props,
@ -155,7 +155,7 @@ BR.Layers = L.Class.extend({
return tmsProps; return tmsProps;
}, },
_addLayer: function (layerData) { _addLayer(layerData) {
var props = layerData.properties; var props = layerData.properties;
var layerName = props.name; var layerName = props.name;
@ -167,8 +167,8 @@ BR.Layers = L.Class.extend({
var layer = this._layersControl.layersConfig.createLayer(layerData); var layer = this._layersControl.layersConfig.createLayer(layerData);
this._customLayers[layerName] = { this._customLayers[layerName] = {
layer: layer, layer,
layerData: layerData, layerData,
}; };
if (props.overlay) { if (props.overlay) {
@ -185,7 +185,7 @@ BR.Layers = L.Class.extend({
} }
}, },
_sync: function () { _sync() {
if (BR.Util.localStorageAvailable()) { if (BR.Util.localStorageAvailable()) {
var geojson = { var geojson = {
type: 'FeatureCollection', type: 'FeatureCollection',

View file

@ -3,13 +3,13 @@ BR.LayersTab = BR.ControlLayers.extend({
previewBounds: null, previewBounds: null,
saveLayers: [], saveLayers: [],
initialize: function (layersConfig, baseLayers, overlays, options) { initialize(layersConfig, baseLayers, overlays, options) {
L.Control.Layers.prototype.initialize.call(this, baseLayers, overlays, options); L.Control.Layers.prototype.initialize.call(this, baseLayers, overlays, options);
this.layersConfig = layersConfig; this.layersConfig = layersConfig;
}, },
addTo: function (map) { addTo(map) {
this._map = map; this._map = map;
this.onAdd(map); this.onAdd(map);
@ -22,21 +22,21 @@ BR.LayersTab = BR.ControlLayers.extend({
return this; return this;
}, },
onAdd: function (map) { onAdd(map) {
BR.ControlLayers.prototype.onAdd.call(this, map); BR.ControlLayers.prototype.onAdd.call(this, map);
map.on('baselayerchange overlayadd overlayremove', this.storeActiveLayers, this); map.on('baselayerchange overlayadd overlayremove', this.storeActiveLayers, this);
map.on('overlayadd overlayremove', this.updateOpacityLabel, this); map.on('overlayadd overlayremove', this.updateOpacityLabel, this);
}, },
onRemove: function (map) { onRemove(map) {
BR.ControlLayers.prototype.onRemove.call(this, map); BR.ControlLayers.prototype.onRemove.call(this, map);
map.off('baselayerchange overlayadd overlayremove', this.storeActiveLayers, this); map.off('baselayerchange overlayadd overlayremove', this.storeActiveLayers, this);
map.off('overlayadd overlayremove', this.updateOpacityLabel, this); map.off('overlayadd overlayremove', this.updateOpacityLabel, this);
}, },
initOpacitySlider: function (map) { initOpacitySlider(map) {
var self = this; var self = this;
var overlayOpacitySlider = new BR.OpacitySlider({ var overlayOpacitySlider = new BR.OpacitySlider({
id: 'overlay', id: 'overlay',
@ -44,7 +44,7 @@ BR.LayersTab = BR.ControlLayers.extend({
orientation: 'horizontal', orientation: 'horizontal',
defaultValue: 1, defaultValue: 1,
title: i18next.t('layers.opacity-slider'), title: i18next.t('layers.opacity-slider'),
callback: function (opacity) { callback(opacity) {
for (var i = 0; i < self._layers.length; i++) { for (var i = 0; i < self._layers.length; i++) {
const layer = self._layers[i].layer; const layer = self._layers[i].layer;
if (!self._layers[i].overlay || !map.hasLayer(layer)) { if (!self._layers[i].overlay || !map.hasLayer(layer)) {
@ -53,7 +53,7 @@ BR.LayersTab = BR.ControlLayers.extend({
if (layer.setOpacity) { if (layer.setOpacity) {
layer.setOpacity(opacity); layer.setOpacity(opacity);
} else if (layer.setStyle) { } else if (layer.setStyle) {
layer.setStyle({ opacity: opacity }); layer.setStyle({ opacity });
} }
} }
}, },
@ -61,7 +61,7 @@ BR.LayersTab = BR.ControlLayers.extend({
L.DomUtil.get('leaflet-control-layers-overlays-opacity-slider').appendChild(overlayOpacitySlider.getElement()); L.DomUtil.get('leaflet-control-layers-overlays-opacity-slider').appendChild(overlayOpacitySlider.getElement());
}, },
initButtons: function () { initButtons() {
var expandTree = function (e) { var expandTree = function (e) {
this.jstree.open_all(); this.jstree.open_all();
}; };
@ -89,7 +89,7 @@ BR.LayersTab = BR.ControlLayers.extend({
L.DomUtil.get('optional_layers_button').onclick = L.bind(toggleOptionalLayers, this); L.DomUtil.get('optional_layers_button').onclick = L.bind(toggleOptionalLayers, this);
}, },
initJsTree: function () { initJsTree() {
var layerIndex = BR.layerIndex; var layerIndex = BR.layerIndex;
var treeData = this.toJsTree(BR.confLayers.tree); var treeData = this.toJsTree(BR.confLayers.tree);
var oldSelected = null; var oldSelected = null;
@ -180,7 +180,7 @@ BR.LayersTab = BR.ControlLayers.extend({
this.jstree = $('#optional-layers-tree').jstree(true); this.jstree = $('#optional-layers-tree').jstree(true);
}, },
toJsTree: function (layerTree) { toJsTree(layerTree) {
var data = { var data = {
children: [], children: [],
}; };
@ -218,7 +218,7 @@ BR.LayersTab = BR.ControlLayers.extend({
// when key required only add if configured // when key required only add if configured
if (!keyObj || (keyObj && BR.keys[keyObj.name])) { if (!keyObj || (keyObj && BR.keys[keyObj.name])) {
childNode = { childNode = {
id: id, id,
text: getText(props, parent), text: getText(props, parent),
icon: self.layersConfig.getOverpassIconUrl(props.icon) || false, icon: self.layersConfig.getOverpassIconUrl(props.icon) || false,
state: { state: {
@ -262,12 +262,13 @@ BR.LayersTab = BR.ControlLayers.extend({
walkObject(inTree); walkObject(inTree);
} }
} }
walkTree(layerTree, data); walkTree(layerTree, data);
return data.children; return data.children;
}, },
storeDefaultLayers: function () { storeDefaultLayers() {
var baseLayers = []; var baseLayers = [];
var overlays = []; var overlays = [];
@ -289,7 +290,7 @@ BR.LayersTab = BR.ControlLayers.extend({
this.layersConfig.storeDefaultLayers(baseLayers, overlays); this.layersConfig.storeDefaultLayers(baseLayers, overlays);
}, },
createLayer: function (layerData) { createLayer(layerData) {
var layer = this.layersConfig.createLayer(layerData); var layer = this.layersConfig.createLayer(layerData);
var overlay = layerData.properties.overlay; var overlay = layerData.properties.overlay;
@ -299,7 +300,7 @@ BR.LayersTab = BR.ControlLayers.extend({
return layer; return layer;
}, },
getLayerById: function (id) { getLayerById(id) {
for (var i = 0; i < this._layers.length; i++) { for (var i = 0; i < this._layers.length; i++) {
var obj = this._layers[i]; var obj = this._layers[i];
if (obj.layer.id === id) { if (obj.layer.id === id) {
@ -310,7 +311,7 @@ BR.LayersTab = BR.ControlLayers.extend({
return null; return null;
}, },
getLayerByLegacyName: function (legacyName) { getLayerByLegacyName(legacyName) {
var obj = null; var obj = null;
var id = this.layersConfig.legacyNameToIdMap[legacyName]; var id = this.layersConfig.legacyNameToIdMap[legacyName];
@ -321,7 +322,7 @@ BR.LayersTab = BR.ControlLayers.extend({
return obj; return obj;
}, },
activateDefaultBaseLayer: function () { activateDefaultBaseLayer() {
var index = BR.conf.defaultBaseLayerIndex || 0; var index = BR.conf.defaultBaseLayerIndex || 0;
var activeBaseLayer = this.getActiveBaseLayer(); var activeBaseLayer = this.getActiveBaseLayer();
if (!activeBaseLayer) { if (!activeBaseLayer) {
@ -329,11 +330,11 @@ BR.LayersTab = BR.ControlLayers.extend({
} }
}, },
saveRemoveActiveLayers: function () { saveRemoveActiveLayers() {
this.saveLayers = this.removeActiveLayers(); this.saveLayers = this.removeActiveLayers();
}, },
restoreActiveLayers: function (overlaysOnly) { restoreActiveLayers(overlaysOnly) {
for (var i = 0; i < this.saveLayers.length; i++) { for (var i = 0; i < this.saveLayers.length; i++) {
var obj = this.saveLayers[i]; var obj = this.saveLayers[i];
@ -350,7 +351,7 @@ BR.LayersTab = BR.ControlLayers.extend({
this.saveLayers = []; this.saveLayers = [];
}, },
removePreviewLayer: function () { removePreviewLayer() {
if (this.previewLayer && this._map.hasLayer(this.previewLayer)) { if (this.previewLayer && this._map.hasLayer(this.previewLayer)) {
this._map.removeLayer(this.previewLayer); this._map.removeLayer(this.previewLayer);
this.previewLayer = null; this.previewLayer = null;
@ -359,7 +360,7 @@ BR.LayersTab = BR.ControlLayers.extend({
return false; return false;
}, },
showPreviewBounds: function (layerData) { showPreviewBounds(layerData) {
if (layerData.geometry) { if (layerData.geometry) {
this.previewBounds = L.geoJson(layerData.geometry, { this.previewBounds = L.geoJson(layerData.geometry, {
// fill/mask outside of bounds polygon with Leaflet.snogylop // fill/mask outside of bounds polygon with Leaflet.snogylop
@ -373,21 +374,21 @@ BR.LayersTab = BR.ControlLayers.extend({
} }
}, },
removePreviewBounds: function () { removePreviewBounds() {
if (this.previewBounds && this._map.hasLayer(this.previewBounds)) { if (this.previewBounds && this._map.hasLayer(this.previewBounds)) {
this._map.removeLayer(this.previewBounds); this._map.removeLayer(this.previewBounds);
this.previewBounds = null; this.previewBounds = null;
} }
}, },
deselectNode: function () { deselectNode() {
var selected = this.jstree.get_selected(); var selected = this.jstree.get_selected();
if (selected.length > 0) { if (selected.length > 0) {
this.jstree.deselect_node(selected[0]); this.jstree.deselect_node(selected[0]);
} }
}, },
onBaselayerchange: function () { onBaselayerchange() {
// execute after current input click handler, // execute after current input click handler,
// otherwise added overlay checkbox state doesn't update // otherwise added overlay checkbox state doesn't update
setTimeout( setTimeout(
@ -401,7 +402,7 @@ BR.LayersTab = BR.ControlLayers.extend({
); );
}, },
showPreview: function (layerData) { showPreview(layerData) {
var layer = this.createLayer(layerData); var layer = this.createLayer(layerData);
this._map.addLayer(layer); this._map.addLayer(layer);
this.removePreviewBounds(); this.removePreviewBounds();
@ -416,7 +417,7 @@ BR.LayersTab = BR.ControlLayers.extend({
L.DomUtil.get('preview').hidden = false; L.DomUtil.get('preview').hidden = false;
}, },
hidePreview: function (layer) { hidePreview(layer) {
this._map.off('baselayerchange', this.onBaselayerchange, this); this._map.off('baselayerchange', this.onBaselayerchange, this);
this.removePreviewBounds(); this.removePreviewBounds();
this.removePreviewLayer(); this.removePreviewLayer();
@ -425,11 +426,11 @@ BR.LayersTab = BR.ControlLayers.extend({
L.DomUtil.get('preview').hidden = true; L.DomUtil.get('preview').hidden = true;
}, },
toLayerString: function (obj) { toLayerString(obj) {
return obj.layer.id ? obj.layer.id : obj.name; return obj.layer.id ? obj.layer.id : obj.name;
}, },
getLayerFromString: function (layerString) { getLayerFromString(layerString) {
var obj = this.getLayerById(layerString); var obj = this.getLayerById(layerString);
if (!obj) { if (!obj) {
@ -445,7 +446,7 @@ BR.LayersTab = BR.ControlLayers.extend({
return obj; return obj;
}, },
storeActiveLayers: function () { storeActiveLayers() {
if (BR.Util.localStorageAvailable()) { if (BR.Util.localStorageAvailable()) {
var objList = this.getActiveLayers(); var objList = this.getActiveLayers();
var idList = objList.map( var idList = objList.map(
@ -459,7 +460,7 @@ BR.LayersTab = BR.ControlLayers.extend({
} }
}, },
loadActiveLayers: function () { loadActiveLayers() {
if (BR.Util.localStorageAvailable()) { if (BR.Util.localStorageAvailable()) {
var item = localStorage.getItem('map/activeLayers'); var item = localStorage.getItem('map/activeLayers');
@ -478,7 +479,7 @@ BR.LayersTab = BR.ControlLayers.extend({
} }
}, },
updateOpacityLabel: function () { updateOpacityLabel() {
var slider = $('#leaflet-control-layers-overlays-opacity-slider'); var slider = $('#leaflet-control-layers-overlays-opacity-slider');
var overlaysCount = this.getActiveLayers().length - 1; var overlaysCount = this.getActiveLayers().length - 1;
if (overlaysCount === 0) { if (overlaysCount === 0) {

View file

@ -6,12 +6,12 @@ BR.Message = L.Class.extend({
onClosed: null, onClosed: null,
}, },
initialize: function (id, options) { initialize(id, options) {
L.setOptions(this, options); L.setOptions(this, options);
this.id = id; this.id = id;
}, },
_show: function (msg, type) { _show(msg, type) {
var ele = L.DomUtil.get(this.id), var ele = L.DomUtil.get(this.id),
iconClass, iconClass,
alertClass; alertClass;
@ -59,11 +59,11 @@ BR.Message = L.Class.extend({
} }
}, },
hide: function () { hide() {
$('#' + this.id + ' .alert').alert('close'); $('#' + this.id + ' .alert').alert('close');
}, },
showError: function (err) { showError(err) {
if (err && err.message) err = err.message; if (err && err.message) err = err.message;
if (err == 'target island detected for section 0\n') { if (err == 'target island detected for section 0\n') {
@ -80,15 +80,15 @@ BR.Message = L.Class.extend({
this._show(err, 'error'); this._show(err, 'error');
}, },
showWarning: function (msg) { showWarning(msg) {
this._show(msg, 'warning'); this._show(msg, 'warning');
}, },
showInfo: function (msg) { showInfo(msg) {
this._show(msg, 'info'); this._show(msg, 'info');
}, },
showLoading: function (msg) { showLoading(msg) {
this._show(msg, 'loading'); this._show(msg, 'loading');
}, },
}); });

View file

@ -5,10 +5,10 @@ BR.OpacitySlider = L.Class.extend({
orientation: 'vertical', orientation: 'vertical',
defaultValue: BR.conf.defaultOpacity, defaultValue: BR.conf.defaultOpacity,
title: '', title: '',
callback: function (opacity) {}, callback(opacity) {},
}, },
initialize: function (options) { initialize(options) {
L.setOptions(this, options); L.setOptions(this, options);
var input = (this.input = $('<input id="slider-' + this.options.id + '" type="text"/>')), var input = (this.input = $('<input id="slider-' + this.options.id + '" type="text"/>')),
@ -26,7 +26,7 @@ BR.OpacitySlider = L.Class.extend({
min: 0, min: 0,
max: 100, max: 100,
step: 1, step: 1,
value: value, value,
orientation: this.options.orientation, orientation: this.options.orientation,
reversed: this.options.reversed, reversed: this.options.reversed,
selection: this.options.reversed ? 'before' : 'after', // inverted, serves as track style, see css selection: this.options.reversed ? 'before' : 'after', // inverted, serves as track style, see css
@ -51,19 +51,19 @@ BR.OpacitySlider = L.Class.extend({
} }
}, },
_keydownListener: function (e) { _keydownListener(e) {
if (BR.Util.keyboardShortcutsAllowed(e) && e.keyCode === this.options.muteKeyCode) { if (BR.Util.keyboardShortcutsAllowed(e) && e.keyCode === this.options.muteKeyCode) {
this.options.callback(0); this.options.callback(0);
} }
}, },
_keyupListener: function (e) { _keyupListener(e) {
if (BR.Util.keyboardShortcutsAllowed(e) && e.keyCode === this.options.muteKeyCode) { if (BR.Util.keyboardShortcutsAllowed(e) && e.keyCode === this.options.muteKeyCode) {
this.options.callback(this.input.val() / 100); this.options.callback(this.input.val() / 100);
} }
}, },
getElement: function () { getElement() {
return this.input.slider('getElement'); return this.input.slider('getElement');
}, },
}); });

View file

@ -3,7 +3,7 @@ BR.OpacitySliderControl = L.Control.extend({
position: 'topleft', position: 'topleft',
}, },
onAdd: function (map) { onAdd(map) {
var container = L.DomUtil.create('div', 'leaflet-bar control-slider'); var container = L.DomUtil.create('div', 'leaflet-bar control-slider');
// prevent also dragging map in Chrome // prevent also dragging map in Chrome

View file

@ -2,7 +2,7 @@ BR.Profile = L.Evented.extend({
cache: {}, cache: {},
saveWarningShown: false, saveWarningShown: false,
initialize: function () { initialize() {
var textArea = L.DomUtil.get('profile_upload'); var textArea = L.DomUtil.get('profile_upload');
this.editor = CodeMirror.fromTextArea(textArea, { this.editor = CodeMirror.fromTextArea(textArea, {
lineNumbers: true, lineNumbers: true,
@ -26,7 +26,7 @@ BR.Profile = L.Evented.extend({
}); });
}, },
clear: function (evt) { clear(evt) {
var button = evt.target || evt.srcElement; var button = evt.target || evt.srcElement;
evt.preventDefault(); evt.preventDefault();
@ -38,7 +38,7 @@ BR.Profile = L.Evented.extend({
button.blur(); button.blur();
}, },
update: function (options, cb) { update(options, cb) {
var profileName = options.profile, var profileName = options.profile,
profileUrl, profileUrl,
loading = false; loading = false;
@ -75,17 +75,17 @@ BR.Profile = L.Evented.extend({
if (cb && !loading) cb(); if (cb && !loading) cb();
}, },
show: function () { show() {
this.editor.refresh(); this.editor.refresh();
}, },
onResize: function () { onResize() {
this.editor.refresh(); this.editor.refresh();
}, },
// Returns the initial value of the given profile variable as String, as defined by the assign statement. // Returns the initial value of the given profile variable as String, as defined by the assign statement.
// Intended for all assigned variables, not just parameters with a comment declaration, i.e. no type information used. // Intended for all assigned variables, not just parameters with a comment declaration, i.e. no type information used.
getProfileVar: function (name) { getProfileVar(name) {
let value; let value;
if (this._isParamsFormActive()) { if (this._isParamsFormActive()) {
const formValues = this._getFormValues(); const formValues = this._getFormValues();
@ -106,13 +106,13 @@ BR.Profile = L.Evented.extend({
}, },
// Returns car|bike|foot, default is foot // Returns car|bike|foot, default is foot
getTransportMode: function () { getTransportMode() {
const isCar = !!this.getProfileVar('validForCars'); const isCar = !!this.getProfileVar('validForCars');
const isBike = !!this.getProfileVar('validForBikes'); const isBike = !!this.getProfileVar('validForBikes');
return isCar ? 'car' : isBike ? 'bike' : 'foot'; return isCar ? 'car' : isBike ? 'bike' : 'foot';
}, },
_upload: function (evt) { _upload(evt) {
var button = evt.target || evt.srcElement, var button = evt.target || evt.srcElement,
profile = this._getProfileText(); profile = this._getProfileText();
@ -136,7 +136,7 @@ BR.Profile = L.Evented.extend({
}); });
}, },
_buildCustomProfile: function (profileText) { _buildCustomProfile(profileText) {
const formValues = this._getFormValues(); const formValues = this._getFormValues();
Object.keys(formValues).forEach((name) => { Object.keys(formValues).forEach((name) => {
const value = formValues[name]; const value = formValues[name];
@ -152,7 +152,7 @@ BR.Profile = L.Evented.extend({
return profileText; return profileText;
}, },
_getFormValues: function () { _getFormValues() {
const obj = {}; const obj = {};
document.querySelectorAll('#profile_params input, #profile_params select').forEach((input) => { document.querySelectorAll('#profile_params input, #profile_params select').forEach((input) => {
const name = input.name; const name = input.name;
@ -167,12 +167,12 @@ BR.Profile = L.Evented.extend({
return obj; return obj;
}, },
_save: function (evt) { _save(evt) {
var profileText = this._buildCustomProfile(this._getProfileText()); var profileText = this._buildCustomProfile(this._getProfileText());
var that = this; var that = this;
this.fire('update', { this.fire('update', {
profileText: profileText, profileText,
callback: function (err, profileId, profileText) { callback(err, profileId, profileText) {
if (!err) { if (!err) {
that.profileName = profileId; that.profileName = profileId;
that.cache[profileId] = profileText; that.cache[profileId] = profileText;
@ -181,7 +181,7 @@ BR.Profile = L.Evented.extend({
}); });
}, },
_updateProfile: function (profileName, profileText) { _updateProfile(profileName, profileText) {
const empty = !this.editor.getValue(); const empty = !this.editor.getValue();
const clean = this.editor.isClean(); const clean = this.editor.isClean();
@ -201,7 +201,7 @@ BR.Profile = L.Evented.extend({
} }
}, },
_setValue: function (profileText) { _setValue(profileText) {
profileText = profileText || ''; profileText = profileText || '';
var clean = this.editor.isClean(); var clean = this.editor.isClean();
@ -220,7 +220,7 @@ BR.Profile = L.Evented.extend({
} }
}, },
_buildParamsForm: function (profileText) { _buildParamsForm(profileText) {
if (!profileText) return; if (!profileText) return;
// Otherwise, create user friendly form // Otherwise, create user friendly form
@ -278,9 +278,9 @@ BR.Profile = L.Evented.extend({
} }
params[name] = { params[name] = {
description: description, description,
type: paramType, type: paramType,
value: value, value,
possible_values: paramValues, possible_values: paramValues,
}; };
} }
@ -359,11 +359,11 @@ BR.Profile = L.Evented.extend({
}); });
}, },
_isParamsFormActive: function () { _isParamsFormActive() {
return L.DomUtil.get('profile_params_container').classList.contains('active'); return L.DomUtil.get('profile_params_container').classList.contains('active');
}, },
_activateSecondaryTab: function () { _activateSecondaryTab() {
var profileText = this._getProfileText(); var profileText = this._getProfileText();
if (this._isParamsFormActive()) { if (this._isParamsFormActive()) {
@ -373,11 +373,11 @@ BR.Profile = L.Evented.extend({
} }
}, },
_getProfileText: function () { _getProfileText() {
return this.editor.getValue(); return this.editor.getValue();
}, },
_getSelectedProfileText: function () { _getSelectedProfileText() {
return this.cache[this.selectedProfileName] ?? this.editor.getValue(); return this.cache[this.selectedProfileName] ?? this.editor.getValue();
}, },
}); });

View file

@ -5,7 +5,7 @@ BR.RoutingOptions = L.Evented.extend({
}, },
}, },
initialize: function () { initialize() {
$('#profile-alternative').on('changed.bs.select', this._getChangeHandler()); $('#profile-alternative').on('changed.bs.select', this._getChangeHandler());
var remembered_profile = this.getRememberedProfile(); var remembered_profile = this.getRememberedProfile();
@ -35,7 +35,7 @@ BR.RoutingOptions = L.Evented.extend({
L.DomEvent.addListener(document, 'keydown', this._keydownListener, this); L.DomEvent.addListener(document, 'keydown', this._keydownListener, this);
}, },
refreshUI: function () { refreshUI() {
// we do not allow to select more than one profile and/or alternative at a time // we do not allow to select more than one profile and/or alternative at a time
// so we disable the current selected items // so we disable the current selected items
$('#profile-alternative') $('#profile-alternative')
@ -61,7 +61,7 @@ BR.RoutingOptions = L.Evented.extend({
button.title = button.title + i18next.t('navbar.profile-tooltip', { key: 'G' }); button.title = button.title + i18next.t('navbar.profile-tooltip', { key: 'G' });
}, },
getOptions: function () { getOptions() {
var profile = $('#profile option:selected'), var profile = $('#profile option:selected'),
alternative = $('#alternative option:selected'); alternative = $('#alternative option:selected');
this.refreshUI(); this.refreshUI();
@ -72,7 +72,7 @@ BR.RoutingOptions = L.Evented.extend({
}; };
}, },
setOptions: function (options) { setOptions(options) {
var values = [ var values = [
options.profile ? options.profile : $('#profile option:selected').val(), options.profile ? options.profile : $('#profile option:selected').val(),
options.alternative ? options.alternative : $('#alternative option:selected').val(), options.alternative ? options.alternative : $('#alternative option:selected').val(),
@ -86,7 +86,7 @@ BR.RoutingOptions = L.Evented.extend({
} }
}, },
setCustomProfile: function (profile, noUpdate) { setCustomProfile(profile, noUpdate) {
var profiles_grp, option; var profiles_grp, option;
profiles_grp = L.DomUtil.get('profile'); profiles_grp = L.DomUtil.get('profile');
@ -112,7 +112,7 @@ BR.RoutingOptions = L.Evented.extend({
} }
}, },
getCustomProfile: function () { getCustomProfile() {
var profiles_grp = L.DomUtil.get('profile'), var profiles_grp = L.DomUtil.get('profile'),
option = profiles_grp.children[0], option = profiles_grp.children[0],
profile = null; profile = null;
@ -123,7 +123,7 @@ BR.RoutingOptions = L.Evented.extend({
return profile; return profile;
}, },
rememberProfile: function (profile) { rememberProfile(profile) {
if (!BR.Util.localStorageAvailable()) { if (!BR.Util.localStorageAvailable()) {
return; return;
} }
@ -135,7 +135,7 @@ BR.RoutingOptions = L.Evented.extend({
localStorage.setItem('routingprofile', profile); localStorage.setItem('routingprofile', profile);
}, },
getRememberedProfile: function () { getRememberedProfile() {
if (!BR.Util.localStorageAvailable()) { if (!BR.Util.localStorageAvailable()) {
return null; return null;
} }
@ -143,14 +143,14 @@ BR.RoutingOptions = L.Evented.extend({
return localStorage.getItem('routingprofile'); return localStorage.getItem('routingprofile');
}, },
_getChangeHandler: function () { _getChangeHandler() {
return L.bind(function (evt) { return L.bind(function (evt) {
this.rememberProfile(evt.target.options[evt.target.options.selectedIndex].value); this.rememberProfile(evt.target.options[evt.target.options.selectedIndex].value);
this.fire('update', { options: this.getOptions() }); this.fire('update', { options: this.getOptions() });
}, this); }, this);
}, },
_keydownListener: function (e) { _keydownListener(e) {
if (BR.Util.keyboardShortcutsAllowed(e) && e.keyCode === this.options.shortcut.switch) { if (BR.Util.keyboardShortcutsAllowed(e) && e.keyCode === this.options.shortcut.switch) {
if (!$('#profile-alternative-form .dropdown').hasClass('show')) { if (!$('#profile-alternative-form .dropdown').hasClass('show')) {
$('#profile-alternative-form button').click(); $('#profile-alternative-form button').click();

View file

@ -8,18 +8,18 @@ BR.ShareRoute = L.Class.extend({
}, },
}, },
initialize: function () { initialize() {
L.DomUtil.get('shareButton').onclick = L.bind(this.share, this); L.DomUtil.get('shareButton').onclick = L.bind(this.share, this);
L.DomEvent.addListener(document, 'keydown', this._keydownListener, this); L.DomEvent.addListener(document, 'keydown', this._keydownListener, this);
}, },
share: function (event) { share(event) {
event.preventDefault(); event.preventDefault();
this.services(); this.services();
this.qrcode(); this.qrcode();
}, },
services: function () { services() {
const self = this; const self = this;
$('.share-copy-link').on('click', function () { $('.share-copy-link').on('click', function () {
@ -68,7 +68,7 @@ BR.ShareRoute = L.Class.extend({
* to the length of the URL * to the length of the URL
* - displays buttons to change the size of the QR Code (small, medium, large) * - displays buttons to change the size of the QR Code (small, medium, large)
*/ */
qrcode: function () { qrcode() {
const exportUrl = this.createQrCodeUrl(); const exportUrl = this.createQrCodeUrl();
this.renderQrCode('share-qrcode-img', exportUrl, this.getQrCodeSizeForUrl(exportUrl)); this.renderQrCode('share-qrcode-img', exportUrl, this.getQrCodeSizeForUrl(exportUrl));
@ -78,7 +78,7 @@ BR.ShareRoute = L.Class.extend({
}); });
}, },
getQrCodeSizeForUrl: function (url) { getQrCodeSizeForUrl(url) {
if (url.length < 500) { if (url.length < 500) {
return 256; return 256;
} }
@ -90,7 +90,7 @@ BR.ShareRoute = L.Class.extend({
return 512; return 512;
}, },
renderQrCode: function (elementId, url, size) { renderQrCode(elementId, url, size) {
$('#share-qrcode-img').empty(); $('#share-qrcode-img').empty();
$('#qrcode-buttons').show(); $('#qrcode-buttons').show();
$('#qrcode-msg-unknown-error').hide(); $('#qrcode-msg-unknown-error').hide();
@ -119,7 +119,7 @@ BR.ShareRoute = L.Class.extend({
} }
}, },
createQrCodeUrl: function () { createQrCodeUrl() {
// We work on a copy of the current location instance to avoid // We work on a copy of the current location instance to avoid
// reloading the page (which will happen when the `export` query // reloading the page (which will happen when the `export` query
// parameter is added to the actual location object): // parameter is added to the actual location object):
@ -137,7 +137,7 @@ BR.ShareRoute = L.Class.extend({
return exportLocation.toString(); return exportLocation.toString();
}, },
getShareUrl: function () { getShareUrl() {
const exportLocation = new URL(document.location.href); const exportLocation = new URL(document.location.href);
const searchParams = new URLSearchParams(exportLocation.search); const searchParams = new URLSearchParams(exportLocation.search);
searchParams.delete('export'); searchParams.delete('export');
@ -146,7 +146,7 @@ BR.ShareRoute = L.Class.extend({
return exportLocation.toString(); return exportLocation.toString();
}, },
_keydownListener: function (event) { _keydownListener(event) {
if ( if (
BR.Util.keyboardShortcutsAllowed(event) && BR.Util.keyboardShortcutsAllowed(event) &&
event.keyCode === this.options.shortcut.share_action && event.keyCode === this.options.shortcut.share_action &&

View file

@ -35,7 +35,7 @@ BR.TrackAnalysis = L.Class.extend({
* @param {Map} map * @param {Map} map
* @param {object} options * @param {object} options
*/ */
initialize: function (map, options) { initialize(map, options) {
this.map = map; this.map = map;
L.setOptions(this, options); L.setOptions(this, options);
}, },
@ -60,7 +60,7 @@ BR.TrackAnalysis = L.Class.extend({
/** /**
* Called by BR.Sidebar when tab is activated * Called by BR.Sidebar when tab is activated
*/ */
show: function () { show() {
this.active = true; this.active = true;
this.options.requestUpdate(this); this.options.requestUpdate(this);
}, },
@ -68,23 +68,23 @@ BR.TrackAnalysis = L.Class.extend({
/** /**
* Called by BR.Sidebar when tab is deactivated * Called by BR.Sidebar when tab is deactivated
*/ */
hide: function () { hide() {
this.active = false; this.active = false;
}, },
/** /**
* Everytime the track changes this method is called: * Everytime the track changes this method is called:
* *
* - calculate statistics (way type, surface, smoothness) * - calculate statistics (way type, max speed, surface, smoothness)
* for the whole track * for the whole track
* - renders statistics tables * - renders statistics tables
* - create event listeners which allow to hover/click a * - create event listeners which allow to hover/click a
* table row for highlighting matching track segments * table row for highlighting matching track segments
* *
* @param {Polyline} polyline * @param {Polyline} polyline
* @param {Array} segments * @param {Array} segments - route segments between waypoints
*/ */
update: function (polyline, segments) { update(polyline, segments) {
if (!this.active) { if (!this.active) {
return; return;
} }
@ -105,7 +105,7 @@ BR.TrackAnalysis = L.Class.extend({
this.trackPolyline = polyline; this.trackPolyline = polyline;
this.trackEdges = new BR.TrackEdges(segments); this.trackEdges = new BR.TrackEdges(segments);
var analysis = this.calcStats(polyline, segments); const analysis = this.calcStats(polyline, segments);
this.render(analysis); this.render(analysis);
@ -129,9 +129,10 @@ BR.TrackAnalysis = L.Class.extend({
* @param segments * @param segments
* @returns {Object} * @returns {Object}
*/ */
calcStats: function (polyline, segments) { calcStats(polyline, segments) {
const analysis = { const analysis = {
highway: {}, highway: {},
maxspeed: {},
surface: {}, surface: {},
smoothness: {}, smoothness: {},
}; };
@ -175,14 +176,25 @@ BR.TrackAnalysis = L.Class.extend({
segments[segmentIndex].feature.properties.messages[messageIndex][3] segments[segmentIndex].feature.properties.messages[messageIndex][3]
); );
break; break;
case 'maxspeed':
case 'surface': case 'surface':
case 'smoothness': case 'smoothness':
if (typeof analysis[tagName][wayTagParts[1]] === 'undefined') { if (typeof analysis[tagName][wayTagParts[1]] === 'undefined') {
analysis[tagName][wayTagParts[1]] = { let formattedName;
formatted_name: i18next.t(
if (tagName.indexOf('maxspeed') === 0) {
formattedName = i18next.t('sidebar.analysis.data.maxspeed', {
maxspeed: wayTagParts[1],
});
} else {
formattedName = i18next.t([
'sidebar.analysis.data.' + tagName + '.' + wayTagParts[1], 'sidebar.analysis.data.' + tagName + '.' + wayTagParts[1],
wayTagParts[1] wayTagParts[1],
), ]);
}
analysis[tagName][wayTagParts[1]] = {
formatted_name: formattedName,
name: wayTagParts[1], name: wayTagParts[1],
subtype: '', subtype: '',
distance: 0.0, distance: 0.0,
@ -209,11 +221,15 @@ BR.TrackAnalysis = L.Class.extend({
* are dropped. If no specialized surface/smoothness tag is found, the default value * are dropped. If no specialized surface/smoothness tag is found, the default value
* is returned, i.e. `smoothness` or `surface`. * is returned, i.e. `smoothness` or `surface`.
* *
* @param wayTags tags + values for a way segment * Also, maxspeed comes in different variations, e.g. `maxspeed`, `maxspeed:forward`,
* @param routingType currently only 'cycling' is supported, can be extended in the future (walking, driving, etc.) * `maxspeed:backward`. Depending on the existence of the `reversedirection` field
* we can select the correct value.
*
* @param wayTags - tags + values for a way segment
* @param routingType - currently only 'cycling' is supported, can be extended in the future (walking, driving, etc.)
* @returns {*[]} * @returns {*[]}
*/ */
normalizeWayTags: function (wayTags, routingType) { normalizeWayTags(wayTags, routingType) {
let normalizedWayTags = {}; let normalizedWayTags = {};
let surfaceTags = {}; let surfaceTags = {};
let smoothnessTags = {}; let smoothnessTags = {};
@ -242,6 +258,19 @@ BR.TrackAnalysis = L.Class.extend({
continue; continue;
} }
if (tagName === 'maxspeed:forward' && !wayTags.includes('reversedirection=yes')) {
normalizedWayTags['maxspeed'] = tagValue;
continue;
}
if (tagName === 'maxspeed:backward' && wayTags.includes('reversedirection=yes')) {
normalizedWayTags['maxspeed'] = tagValue;
continue;
}
if (tagName === 'maxspeed') {
normalizedWayTags[tagName] = tagValue;
continue;
}
normalizedWayTags[tagName] = tagValue; normalizedWayTags[tagName] = tagValue;
} }
@ -278,11 +307,11 @@ BR.TrackAnalysis = L.Class.extend({
* *
* @returns {Object} * @returns {Object}
*/ */
sortAnalysisData: function (analysis) { sortAnalysisData(analysis) {
var analysisSortable = {}; const analysisSortable = {};
var result = {}; const result = {};
for (var type in analysis) { for (const type in analysis) {
if (!analysis.hasOwnProperty(type)) { if (!analysis.hasOwnProperty(type)) {
continue; continue;
} }
@ -290,18 +319,24 @@ BR.TrackAnalysis = L.Class.extend({
result[type] = {}; result[type] = {};
analysisSortable[type] = []; analysisSortable[type] = [];
for (var name in analysis[type]) { for (const name in analysis[type]) {
if (!analysis[type].hasOwnProperty(name)) { if (!analysis[type].hasOwnProperty(name)) {
continue; continue;
} }
analysisSortable[type].push(analysis[type][name]); analysisSortable[type].push(analysis[type][name]);
} }
if (type === 'maxspeed') {
analysisSortable[type].sort(function (a, b) {
return parseInt(a.name) - parseInt(b.name);
});
} else {
analysisSortable[type].sort(function (a, b) { analysisSortable[type].sort(function (a, b) {
return b.distance - a.distance; return b.distance - a.distance;
}); });
}
for (var j = 0; j < analysisSortable[type].length; j++) { for (let j = 0; j < analysisSortable[type].length; j++) {
result[type][analysisSortable[type][j].formatted_name] = analysisSortable[type][j]; result[type][analysisSortable[type][j].formatted_name] = analysisSortable[type][j];
} }
} }
@ -316,9 +351,9 @@ BR.TrackAnalysis = L.Class.extend({
* @param {string[]} wayTags * @param {string[]} wayTags
* @returns {string} * @returns {string}
*/ */
getTrackType: function (wayTags) { getTrackType(wayTags) {
for (var i = 0; i < wayTags.length; i++) { for (let i = 0; i < wayTags.length; i++) {
var wayTagParts = wayTags[i].split('='); const wayTagParts = wayTags[i].split('=');
if (wayTagParts[0] === 'tracktype') { if (wayTagParts[0] === 'tracktype') {
return wayTagParts[1]; return wayTagParts[1];
} }
@ -330,22 +365,20 @@ BR.TrackAnalysis = L.Class.extend({
/** /**
* @param {Object} analysis * @param {Object} analysis
*/ */
render: function (analysis) { render(analysis) {
var $content = $('#track_statistics'); const $content = $('#track_statistics');
$content.html(''); $content.html('');
$content.append( $content.append($(`<h4 class="track-analysis-heading">${i18next.t('sidebar.analysis.header.highway')}</h4>`));
$('<h4 class="track-analysis-heading">' + i18next.t('sidebar.analysis.header.highway') + '</h4>')
);
$content.append(this.renderTable('highway', analysis.highway)); $content.append(this.renderTable('highway', analysis.highway));
$content.append( $content.append($(`<h4 class="track-analysis-heading">${i18next.t('sidebar.analysis.header.surface')}</h4>`));
$('<h4 class="track-analysis-heading">' + i18next.t('sidebar.analysis.header.surface') + '</h4>')
);
$content.append(this.renderTable('surface', analysis.surface)); $content.append(this.renderTable('surface', analysis.surface));
$content.append( $content.append(
$('<h4 class="track-analysis-heading">' + i18next.t('sidebar.analysis.header.smoothness') + '</h4>') $(`<h4 class="track-analysis-heading">${i18next.t('sidebar.analysis.header.smoothness')}</h4>`)
); );
$content.append(this.renderTable('smoothness', analysis.smoothness)); $content.append(this.renderTable('smoothness', analysis.smoothness));
$content.append($(`<h4 class="track-analysis-heading">${i18next.t('sidebar.analysis.header.maxspeed')}</h4>`));
$content.append(this.renderTable('maxspeed', analysis.maxspeed));
}, },
/** /**
@ -355,68 +388,46 @@ BR.TrackAnalysis = L.Class.extend({
* @param {Array} data * @param {Array} data
* @returns {jQuery} * @returns {jQuery}
*/ */
renderTable: function (type, data) { renderTable(type, data) {
var index; let index;
var $table = $( const $table = $(`<table data-type="${type}" class="mini stripe dataTable track-analysis-table"></table>`);
'<table data-type="' + type + '" class="mini cell-border stripe dataTable track-analysis-table"></table>' const $thead = $('<thead></thead>');
);
var $thead = $('<thead></thead>');
$thead.append( $thead.append(
$('<tr>') $('<tr>')
.append( .append(
'<th class="track-analysis-header-category">' + `<th class="track-analysis-header-category">${i18next.t('sidebar.analysis.table.category')}</th>`
i18next.t('sidebar.analysis.table.category') +
'</th>'
) )
.append( .append(
$( $(`<th class="track-analysis-header-distance">${i18next.t('sidebar.analysis.table.length')}</th>`)
'<th class="track-analysis-header-distance">' +
i18next.t('sidebar.analysis.table.length') +
'</th>'
)
) )
); );
$table.append($thead); $table.append($thead);
var $tbody = $('<tbody></tbody>'); const $tbody = $('<tbody></tbody>');
var totalDistance = 0.0; let totalDistance = 0.0;
for (index in data) { for (index in data) {
if (!data.hasOwnProperty(index)) { if (!data.hasOwnProperty(index)) {
continue; continue;
} }
var $row = $( const $row = $(`<tr data-name="${data[index].name}" \
'<tr data-name="' + data-subtype="${data[index].subtype}" \
data[index].name + data-distance="${data[index].distance}"></tr>`);
'" data-subtype="' + $row.append(`<td class="track-analysis-title">${data[index].formatted_name}</td>`);
data[index].subtype + $row.append(`<td class="track-analysis-distance">${this.formatDistance(data[index].distance)} km</td>`);
'" data-distance="' +
data[index].distance +
'"></tr>'
);
$row.append('<td class="track-analysis-title">' + data[index].formatted_name + '</td>');
$row.append(
'<td class="track-analysis-distance">' + this.formatDistance(data[index].distance) + ' km</td>'
);
$tbody.append($row); $tbody.append($row);
totalDistance += data[index].distance; totalDistance += data[index].distance;
} }
if (totalDistance < this.totalRouteDistance) { if (totalDistance < this.totalRouteDistance) {
$tbody.append( $tbody.append(
$( $(`<tr data-name="internal-unknown" data-distance="${this.totalRouteDistance - totalDistance}"></tr>`)
'<tr data-name="internal-unknown" data-distance="' + .append($(`<td class="track-analysis-title">${i18next.t('sidebar.analysis.table.unknown')}</td>`))
(this.totalRouteDistance - totalDistance) +
'"></tr>'
)
.append(
$('<td class="track-analysis-title">' + i18next.t('sidebar.analysis.table.unknown') + '</td>')
)
.append( .append(
$( $(
'<td class="track-analysis-distance">' + `<td class="track-analysis-distance">${this.formatDistance(
this.formatDistance(this.totalRouteDistance - totalDistance) + this.totalRouteDistance - totalDistance
' km</td>' )} km</td>`
) )
) )
); );
@ -427,12 +438,12 @@ BR.TrackAnalysis = L.Class.extend({
$table.append( $table.append(
$('<tfoot></tfoot>') $('<tfoot></tfoot>')
.append('<tr></tr>') .append('<tr></tr>')
.append($('<td>' + i18next.t('sidebar.analysis.table.total_known') + '</td>')) .append($(`<td>${i18next.t('sidebar.analysis.table.total_known')}</td>`))
.append( .append(
$( $(
'<td class="track-analysis-distance track-analysis-distance-total">' + `<td class="track-analysis-distance track-analysis-distance-total">${this.formatDistance(
this.formatDistance(totalDistance) + totalDistance
' km</td>' )} km</td>`
) )
) )
); );
@ -446,32 +457,32 @@ BR.TrackAnalysis = L.Class.extend({
* @param {number} meters * @param {number} meters
* @returns {string} * @returns {string}
*/ */
formatDistance: function (meters) { formatDistance(meters) {
return (meters / 1000).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }); return (meters / 1000).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}, },
handleHover: function (event) { handleHover(event) {
var $tableRow = $(event.currentTarget); const $tableRow = $(event.currentTarget);
var $table = $tableRow.parents('table').first(); const $table = $tableRow.parents('table').first();
var dataType = $table.data('type'); const dataType = $table.data('type');
var dataName = $tableRow.data('name'); const dataName = $tableRow.data('name');
var trackType = $tableRow.data('subtype'); const trackType = $tableRow.data('subtype');
var polylinesForDataType = this.getPolylinesForDataType(dataType, dataName, trackType); const polylinesForDataType = this.getPolylinesForDataType(dataType, dataName, trackType);
this.highlightedSegments = L.layerGroup(polylinesForDataType).addTo(this.map); this.highlightedSegments = L.layerGroup(polylinesForDataType).addTo(this.map);
}, },
handleHoverOut: function () { handleHoverOut() {
this.map.removeLayer(this.highlightedSegments); this.map.removeLayer(this.highlightedSegments);
}, },
toggleSelected: function (event) { toggleSelected(event) {
var tableRow = event.currentTarget; const tableRow = event.currentTarget;
var $table = $(tableRow).parents('table').first(); const $table = $(tableRow).parents('table').first();
var dataType = $table.data('type'); const dataType = $table.data('type');
var dataName = $(tableRow).data('name'); const dataName = $(tableRow).data('name');
var trackType = $(tableRow).data('subtype'); const trackType = $(tableRow).data('subtype');
if (tableRow.classList.toggle('selected')) { if (tableRow.classList.toggle('selected')) {
if (this.highlightedSegment) { if (this.highlightedSegment) {
@ -497,21 +508,21 @@ BR.TrackAnalysis = L.Class.extend({
* track edge matches the search, create a Leaflet polyline * track edge matches the search, create a Leaflet polyline
* and add it to the result array. * and add it to the result array.
* *
* @param {string} dataType `highway`, `surface`, `smoothness` * @param {string} dataType - `highway`, `surface`, `smoothness`
* @param {string} dataName `primary`, `track, `asphalt`, etc. * @param {string} dataName - `primary`, `track, `asphalt`, etc.
* @param {string} trackType the tracktype is passed here (e.g. * @param {string} trackType - the tracktype is passed here (e.g.
* `grade3`), but only in the case that `dataName` is `track` * `grade3`), but only in the case that `dataName` is `track`
* *
* @returns {Polyline[]} * @returns {Polyline[]}
*/ */
getPolylinesForDataType: function (dataType, dataName, trackType) { getPolylinesForDataType(dataType, dataName, trackType) {
var polylines = []; const polylines = [];
var trackLatLngs = this.trackPolyline.getLatLngs(); const trackLatLngs = this.trackPolyline.getLatLngs();
for (var i = 0; i < this.trackEdges.edges.length; i++) { for (let i = 0; i < this.trackEdges.edges.length; i++) {
if (this.wayTagsMatchesData(trackLatLngs[this.trackEdges.edges[i]], dataType, dataName, trackType)) { if (this.wayTagsMatchesData(trackLatLngs[this.trackEdges.edges[i]], dataType, dataName, trackType)) {
var matchedEdgeIndexStart = i > 0 ? this.trackEdges.edges[i - 1] : 0; const matchedEdgeIndexStart = i > 0 ? this.trackEdges.edges[i - 1] : 0;
var matchedEdgeIndexEnd = this.trackEdges.edges[i] + 1; const matchedEdgeIndexEnd = this.trackEdges.edges[i] + 1;
polylines.push( polylines.push(
L.polyline( L.polyline(
trackLatLngs.slice(matchedEdgeIndexStart, matchedEdgeIndexEnd), trackLatLngs.slice(matchedEdgeIndexStart, matchedEdgeIndexEnd),
@ -530,16 +541,16 @@ BR.TrackAnalysis = L.Class.extend({
* which matches if a tag-pair is missing. Special handling for * which matches if a tag-pair is missing. Special handling for
* tracktypes again. * tracktypes again.
* *
* @param {string} wayTags The way tags as provided by brouter, e.g. * @param {string} wayTags - The way tags as provided by brouter, e.g.
* `highway=secondary surface=asphalt smoothness=good` * `highway=secondary surface=asphalt smoothness=good`
* @param {string} dataType `highway`, `surface`, `smoothness` * @param {string} dataType - `highway`, `surface`, `smoothness`
* @param {string} dataName `primary`, `track, `asphalt`, etc. * @param {string} dataName - `primary`, `track, `asphalt`, etc.
* @param {string} trackType the tracktype is passed here (e.g. * @param {string} trackType - the tracktype is passed here (e.g.
* `grade3`), but only in the case that `dataName` is `track` * `grade3`), but only in the case that `dataName` is `track`
* *
* @returns {boolean} * @returns {boolean}
*/ */
wayTagsMatchesData: function (wayTags, dataType, dataName, trackType) { wayTagsMatchesData(wayTags, dataType, dataName, trackType) {
const parsed = this.wayTagsToObject(wayTags); const parsed = this.wayTagsToObject(wayTags);
switch (dataType) { switch (dataType) {
@ -559,19 +570,44 @@ BR.TrackAnalysis = L.Class.extend({
return this.singleWayTagMatchesData('surface', parsed, dataName); return this.singleWayTagMatchesData('surface', parsed, dataName);
case 'smoothness': case 'smoothness':
return this.singleWayTagMatchesData('smoothness', parsed, dataName); return this.singleWayTagMatchesData('smoothness', parsed, dataName);
case 'maxspeed':
return this.singleWayTagMatchesData('maxspeed', parsed, dataName);
} }
return false; return false;
}, },
singleWayTagMatchesData: function (category, parsedData, lookupValue) { singleWayTagMatchesData(category, parsedData, lookupValue) {
var foundValue = null; if (typeof lookupValue === 'number') {
lookupValue = lookupValue.toString();
for (var iterationKey in parsedData) {
if (iterationKey.indexOf(category) !== -1) {
foundValue = parsedData[iterationKey];
break;
} }
let foundValue = null;
// We need to handle `maxspeed:forward` and `maxspeed:backward` separately
// from all other tags, because we need to consider the `reversedirection`
// tag.
// Test URL: http://localhost:3000/#map=15/52.2292/13.6204/standard&lonlats=13.61948,52.231611;13.611327,52.227431
if (
category === 'maxspeed' &&
parsedData.hasOwnProperty('maxspeed:forward') &&
!parsedData.hasOwnProperty('reversedirection')
) {
foundValue = parsedData['maxspeed:forward'];
}
if (
category === 'maxspeed' &&
parsedData.hasOwnProperty('maxspeed:backward') &&
parsedData.hasOwnProperty('reversedirection') &&
parsedData.reversedirection === 'yes'
) {
foundValue = parsedData['maxspeed:backward'];
}
// if the special handling for `maxspeed` didn't find a result,
// check wayTags for matching property:
if (foundValue === null && parsedData.hasOwnProperty(category)) {
foundValue = parsedData[category];
} }
if (lookupValue === 'internal-unknown' && foundValue === null) { if (lookupValue === 'internal-unknown' && foundValue === null) {
@ -586,12 +622,12 @@ BR.TrackAnalysis = L.Class.extend({
* *
* 'highway=primary surface=asphalt' => { highway: 'primary', surface: 'asphalt' } * 'highway=primary surface=asphalt' => { highway: 'primary', surface: 'asphalt' }
* *
* @param wayTags The way tags as provided by brouter, e.g. * @param wayTags - The way tags as provided by brouter, e.g.
* `highway=secondary surface=asphalt smoothness=good` * `highway=secondary surface=asphalt smoothness=good`
* *
* @returns {object} * @returns {object}
*/ */
wayTagsToObject: function (wayTags) { wayTagsToObject(wayTags) {
let result = {}; let result = {};
const wayTagPairs = wayTags.feature.wayTags.split(' '); const wayTagPairs = wayTags.feature.wayTags.split(' ');
@ -608,11 +644,11 @@ BR.TrackAnalysis = L.Class.extend({
* *
* { 'highway' : 'path', 'surface' : 'sand' } => ['highway=path', 'surface=sand'] * { 'highway' : 'path', 'surface' : 'sand' } => ['highway=path', 'surface=sand']
* *
* @param wayTags The way tags in object representation * @param wayTags - The way tags in object representation
* *
* @returns {object} * @returns {object}
*/ */
wayTagsToArray: function (wayTags) { wayTagsToArray(wayTags) {
let wayTagsArray = []; let wayTagsArray = [];
for (let wayTagKey in wayTags) { for (let wayTagKey in wayTags) {
wayTagsArray.push(wayTagKey + '=' + wayTags[wayTagKey]); wayTagsArray.push(wayTagKey + '=' + wayTags[wayTagKey]);

View file

@ -38,7 +38,7 @@ BR.TrackMessages = L.Class.extend({
segments: null, segments: null,
initialize: function (map, options) { initialize(map, options) {
L.setOptions(this, options); L.setOptions(this, options);
this._map = map; this._map = map;
@ -53,7 +53,7 @@ BR.TrackMessages = L.Class.extend({
this._mapMouseOutHandlerBound = this.mapMouseOutHandler.bind(this); this._mapMouseOutHandlerBound = this.mapMouseOutHandler.bind(this);
}, },
update: function (polyline, segments, layer) { update(polyline, segments, layer) {
var i, var i,
messages, messages,
columns, columns,
@ -89,8 +89,8 @@ BR.TrackMessages = L.Class.extend({
this._table = $('#datatable').DataTable({ this._table = $('#datatable').DataTable({
destroy: true, destroy: true,
data: data, data,
columns: columns, columns,
paging: false, paging: false,
searching: false, searching: false,
info: false, info: false,
@ -109,7 +109,7 @@ BR.TrackMessages = L.Class.extend({
this.listenMapEvents(layer, true); this.listenMapEvents(layer, true);
}, },
listenMapEvents: function (layer, on) { listenMapEvents(layer, on) {
if (layer) { if (layer) {
if (on) { if (on) {
layer.on('mousemove', this._mapMouseMoveHandlerBound); layer.on('mousemove', this._mapMouseMoveHandlerBound);
@ -121,16 +121,16 @@ BR.TrackMessages = L.Class.extend({
} }
}, },
show: function () { show() {
this.active = true; this.active = true;
this.options.requestUpdate(this); this.options.requestUpdate(this);
}, },
hide: function () { hide() {
this.active = false; this.active = false;
}, },
_destroyTable: function () { _destroyTable() {
var ele; var ele;
if ($.fn.DataTable.isDataTable('#datatable')) { if ($.fn.DataTable.isDataTable('#datatable')) {
@ -147,7 +147,7 @@ BR.TrackMessages = L.Class.extend({
return ele || document.getElementById('datatable'); return ele || document.getElementById('datatable');
}, },
_destroyEdges: function () { _destroyEdges() {
if (this._selectedEdge) { if (this._selectedEdge) {
this._map.removeLayer(this._selectedEdge); this._map.removeLayer(this._selectedEdge);
this._selectedEdge = null; this._selectedEdge = null;
@ -158,7 +158,7 @@ BR.TrackMessages = L.Class.extend({
} }
}, },
_getColumns: function (headings, data) { _getColumns(headings, data) {
var columns = [], var columns = [],
defaultOptions, defaultOptions,
options, options,
@ -175,7 +175,7 @@ BR.TrackMessages = L.Class.extend({
return columns; return columns;
}, },
_getEmptyColumns: function (data) { _getEmptyColumns(data) {
var empty = new Array(data[0].length), var empty = new Array(data[0].length),
i; i;
@ -192,7 +192,7 @@ BR.TrackMessages = L.Class.extend({
return empty; return empty;
}, },
_getRowEdge: function (tr) { _getRowEdge(tr) {
var row = this._table.row($(tr)), var row = this._table.row($(tr)),
trackLatLngs = this.trackPolyline.getLatLngs(), trackLatLngs = this.trackPolyline.getLatLngs(),
startIndex = row.index() > 0 ? this.trackEdges.edges[row.index() - 1] : 0, startIndex = row.index() > 0 ? this.trackEdges.edges[row.index() - 1] : 0,
@ -202,7 +202,7 @@ BR.TrackMessages = L.Class.extend({
return L.polyline(edgeLatLngs, this.options.edgeStyle); return L.polyline(edgeLatLngs, this.options.edgeStyle);
}, },
_handleHover: function (evt) { _handleHover(evt) {
var tr = evt.currentTarget; var tr = evt.currentTarget;
this._hoveredEdge = this._getRowEdge(tr).addTo(this._map); this._hoveredEdge = this._getRowEdge(tr).addTo(this._map);
@ -211,12 +211,12 @@ BR.TrackMessages = L.Class.extend({
} }
}, },
_handleHoverOut: function (evt) { _handleHoverOut(evt) {
this._map.removeLayer(this._hoveredEdge); this._map.removeLayer(this._hoveredEdge);
this._hoveredEdge = null; this._hoveredEdge = null;
}, },
_toggleSelected: function (evt) { _toggleSelected(evt) {
var tr = evt.currentTarget; var tr = evt.currentTarget;
if (tr.classList.toggle('selected')) { if (tr.classList.toggle('selected')) {
@ -237,14 +237,14 @@ BR.TrackMessages = L.Class.extend({
} }
}, },
_toggleSyncMap: function (evt) { _toggleSyncMap(evt) {
var button = evt.currentTarget; var button = evt.currentTarget;
button.classList.toggle('active'); button.classList.toggle('active');
this.options.syncMap = !this.options.syncMap; this.options.syncMap = !this.options.syncMap;
}, },
mapMouseMoveHandler: function (evt) { mapMouseMoveHandler(evt) {
// initialize the vars for the closest item calculation // initialize the vars for the closest item calculation
let closestPointIdx = null; let closestPointIdx = null;
// large enough to be trumped by any point on the chart // large enough to be trumped by any point on the chart
@ -292,7 +292,7 @@ BR.TrackMessages = L.Class.extend({
} }
}, },
mapMouseOutHandler: function () { mapMouseOutHandler() {
if (this._mapHoveredRow) { if (this._mapHoveredRow) {
this._mapHoveredRow.classList.remove('hoverRoute'); this._mapHoveredRow.classList.remove('hoverRoute');
} }

View file

@ -1,5 +1,5 @@
BR.TrackStats = L.Class.extend({ BR.TrackStats = L.Class.extend({
update: function (polyline, segments) { update(polyline, segments) {
if (segments.length == 0) { if (segments.length == 0) {
$('#stats-container').hide(); $('#stats-container').hide();
$('#stats-info').show(); $('#stats-info').show();
@ -44,7 +44,7 @@ BR.TrackStats = L.Class.extend({
$('#meanenergy').html(meanEnergy); $('#meanenergy').html(meanEnergy);
}, },
calcStats: function (polyline, segments) { calcStats(polyline, segments) {
var stats = { var stats = {
trackLength: 0, trackLength: 0,
filteredAscend: 0, filteredAscend: 0,

View file

@ -1,5 +1,5 @@
BR.Csv = { BR.Csv = {
format: function (geoJson) { format(geoJson) {
const separator = '\t'; const separator = '\t';
const newline = '\n'; const newline = '\n';
const messages = geoJson.features[0].properties.messages; const messages = geoJson.features[0].properties.messages;

View file

@ -1,5 +1,5 @@
BR.Fit = { BR.Fit = {
format: function (geoJson, turnInstructionMode = 0) { format(geoJson, turnInstructionMode = 0) {
if (!geoJson?.features) return ''; if (!geoJson?.features) return '';
function calcDistance(p1, p2) { function calcDistance(p1, p2) {

View file

@ -1,6 +1,6 @@
// derived from BRouter btools.router.OsmTrack.formatAsGpx // derived from BRouter btools.router.OsmTrack.formatAsGpx
BR.Gpx = { BR.Gpx = {
format: function (geoJson, turnInstructionMode = 0, transportMode = 'bike') { format(geoJson, turnInstructionMode = 0, transportMode = 'bike') {
if (!geoJson?.features) return ''; if (!geoJson?.features) return '';
class GpxTransform { class GpxTransform {
@ -55,9 +55,9 @@ BR.Gpx = {
let gpx = togpx(geoJson, { let gpx = togpx(geoJson, {
creator: (BR.conf.appName || 'BRouter-Web') + ' ' + BR.version, creator: (BR.conf.appName || 'BRouter-Web') + ' ' + BR.version,
featureTitle: function () {}, featureTitle() {},
featureDescription: function () {}, featureDescription() {},
featureCoordTimes: function () {}, featureCoordTimes() {},
transform: gpxTransform, transform: gpxTransform,
}); });
const statsComment = BR.Gpx._statsComment(geoJson); const statsComment = BR.Gpx._statsComment(geoJson);
@ -67,7 +67,7 @@ BR.Gpx = {
}, },
// <!-- track-length = 319 filtered ascend = 2 plain-ascend = -1 cost=533 energy=.0kwh time=44s --> // <!-- track-length = 319 filtered ascend = 2 plain-ascend = -1 cost=533 energy=.0kwh time=44s -->
_statsComment: function (geoJson) { _statsComment(geoJson) {
const props = geoJson.features?.[0].properties; const props = geoJson.features?.[0].properties;
if (!props) return ''; if (!props) return '';

View file

@ -1,5 +1,5 @@
BR.Kml = { BR.Kml = {
format: function (geoJson) { format(geoJson) {
// don't export properties as <ExtendedData>, probably no need for it // don't export properties as <ExtendedData>, probably no need for it
geoJson.features[0].properties = { name: geoJson.features[0].properties.name }; geoJson.features[0].properties = { name: geoJson.features[0].properties.name };
return BR.Xml.pretty(tokml(geoJson)); return BR.Xml.pretty(tokml(geoJson));

View file

@ -235,7 +235,7 @@
const wpt = { const wpt = {
ele: coord[2], ele: coord[2],
name: cmd.message, name: cmd.message,
extensions: extensions, extensions,
}; };
if (wpt.ele === undefined || wpt.ele === null) { if (wpt.ele === undefined || wpt.ele === null) {

View file

@ -2,7 +2,7 @@ BR.Xml = {
// modified version of // modified version of
// https://gist.github.com/sente/1083506#gistcomment-2254622 // https://gist.github.com/sente/1083506#gistcomment-2254622
// MIT License, Copyright (c) 2016 Stuart Powers, ES6 version by Jonathan Gruber // MIT License, Copyright (c) 2016 Stuart Powers, ES6 version by Jonathan Gruber
pretty: function (xml, indentSize = 1) { pretty(xml, indentSize = 1) {
const PADDING = ' '.repeat(indentSize); const PADDING = ' '.repeat(indentSize);
const newline = '\n'; const newline = '\n';

View file

@ -58,7 +58,7 @@
{ {
stateName: 'deactivate-draw', stateName: 'deactivate-draw',
icon: 'fa-pencil active', icon: 'fa-pencil active',
onClick: function (control) { onClick(control) {
routing.draw(false); routing.draw(false);
control.state('activate-draw'); control.state('activate-draw');
}, },
@ -70,7 +70,7 @@
{ {
stateName: 'activate-draw', stateName: 'activate-draw',
icon: 'fa-pencil', icon: 'fa-pencil',
onClick: function (control) { onClick(control) {
routing.draw(true); routing.draw(true);
control.state('deactivate-draw'); control.state('deactivate-draw');
}, },
@ -103,13 +103,13 @@
stateName: 'activate-beeline', stateName: 'activate-beeline',
icon: svg.replace(' active', ''), icon: svg.replace(' active', ''),
onClick: beelineClickHandler, onClick: beelineClickHandler,
title: title, title,
}, },
{ {
stateName: 'deactivate-beeline', stateName: 'deactivate-beeline',
icon: svg, icon: svg,
onClick: beelineClickHandler, onClick: beelineClickHandler,
title: title, title,
}, },
], ],
}); });
@ -188,10 +188,10 @@
}, },
], ],
value: ['route'], value: ['route'],
onShown: function () { onShown() {
$('button.bootbox-accept', $(this)).focus(); $('button.bootbox-accept', $(this)).focus();
}, },
callback: function (result) { callback(result) {
if (result !== null) { if (result !== null) {
if (result.indexOf('route') !== -1) { if (result.indexOf('route') !== -1) {
routing.clear(); routing.clear();
@ -290,10 +290,10 @@
routingOptions.setCustomProfile(null); routingOptions.setCustomProfile(null);
}); });
trackMessages = new BR.TrackMessages(map, { trackMessages = new BR.TrackMessages(map, {
requestUpdate: requestUpdate, requestUpdate,
}); });
trackAnalysis = new BR.TrackAnalysis(map, { trackAnalysis = new BR.TrackAnalysis(map, {
requestUpdate: requestUpdate, requestUpdate,
}); });
routingPathQuality = new BR.RoutingPathQuality(map, layersControl); routingPathQuality = new BR.RoutingPathQuality(map, layersControl);
@ -500,7 +500,7 @@
urlHash.onHashChangeCb = onHashChangeCb; urlHash.onHashChangeCb = onHashChangeCb;
urlHash.onInvalidHashChangeCb = onInvalidHashChangeCb; urlHash.onInvalidHashChangeCb = onInvalidHashChangeCb;
urlHash.init(map, { urlHash.init(map, {
layersControl: layersControl, layersControl,
}); });
// activate configured default base layer or first if no hash, // activate configured default base layer or first if no hash,

View file

@ -6,7 +6,7 @@ BR.BingLayer = L.BingLayer.extend({
' (<a target="_blank" href="https://go.microsoft.com/?linkid=9710837">TOU</a>)', ' (<a target="_blank" href="https://go.microsoft.com/?linkid=9710837">TOU</a>)',
}, },
initialize: function (key, options) { initialize(key, options) {
L.BingLayer.prototype.initialize.call(this, key, options); L.BingLayer.prototype.initialize.call(this, key, options);
this._logo = L.control({ position: 'bottomleft' }); this._logo = L.control({ position: 'bottomleft' });
@ -18,12 +18,12 @@ BR.BingLayer = L.BingLayer.extend({
}; };
}, },
onAdd: function (map) { onAdd(map) {
L.BingLayer.prototype.onAdd.call(this, map); L.BingLayer.prototype.onAdd.call(this, map);
map.addControl(this._logo); map.addControl(this._logo);
}, },
onRemove: function (map) { onRemove(map) {
L.BingLayer.prototype.onRemove.call(this, map); L.BingLayer.prototype.onRemove.call(this, map);
map.removeControl(this._logo); map.removeControl(this._logo);
}, },

View file

@ -20,14 +20,14 @@ BR.CircleGoArea = L.Control.extend({
}, },
}, },
initialize: function (routing, nogos, pois, options) { initialize(routing, nogos, pois, options) {
this.routing = routing; this.routing = routing;
this.nogos = nogos; this.nogos = nogos;
this.pois = pois; this.pois = pois;
L.setOptions(this, options); L.setOptions(this, options);
}, },
onAdd: function (map) { onAdd(map) {
var self = this; var self = this;
this.map = map; this.map = map;
@ -38,7 +38,7 @@ BR.CircleGoArea = L.Control.extend({
{ {
stateName: 'activate-circlego', stateName: 'activate-circlego',
icon: 'fa-circle-o', icon: 'fa-circle-o',
onClick: function () { onClick() {
self.draw(true); self.draw(true);
}, },
title: i18next.t('keyboard.generic-shortcut', { title: i18next.t('keyboard.generic-shortcut', {
@ -49,7 +49,7 @@ BR.CircleGoArea = L.Control.extend({
{ {
stateName: 'deactivate-circlego', stateName: 'deactivate-circlego',
icon: 'fa-circle-o active', icon: 'fa-circle-o active',
onClick: function () { onClick() {
self.draw(false); self.draw(false);
}, },
title: i18next.t('keyboard.generic-shortcut', { title: i18next.t('keyboard.generic-shortcut', {
@ -88,7 +88,7 @@ BR.CircleGoArea = L.Control.extend({
return container; return container;
}, },
draw: function (enable) { draw(enable) {
this.drawButton.state(enable ? 'deactivate-circlego' : 'activate-circlego'); this.drawButton.state(enable ? 'deactivate-circlego' : 'activate-circlego');
if (enable) { if (enable) {
this.routing.draw(false); this.routing.draw(false);
@ -109,7 +109,7 @@ BR.CircleGoArea = L.Control.extend({
} }
}, },
_keydownListener: function (e) { _keydownListener(e) {
if (!BR.Util.keyboardShortcutsAllowed(e)) { if (!BR.Util.keyboardShortcutsAllowed(e)) {
return; return;
} }
@ -120,7 +120,7 @@ BR.CircleGoArea = L.Control.extend({
} }
}, },
_getBoundary: function (center, adminLevel, adminLevelFallback) { _getBoundary(center, adminLevel, adminLevelFallback) {
adminLevel = adminLevel || 8; adminLevel = adminLevel || 8;
var query = var query =
'[out:json]; is_in(' + '[out:json]; is_in(' +
@ -165,7 +165,7 @@ BR.CircleGoArea = L.Control.extend({
); );
}, },
_setBoundary: function (geoJson) { _setBoundary(geoJson) {
// drop admin_centre nodes // drop admin_centre nodes
geoJson.features = geoJson.features.filter(function (feature) { geoJson.features = geoJson.features.filter(function (feature) {
return feature.geometry.type !== 'Point'; return feature.geometry.type !== 'Point';
@ -173,7 +173,7 @@ BR.CircleGoArea = L.Control.extend({
var boundaryLine = turf.polygonToLine(geoJson.features[0]); var boundaryLine = turf.polygonToLine(geoJson.features[0]);
this.boundaryLayer = L.geoJson(boundaryLine, { this.boundaryLayer = L.geoJson(boundaryLine, {
style: function (feature) { style(feature) {
return { return {
weight: 1, weight: 1,
color: 'black', color: 'black',
@ -199,7 +199,7 @@ BR.CircleGoArea = L.Control.extend({
this.setOutsideArea(ring); this.setOutsideArea(ring);
}, },
_getPolygonForPoint: function (center, featureCollection) { _getPolygonForPoint(center, featureCollection) {
var polygon = null; var polygon = null;
var point = turf.point(center); var point = turf.point(center);
@ -216,15 +216,15 @@ BR.CircleGoArea = L.Control.extend({
return polygon; return polygon;
}, },
_getState: function (center) { _getState(center) {
return this._getPolygonForPoint(center, this.states); return this._getPolygonForPoint(center, this.states);
}, },
_getCountry: function (center) { _getCountry(center) {
return this._getPolygonForPoint(center, this.countries); return this._getPolygonForPoint(center, this.countries);
}, },
_applyStateRules: function (center) { _applyStateRules(center) {
var state = this._getState(center); var state = this._getState(center);
if (state) { if (state) {
@ -255,7 +255,7 @@ BR.CircleGoArea = L.Control.extend({
} }
}, },
_applyCountryRules: function (center) { _applyCountryRules(center) {
var country = this._getCountry(center); var country = this._getCountry(center);
if (country) { if (country) {
@ -294,7 +294,7 @@ BR.CircleGoArea = L.Control.extend({
}, },
// debugging // debugging
_logStates: function (states) { _logStates(states) {
for (var i = 0; i < states.features.length; i++) { for (var i = 0; i < states.features.length; i++) {
var state = states.features[i]; var state = states.features[i];
console.log( console.log(
@ -304,12 +304,12 @@ BR.CircleGoArea = L.Control.extend({
}, },
// debugging // debugging
_addGeoJsonLayer: function (states, options) { _addGeoJsonLayer(states, options) {
// delay, otherwise triggers premature hash update through mapmove // delay, otherwise triggers premature hash update through mapmove
setTimeout( setTimeout(
L.bind(function () { L.bind(function () {
L.geoJson(states, { L.geoJson(states, {
style: function (feature) { style(feature) {
return L.extend( return L.extend(
{ {
weight: 1, weight: 1,
@ -327,7 +327,7 @@ BR.CircleGoArea = L.Control.extend({
); );
}, },
_loadStates: function () { _loadStates() {
if (this.statesLoading) return; if (this.statesLoading) return;
this.statesLoading = true; this.statesLoading = true;
@ -349,7 +349,7 @@ BR.CircleGoArea = L.Control.extend({
); );
}, },
_loadCountries: function () { _loadCountries() {
BR.Util.getJson( BR.Util.getJson(
this.options.countriesUrl, this.options.countriesUrl,
'countries', 'countries',
@ -364,7 +364,7 @@ BR.CircleGoArea = L.Control.extend({
renderer: this.maskRenderer, renderer: this.maskRenderer,
// use Leaflet.snogylop plugin here, turf.mask too slow (~4s) for some reason // use Leaflet.snogylop plugin here, turf.mask too slow (~4s) for some reason
invert: true, invert: true,
style: function (feature) { style(feature) {
return { return {
weight: 1, weight: 1,
color: 'darkgreen', color: 'darkgreen',
@ -388,25 +388,25 @@ BR.CircleGoArea = L.Control.extend({
); );
}, },
_setNogo: function (ring) { _setNogo(ring) {
this.nogoPolylines = L.geoJson(ring, BR.NogoAreas.prototype.polylineOptions); this.nogoPolylines = L.geoJson(ring, BR.NogoAreas.prototype.polylineOptions);
this.nogos.addNogos(null, this.nogoPolylines.getLayers(), null); this.nogos.addNogos(null, this.nogoPolylines.getLayers(), null);
}, },
_removeNogo: function () { _removeNogo() {
if (this.nogoPolylines) { if (this.nogoPolylines) {
this.nogos.removeNogos(null, this.nogoPolylines.getLayers(), null); this.nogos.removeNogos(null, this.nogoPolylines.getLayers(), null);
this.nogoPolylines = null; this.nogoPolylines = null;
} }
}, },
_setNogoCircle: function (center) { _setNogoCircle(center) {
var polygon = this.circleToPolygon(center, this.radius); var polygon = this.circleToPolygon(center, this.radius);
this._setNogo(polygon); this._setNogo(polygon);
this.setOutsideArea(polygon); this.setOutsideArea(polygon);
}, },
setNogoRing: function (center) { setNogoRing(center) {
this._clearLayers(); this._clearLayers();
this._removeNogo(); this._removeNogo();
@ -428,7 +428,7 @@ BR.CircleGoArea = L.Control.extend({
} }
}, },
_lockOutsideArea: function () { _lockOutsideArea() {
if (this.outsideArea) { if (this.outsideArea) {
this.outsideArea.eachLayer(function (layer) { this.outsideArea.eachLayer(function (layer) {
layer._path.classList.add('circlego-outside'); layer._path.classList.add('circlego-outside');
@ -437,7 +437,7 @@ BR.CircleGoArea = L.Control.extend({
} }
}, },
_unlockOutsideArea: function () { _unlockOutsideArea() {
if (this.outsideArea) { if (this.outsideArea) {
this.outsideArea.eachLayer(function (layer) { this.outsideArea.eachLayer(function (layer) {
layer._path.classList.remove('circlego-outside'); layer._path.classList.remove('circlego-outside');
@ -446,12 +446,12 @@ BR.CircleGoArea = L.Control.extend({
} }
}, },
setOutsideArea: function (ring) { setOutsideArea(ring) {
var mask = turf.mask(turf.polygonize(ring)); var mask = turf.mask(turf.polygonize(ring));
this.outsideArea = L.geoJson(mask, { this.outsideArea = L.geoJson(mask, {
renderer: this.maskRenderer, renderer: this.maskRenderer,
style: function (feature) { style(feature) {
return { return {
weight: 4, weight: 4,
color: 'black', color: 'black',
@ -466,11 +466,11 @@ BR.CircleGoArea = L.Control.extend({
this._lockOutsideArea(); this._lockOutsideArea();
}, },
onMapClick: function (e) { onMapClick(e) {
this.setCircle([e.latlng.lng, e.latlng.lat]); this.setCircle([e.latlng.lng, e.latlng.lat]);
}, },
setOptions: function (opts) { setOptions(opts) {
this.radius = opts.circlego[2]; this.radius = opts.circlego[2];
if (opts.polylines) { if (opts.polylines) {
this.nogoPolylines = L.featureGroup(opts.polylines, BR.NogoAreas.prototype.polylineOptions); this.nogoPolylines = L.featureGroup(opts.polylines, BR.NogoAreas.prototype.polylineOptions);
@ -478,7 +478,7 @@ BR.CircleGoArea = L.Control.extend({
this.setCircle([opts.circlego[0], opts.circlego[1]], opts.polylines); this.setCircle([opts.circlego[0], opts.circlego[1]], opts.polylines);
}, },
setCircle: function (center, polylines) { setCircle(center, polylines) {
var marker = (this.marker = this._createMarker(center)); var marker = (this.marker = this._createMarker(center));
this.clear(); this.clear();
@ -503,7 +503,7 @@ BR.CircleGoArea = L.Control.extend({
this.draw(false); this.draw(false);
}, },
_createMarker: function (center) { _createMarker(center) {
var self = this; var self = this;
var icon = (this.icon = L.VectorMarkers.icon({ var icon = (this.icon = L.VectorMarkers.icon({
icon: 'home', icon: 'home',
@ -519,7 +519,7 @@ BR.CircleGoArea = L.Control.extend({
'<button id="remove-ringgo-marker" class="btn btn-secondary"><i class="fa fa-trash"></i></button>'; '<button id="remove-ringgo-marker" class="btn btn-secondary"><i class="fa fa-trash"></i></button>';
var marker = L.marker([center[1], center[0]], { var marker = L.marker([center[1], center[0]], {
icon: icon, icon,
draggable: true, draggable: true,
// prevent being on top of route markers // prevent being on top of route markers
zIndexOffset: -500, zIndexOffset: -500,
@ -547,7 +547,7 @@ BR.CircleGoArea = L.Control.extend({
return marker; return marker;
}, },
_onPopupOpen: function (popup, popupContent) { _onPopupOpen(popup, popupContent) {
var exportName = ''; var exportName = '';
var html = '<p>'; var html = '<p>';
if (this.radius) { if (this.radius) {
@ -580,7 +580,7 @@ BR.CircleGoArea = L.Control.extend({
if (this.nogoPolylines) { if (this.nogoPolylines) {
var link = location.href.replace(/&polylines=[^&]*/, ''); var link = location.href.replace(/&polylines=[^&]*/, '');
var geoJson = this.nogoPolylines.toGeoJSON(); var geoJson = this.nogoPolylines.toGeoJSON();
var gpx = togpx(geoJson, { metadata: { name: exportName, link: link } }); var gpx = togpx(geoJson, { metadata: { name: exportName, link } });
this._setDownloadUrl(gpx, 'application/gpx+xml', 'ringgo-download-gpx'); this._setDownloadUrl(gpx, 'application/gpx+xml', 'ringgo-download-gpx');
this._setDownloadUrl( this._setDownloadUrl(
JSON.stringify(geoJson, null, 2), JSON.stringify(geoJson, null, 2),
@ -599,12 +599,12 @@ BR.CircleGoArea = L.Control.extend({
); );
}, },
_onPopupClose: function (evt) { _onPopupClose(evt) {
this._revokeDownloadUrl('ringgo-download-gpx'); this._revokeDownloadUrl('ringgo-download-gpx');
this._revokeDownloadUrl('ringgo-download-geojson'); this._revokeDownloadUrl('ringgo-download-geojson');
}, },
_setDownloadUrl: function (text, mimeType, elementId) { _setDownloadUrl(text, mimeType, elementId) {
var blob = new Blob([text], { var blob = new Blob([text], {
type: mimeType + ';charset=utf-8', type: mimeType + ';charset=utf-8',
}); });
@ -613,14 +613,14 @@ BR.CircleGoArea = L.Control.extend({
download.href = objectUrl; download.href = objectUrl;
}, },
_revokeDownloadUrl: function (elementId) { _revokeDownloadUrl(elementId) {
var download = document.getElementById(elementId); var download = document.getElementById(elementId);
if (download) { if (download) {
URL.revokeObjectURL(download.href); URL.revokeObjectURL(download.href);
} }
}, },
_clearLayers: function () { _clearLayers() {
if (this.outsideArea) { if (this.outsideArea) {
this.map.removeLayer(this.outsideArea); this.map.removeLayer(this.outsideArea);
this.outsideArea = null; this.outsideArea = null;
@ -631,16 +631,16 @@ BR.CircleGoArea = L.Control.extend({
} }
}, },
clear: function () { clear() {
this.circleLayer.clearLayers(); this.circleLayer.clearLayers();
this._clearLayers(); this._clearLayers();
}, },
getButton: function () { getButton() {
return this.drawButton; return this.drawButton;
}, },
getCircle: function () { getCircle() {
var circle = this.circleLayer.getLayers().map(function (it) { var circle = this.circleLayer.getLayers().map(function (it) {
return it.getLatLng(); return it.getLatLng();
}); });
@ -651,15 +651,15 @@ BR.CircleGoArea = L.Control.extend({
} }
}, },
toRadians: function (angleInDegrees) { toRadians(angleInDegrees) {
return (angleInDegrees * Math.PI) / 180; return (angleInDegrees * Math.PI) / 180;
}, },
toDegrees: function (angleInRadians) { toDegrees(angleInRadians) {
return (angleInRadians * 180) / Math.PI; return (angleInRadians * 180) / Math.PI;
}, },
offset: function (c1, distance, bearing) { offset(c1, distance, bearing) {
var lon1 = this.toRadians(c1[0]); var lon1 = this.toRadians(c1[0]);
var lat1 = this.toRadians(c1[1]); var lat1 = this.toRadians(c1[1]);
var dByR = distance / 6378137; // distance divided by 6378137 (radius of the earth) wgs84 var dByR = distance / 6378137; // distance divided by 6378137 (radius of the earth) wgs84
@ -673,7 +673,7 @@ BR.CircleGoArea = L.Control.extend({
return [this.toDegrees(lon), this.toDegrees(lat)]; return [this.toDegrees(lon), this.toDegrees(lat)];
}, },
circleToPolygon: function (center, radius, numberOfSegments) { circleToPolygon(center, radius, numberOfSegments) {
var n = numberOfSegments ? numberOfSegments : 64; var n = numberOfSegments ? numberOfSegments : 64;
var inner = []; var inner = [];

View file

@ -11,49 +11,137 @@ BR.Heightgraph = function (map, layersControl, routing, pois) {
expandControls: false, expandControls: false,
mappings: { mappings: {
gradient: { gradient: {
'-16': {
text: '< -15%',
color: '#81A850',
},
'-15': {
text: '-15%',
color: '#89AA55',
},
'-14': {
text: '-14%',
color: '#91AD59',
},
'-13': {
text: '-13%',
color: '#99AF5E',
},
'-12': {
text: '-12%',
color: '#A1B162',
},
'-11': {
text: '-11%',
color: '#A8B367',
},
'-10': {
text: '-10%',
color: '#B0B66B',
},
'-9': {
text: '-9%',
color: '#B8B870',
},
'-8': {
text: '-8%',
color: '#C0BA75',
},
'-7': {
text: '-7%',
color: '#C8BC79',
},
'-6': {
text: '-6%',
color: '#D0BF7E',
},
'-5': { '-5': {
text: '- 16%+', text: '-5%',
color: '#028306', color: '#D8C182',
}, },
'-4': { '-4': {
text: '- 10-15%', text: '-4%',
color: '#2AA12E', color: '#E0C387',
}, },
'-3': { '-3': {
text: '- 7-9%', text: '-3%',
color: '#53BF56', color: '#E7C58B',
}, },
'-2': { '-2': {
text: '- 4-6%', text: '-2%',
color: '#7BDD7E', color: '#EFC890',
}, },
'-1': { '-1': {
text: '- 1-3%', text: '-1%',
color: '#A4FBA6', color: '#F7CA94',
}, },
0: { 0: {
text: '0%', text: '0%',
color: '#ffcc99', color: '#FFCC99',
}, },
1: { 1: {
text: '1-3%', text: '1%',
color: '#F29898', color: '#FCC695',
}, },
2: { 2: {
text: '4-6%', text: '2%',
color: '#E07575', color: '#FAC090',
}, },
3: { 3: {
text: '7-9%', text: '3%',
color: '#CF5352', color: '#F7BA8C',
}, },
4: { 4: {
text: '10-15%', text: '4%',
color: '#BE312F', color: '#F5B588',
}, },
5: { 5: {
text: '16%+', text: '5%',
color: '#AD0F0C', color: '#F2AF83',
},
6: {
text: '6%',
color: '#F0A97F',
},
7: {
text: '7%',
color: '#EDA37A',
},
8: {
text: '8%',
color: '#EB9D76',
},
9: {
text: '9%',
color: '#E89772',
},
10: {
text: '10%',
color: '#E5916D',
},
11: {
text: '11%',
color: '#E38B69',
},
12: {
text: '12%',
color: '#E08665',
},
13: {
text: '13%',
color: '#DE8060',
},
14: {
text: '14%',
color: '#DB7A5C',
},
15: {
text: '15%',
color: '#D97457',
},
16: {
text: '> 15%',
color: '#D66E53',
}, },
}, },
}, },
@ -63,7 +151,7 @@ BR.Heightgraph = function (map, layersControl, routing, pois) {
}, },
}, },
addBelow: function (map) { addBelow(map) {
// waiting for https://github.com/MrMufflon/Leaflet.Elevation/pull/66 // waiting for https://github.com/MrMufflon/Leaflet.Elevation/pull/66
// this.width($('#map').outerWidth()); // this.width($('#map').outerWidth());
this.options.width = $('#content').outerWidth(); this.options.width = $('#content').outerWidth();
@ -75,6 +163,7 @@ BR.Heightgraph = function (map, layersControl, routing, pois) {
function setParent(el, newParent) { function setParent(el, newParent) {
newParent.appendChild(el); newParent.appendChild(el);
} }
this.addTo(map); this.addTo(map);
// move elevation graph outside of the map // move elevation graph outside of the map
@ -114,7 +203,7 @@ BR.Heightgraph = function (map, layersControl, routing, pois) {
this.update(); this.update();
}, },
initCollapse: function (map) { initCollapse(map) {
var self = this; var self = this;
var onHide = function () { var onHide = function () {
$('#elevation-btn').removeClass('active'); $('#elevation-btn').removeClass('active');
@ -143,13 +232,13 @@ BR.Heightgraph = function (map, layersControl, routing, pois) {
}); });
}, },
_keydownListener: function (e) { _keydownListener(e) {
if (BR.Util.keyboardShortcutsAllowed(e) && e.keyCode === this.options.shortcut.toggle) { if (BR.Util.keyboardShortcutsAllowed(e) && e.keyCode === this.options.shortcut.toggle) {
$('#elevation-btn').click(); $('#elevation-btn').click();
} }
}, },
update: function (track, layer) { update(track, layer) {
// bring height indicator to front, because of track casing in BR.Routing // bring height indicator to front, because of track casing in BR.Routing
if (this._mouseHeightFocus) { if (this._mouseHeightFocus) {
var g = this._mouseHeightFocus._groups[0][0].parentNode; var g = this._mouseHeightFocus._groups[0][0].parentNode;
@ -167,7 +256,11 @@ BR.Heightgraph = function (map, layersControl, routing, pois) {
} else { } else {
$('#no-elevation-data').hide(); $('#no-elevation-data').hide();
} }
var geojsonFeatures = geoDataExchange.buildGeojsonFeatures(track.getLatLngs());
var geojsonFeatures = geoDataExchange.buildGeojsonFeatures(track.getLatLngs(), {
interpolate: false,
normalize: false,
});
this.addData(geojsonFeatures); this.addData(geojsonFeatures);
// re-add handlers // re-add handlers
@ -197,6 +290,109 @@ BR.Heightgraph = function (map, layersControl, routing, pois) {
$('#elevation-chart').collapse('hide'); $('#elevation-chart').collapse('hide');
} }
}, },
_createLegend() {
if (this._categories.length > 0) {
// find the min and the max gradients for the current profile
var minGradient = 16;
var maxGradient = -16;
// this legend object has the profile gradients as keys; it was built by heightgraph
var allLegend = this._categories[this.options.selectedAttributeIdx].legend;
for (key in allLegend) {
var gradient = parseInt(key);
if (minGradient > gradient) {
minGradient = gradient;
}
if (maxGradient < gradient) {
maxGradient = gradient;
}
}
// define the simplified legend with all known gradients
var simplifiedLegend = [
{
type: -16,
text: this.options.mappings.gradient['-16'].text,
color: this.options.mappings.gradient['-16'].color,
},
{
type: -10,
text: this.options.mappings.gradient['-10'].text,
color: this.options.mappings.gradient['-10'].color,
},
{
type: -5,
text: this.options.mappings.gradient['-5'].text,
color: this.options.mappings.gradient['-5'].color,
},
{
type: 0,
text: this.options.mappings.gradient['0'].text,
color: this.options.mappings.gradient['0'].color,
},
{
type: 5,
text: this.options.mappings.gradient['5'].text,
color: this.options.mappings.gradient['5'].color,
},
{
type: 10,
text: this.options.mappings.gradient['10'].text,
color: this.options.mappings.gradient['10'].color,
},
{
type: 16,
text: this.options.mappings.gradient['16'].text,
color: this.options.mappings.gradient['16'].color,
},
];
// then, keep only the range relevant to the current profile
// (e.g. if min gradient of profile is -6, remove -16 and -15 from range)
for (var i = 0; i < simplifiedLegend.length; i++) {
if (simplifiedLegend[i].type > minGradient) {
simplifiedLegend.splice(0, i - 1);
break;
}
}
for (var i = simplifiedLegend.length - 1; i > -1; i--) {
if (simplifiedLegend[i].type < maxGradient) {
simplifiedLegend.splice(i + 2);
break;
}
}
this._categories[this.options.selectedAttributeIdx].legend = simplifiedLegend;
}
var existingLegend = document.querySelector('.legend-container');
if (existingLegend !== null) {
existingLegend.remove();
}
var legend = L.DomUtil.create('div', 'legend-container', this._container);
// hack to keep the chart from getting too tall,
// and to keep it from growing vertically on window resize
legend.style.setProperty('position', 'absolute');
// naively align the legend vertically with the y-axis
legend.style.setProperty('margin-left', '65px');
legend.style.setProperty('margin-top', '-18px');
var legendLabel = L.DomUtil.create('span', 'legend-hover legend-text', legend);
legendLabel.textContent = this._getTranslation('legend') + ':';
this._categories[this.options.selectedAttributeIdx].legend.forEach((l) => {
var color = L.DomUtil.create('span', 'legend-rect', legend);
color.style.setProperty('padding-left', '10px');
color.style.setProperty('padding-right', '3px');
color.style.setProperty('width', '6px');
color.style.setProperty('height', '6px');
color.style.setProperty('color', l.color);
color.innerHTML = '&#9632;';
var label = L.DomUtil.create('span', 'legend-text', legend);
label.textContent = l.text;
});
},
}); });
var heightgraphControl = new Heightgraph(); var heightgraphControl = new Heightgraph();

View file

@ -40,11 +40,11 @@ BR.NogoAreas = L.Control.extend({
smoothFactor: 0.5, smoothFactor: 0.5,
}, },
initialize: function () { initialize() {
this._wasRouteDrawing = false; this._wasRouteDrawing = false;
}, },
onAdd: function (map) { onAdd(map) {
var self = this; var self = this;
$('#submitNogos').on('click', L.bind(this.uploadNogos, this)); $('#submitNogos').on('click', L.bind(this.uploadNogos, this));
@ -149,7 +149,7 @@ BR.NogoAreas = L.Control.extend({
return L.DomUtil.create('div'); return L.DomUtil.create('div');
}, },
_keydownListener: function (e) { _keydownListener(e) {
if (!BR.Util.keyboardShortcutsAllowed(e)) { if (!BR.Util.keyboardShortcutsAllowed(e)) {
return; return;
} }
@ -170,17 +170,17 @@ BR.NogoAreas = L.Control.extend({
} }
}, },
displayUploadError: function (message) { displayUploadError(message) {
$('#nogoError').text(message ? message : ''); $('#nogoError').text(message ? message : '');
$('#nogoError').css('display', message ? 'block' : 'none'); $('#nogoError').css('display', message ? 'block' : 'none');
}, },
onFileChanged: function (e) { onFileChanged(e) {
if (!e.target.files[0]) return; if (!e.target.files[0]) return;
$(e.target).next('label').text(e.target.files[0].name); $(e.target).next('label').text(e.target.files[0].name);
}, },
uploadNogos: function () { uploadNogos() {
var self = this; var self = this;
var geoJSONPromise; var geoJSONPromise;
@ -253,7 +253,7 @@ BR.NogoAreas = L.Control.extend({
} }
var geoJSON = L.geoJson(turf.featureCollection(cleanedGeoJSONFeatures), { var geoJSON = L.geoJson(turf.featureCollection(cleanedGeoJSONFeatures), {
onEachFeature: function (feature, layer) { onEachFeature(feature, layer) {
layer.options.nogoWeight = feature.properties.nogoWeight || nogoWeight; layer.options.nogoWeight = feature.properties.nogoWeight || nogoWeight;
if (feature.geometry.type === 'LineString') { if (feature.geometry.type === 'LineString') {
L.setOptions(layer, self.polylineOptions); L.setOptions(layer, self.polylineOptions);
@ -266,7 +266,7 @@ BR.NogoAreas = L.Control.extend({
nogosPoints = nogosPoints.map(function (item) { nogosPoints = nogosPoints.map(function (item) {
var radius = item.feature.properties.radius || nogoRadius; var radius = item.feature.properties.radius || nogoRadius;
if (radius > 0) { if (radius > 0) {
return L.circle(item.getLatLng(), { radius: radius }); return L.circle(item.getLatLng(), { radius });
} }
return null; return null;
}); });
@ -303,7 +303,7 @@ BR.NogoAreas = L.Control.extend({
}, },
// prevent route waypoint added after circle create (map click after up) // prevent route waypoint added after circle create (map click after up)
preventRoutePointOnCreate: function (routing) { preventRoutePointOnCreate(routing) {
this.editTools.on( this.editTools.on(
'editable:drawing:start', 'editable:drawing:start',
function (e) { function (e) {
@ -327,7 +327,7 @@ BR.NogoAreas = L.Control.extend({
); );
}, },
getOptions: function () { getOptions() {
return { return {
nogos: this.drawnItems.getLayers().filter(function (e) { nogos: this.drawnItems.getLayers().filter(function (e) {
return e instanceof L.Circle; return e instanceof L.Circle;
@ -341,7 +341,7 @@ BR.NogoAreas = L.Control.extend({
}; };
}, },
setOptions: function (options) { setOptions(options) {
var nogos = options.nogos; var nogos = options.nogos;
var polylines = options.polylines; var polylines = options.polylines;
var polygons = options.polygons; var polygons = options.polygons;
@ -349,12 +349,12 @@ BR.NogoAreas = L.Control.extend({
this._addNogos(nogos, polylines, polygons); this._addNogos(nogos, polylines, polygons);
}, },
addNogos: function (nogos, polylines, polygons) { addNogos(nogos, polylines, polygons) {
this._addNogos(nogos, polylines, polygons); this._addNogos(nogos, polylines, polygons);
this._fireUpdate(); this._fireUpdate();
}, },
_addNogos: function (nogos, polylines, polygons) { _addNogos(nogos, polylines, polygons) {
if (nogos) { if (nogos) {
for (var i = 0; i < nogos.length; i++) { for (var i = 0; i < nogos.length; i++) {
nogos[i].setStyle(this.style); nogos[i].setStyle(this.style);
@ -375,7 +375,7 @@ BR.NogoAreas = L.Control.extend({
} }
}, },
removeNogos: function (nogos, polylines, polygons) { removeNogos(nogos, polylines, polygons) {
if (nogos) { if (nogos) {
for (var i = 0; i < nogos.length; i++) { for (var i = 0; i < nogos.length; i++) {
this.drawnItems.removeLayer(nogos[i]); this.drawnItems.removeLayer(nogos[i]);
@ -395,28 +395,28 @@ BR.NogoAreas = L.Control.extend({
this._fireUpdate(); this._fireUpdate();
}, },
_clear: function () { _clear() {
this.drawnItems.clearLayers(); this.drawnItems.clearLayers();
}, },
clear: function () { clear() {
this._clear(); this._clear();
this._fireUpdate(); this._fireUpdate();
}, },
_fireUpdate: function () { _fireUpdate() {
this.fire('update', { options: this.getOptions() }); this.fire('update', { options: this.getOptions() });
}, },
getFeatureGroup: function () { getFeatureGroup() {
return this.drawnItems; return this.drawnItems;
}, },
getEditGroup: function () { getEditGroup() {
return this.editTools.editLayer; return this.editTools.editLayer;
}, },
getButton: function () { getButton() {
return this.button; return this.button;
}, },
}); });
@ -430,7 +430,7 @@ BR.Editable = L.Editable.extend({
// Also, we generally disable the Tap handler in the map options for route dragging, // Also, we generally disable the Tap handler in the map options for route dragging,
// see Map.js, so we always need to enable for drawing. // see Map.js, so we always need to enable for drawing.
initialize: function (map, options) { initialize(map, options) {
L.Editable.prototype.initialize.call(this, map, options); L.Editable.prototype.initialize.call(this, map, options);
if (!this.map.tap) { if (!this.map.tap) {
@ -439,7 +439,7 @@ BR.Editable = L.Editable.extend({
} }
}, },
registerForDrawing: function (editor) { registerForDrawing(editor) {
this._tapEnabled = this.map.tap.enabled(); this._tapEnabled = this.map.tap.enabled();
if (!this._tapEnabled) { if (!this._tapEnabled) {
this.map.tap.enable(); this.map.tap.enable();
@ -448,7 +448,7 @@ BR.Editable = L.Editable.extend({
L.Editable.prototype.registerForDrawing.call(this, editor); L.Editable.prototype.registerForDrawing.call(this, editor);
}, },
unregisterForDrawing: function (editor) { unregisterForDrawing(editor) {
if (!this._tapEnabled) { if (!this._tapEnabled) {
this.map.tap.disable(); this.map.tap.disable();
} }
@ -456,7 +456,7 @@ BR.Editable = L.Editable.extend({
L.Editable.prototype.unregisterForDrawing.call(this, editor); L.Editable.prototype.unregisterForDrawing.call(this, editor);
}, },
createVertexIcon: function (options) { createVertexIcon(options) {
return BR.Browser.touch ? new L.Editable.TouchVertexIcon(options) : new L.Editable.VertexIcon(options); return BR.Browser.touch ? new L.Editable.TouchVertexIcon(options) : new L.Editable.VertexIcon(options);
}, },
}); });
@ -466,13 +466,13 @@ BR.EditingTooltip = L.Handler.extend({
closeTimeout: 2000, closeTimeout: 2000,
}, },
initialize: function (map, editTools, button) { initialize(map, editTools, button) {
this.map = map; this.map = map;
this.editTools = editTools; this.editTools = editTools;
this.button = button; this.button = button;
}, },
addHooks: function () { addHooks() {
// hack: listen to EasyButton click (instead of editable:drawing:start), // hack: listen to EasyButton click (instead of editable:drawing:start),
// to get mouse position from event for initial tooltip location // to get mouse position from event for initial tooltip location
L.DomEvent.addListener(this.button.button, 'click', this._addCreate, this); L.DomEvent.addListener(this.button.button, 'click', this._addCreate, this);
@ -484,7 +484,7 @@ BR.EditingTooltip = L.Handler.extend({
this.editTools.on('editable:disable', this._disable, this); this.editTools.on('editable:disable', this._disable, this);
}, },
removeHooks: function () { removeHooks() {
L.DomEvent.removeListener(this.button.button, 'click', this._addCreate, this); L.DomEvent.removeListener(this.button.button, 'click', this._addCreate, this);
this.editTools.featuresLayer.off('layeradd', this._bind, this); this.editTools.featuresLayer.off('layeradd', this._bind, this);
@ -494,7 +494,7 @@ BR.EditingTooltip = L.Handler.extend({
this.editTools.off('editable:disable', this._disable, this); this.editTools.off('editable:disable', this._disable, this);
}, },
_bind: function (e) { _bind(e) {
// Position tooltip at bottom of circle, less distracting than // Position tooltip at bottom of circle, less distracting than
// sticky with cursor or at center. // sticky with cursor or at center.
@ -517,7 +517,7 @@ BR.EditingTooltip = L.Handler.extend({
}; };
}, },
_addCreate: function (e) { _addCreate(e) {
// button cancel // button cancel
if (!this.editTools.drawing()) return; if (!this.editTools.drawing()) return;
@ -564,7 +564,7 @@ BR.EditingTooltip = L.Handler.extend({
} }
}, },
_setCloseTimeout: function (layer) { _setCloseTimeout(layer) {
var timeoutId = setTimeout(function () { var timeoutId = setTimeout(function () {
layer.closeTooltip(); layer.closeTooltip();
}, this.options.closeTimeout); }, this.options.closeTimeout);
@ -575,7 +575,7 @@ BR.EditingTooltip = L.Handler.extend({
}); });
}, },
_postCreate: function () { _postCreate() {
// editing is disabled by another handler, tooltip won't stay open before // editing is disabled by another handler, tooltip won't stay open before
this.editTools.once( this.editTools.once(
'editable:disable', 'editable:disable',
@ -588,7 +588,7 @@ BR.EditingTooltip = L.Handler.extend({
); );
}, },
_enable: function (e) { _enable(e) {
e.layer.setTooltipContent(BR.NogoAreas.MSG_ENABLED); e.layer.setTooltipContent(BR.NogoAreas.MSG_ENABLED);
this.editTools.once( this.editTools.once(
@ -600,42 +600,42 @@ BR.EditingTooltip = L.Handler.extend({
); );
}, },
_disable: function (e) { _disable(e) {
e.layer.setTooltipContent(BR.NogoAreas.MSG_DISABLED); e.layer.setTooltipContent(BR.NogoAreas.MSG_DISABLED);
this._setCloseTimeout(e.layer); this._setCloseTimeout(e.layer);
}, },
}); });
BR.DeletableCircleEditor = L.Editable.CircleEditor.extend({ BR.DeletableCircleEditor = L.Editable.CircleEditor.extend({
_computeDeleteLatLng: function () { _computeDeleteLatLng() {
// While circle is not added to the map, _radius is not set. // While circle is not added to the map, _radius is not set.
var delta = (this.feature._radius || this.feature._mRadius) * Math.cos(Math.PI / 4), var delta = (this.feature._radius || this.feature._mRadius) * Math.cos(Math.PI / 4),
point = this.map.project(this.feature._latlng); point = this.map.project(this.feature._latlng);
return this.map.unproject([point.x - delta, point.y - delta]); return this.map.unproject([point.x - delta, point.y - delta]);
}, },
_updateDeleteLatLng: function () { _updateDeleteLatLng() {
this._deleteLatLng.update(this._computeDeleteLatLng()); this._deleteLatLng.update(this._computeDeleteLatLng());
this._deleteLatLng.__vertex.update(); this._deleteLatLng.__vertex.update();
}, },
_addDeleteMarker: function () { _addDeleteMarker() {
if (!this.enabled()) return; if (!this.enabled()) return;
this._deleteLatLng = this._computeDeleteLatLng(); this._deleteLatLng = this._computeDeleteLatLng();
return new BR.DeleteMarker(this._deleteLatLng, this); return new BR.DeleteMarker(this._deleteLatLng, this);
}, },
_delete: function () { _delete() {
this.disable(); this.disable();
this.tools.featuresLayer.removeLayer(this.feature); this.tools.featuresLayer.removeLayer(this.feature);
}, },
delete: function () { delete() {
this._delete(); this._delete();
this.fireAndForward('editable:deleted'); this.fireAndForward('editable:deleted');
}, },
initialize: function (map, feature, options) { initialize(map, feature, options) {
L.Editable.CircleEditor.prototype.initialize.call(this, map, feature, options); L.Editable.CircleEditor.prototype.initialize.call(this, map, feature, options);
this._deleteLatLng = this._computeDeleteLatLng(); this._deleteLatLng = this._computeDeleteLatLng();
@ -643,7 +643,7 @@ BR.DeletableCircleEditor = L.Editable.CircleEditor.extend({
this.editLayer = new L.FeatureGroup(); this.editLayer = new L.FeatureGroup();
}, },
addHooks: function () { addHooks() {
L.Editable.CircleEditor.prototype.addHooks.call(this); L.Editable.CircleEditor.prototype.addHooks.call(this);
if (this.feature) { if (this.feature) {
this._addDeleteMarker(); this._addDeleteMarker();
@ -651,12 +651,12 @@ BR.DeletableCircleEditor = L.Editable.CircleEditor.extend({
return this; return this;
}, },
reset: function () { reset() {
L.Editable.CircleEditor.prototype.reset.call(this); L.Editable.CircleEditor.prototype.reset.call(this);
this._addDeleteMarker(); this._addDeleteMarker();
}, },
onDrawingMouseDown: function (e) { onDrawingMouseDown(e) {
this._deleteLatLng.update(e.latlng); this._deleteLatLng.update(e.latlng);
L.Editable.CircleEditor.prototype.onDrawingMouseDown.call(this, e); L.Editable.CircleEditor.prototype.onDrawingMouseDown.call(this, e);
}, },
@ -664,7 +664,7 @@ BR.DeletableCircleEditor = L.Editable.CircleEditor.extend({
// override to cancel/remove created circle when added by click instead of drag, because: // override to cancel/remove created circle when added by click instead of drag, because:
// - without resize, edit handles stacked on top of each other // - without resize, edit handles stacked on top of each other
// - makes event handling more complicated (editable:vertex:dragend not called) // - makes event handling more complicated (editable:vertex:dragend not called)
onDrawingMouseUp: function (e) { onDrawingMouseUp(e) {
if (this.feature.getRadius() > 0) { if (this.feature.getRadius() > 0) {
this.commitDrawing(e); this.commitDrawing(e);
} else { } else {
@ -675,7 +675,7 @@ BR.DeletableCircleEditor = L.Editable.CircleEditor.extend({
L.Editable.PathEditor.prototype.onDrawingMouseUp.call(this, e); L.Editable.PathEditor.prototype.onDrawingMouseUp.call(this, e);
}, },
onVertexMarkerDrag: function (e) { onVertexMarkerDrag(e) {
this._updateDeleteLatLng(); this._updateDeleteLatLng();
L.Editable.CircleEditor.prototype.onVertexMarkerDrag.call(this, e); L.Editable.CircleEditor.prototype.onVertexMarkerDrag.call(this, e);
}, },
@ -690,7 +690,7 @@ BR.DeleteMarker = L.Marker.extend({
}), }),
}, },
initialize: function (latlng, editor, options) { initialize(latlng, editor, options) {
// derived from L.Editable.VertexMarker.initialize // derived from L.Editable.VertexMarker.initialize
// We don't use this._latlng, because on drag Leaflet replace it while // We don't use this._latlng, because on drag Leaflet replace it while
@ -707,18 +707,18 @@ BR.DeleteMarker = L.Marker.extend({
this.setZIndexOffset(editor.tools._lastZIndex); this.setZIndexOffset(editor.tools._lastZIndex);
}, },
onAdd: function (map) { onAdd(map) {
L.Marker.prototype.onAdd.call(this, map); L.Marker.prototype.onAdd.call(this, map);
this.on('click', this.onClick); this.on('click', this.onClick);
}, },
onRemove: function (map) { onRemove(map) {
delete this.latlng.__vertex; delete this.latlng.__vertex;
this.off('click', this.onClick); this.off('click', this.onClick);
L.Marker.prototype.onRemove.call(this, map); L.Marker.prototype.onRemove.call(this, map);
}, },
onClick: function (e) { onClick(e) {
this.editor.delete(); this.editor.delete();
}, },
}); });

View file

@ -10,12 +10,12 @@ BR.PoiMarkers = L.Control.extend({
}, },
}, },
}, },
initialize: function (routing) { initialize(routing) {
this.routing = routing; this.routing = routing;
this.circlego = null; this.circlego = null;
}, },
onAdd: function (map) { onAdd(map) {
var self = this; var self = this;
this.map = map; this.map = map;
@ -26,7 +26,7 @@ BR.PoiMarkers = L.Control.extend({
{ {
stateName: 'activate-poi', stateName: 'activate-poi',
icon: 'fa-hand-o-right', icon: 'fa-hand-o-right',
onClick: function () { onClick() {
self.draw(true); self.draw(true);
}, },
title: i18next.t('keyboard.generic-shortcut', { action: '$t(map.draw-poi-start)', key: 'P' }), title: i18next.t('keyboard.generic-shortcut', { action: '$t(map.draw-poi-start)', key: 'P' }),
@ -34,7 +34,7 @@ BR.PoiMarkers = L.Control.extend({
{ {
stateName: 'deactivate-poi', stateName: 'deactivate-poi',
icon: 'fa-hand-o-right active', icon: 'fa-hand-o-right active',
onClick: function () { onClick() {
self.draw(false); self.draw(false);
}, },
title: i18next.t('keyboard.generic-shortcut', { title: i18next.t('keyboard.generic-shortcut', {
@ -55,7 +55,7 @@ BR.PoiMarkers = L.Control.extend({
return container; return container;
}, },
draw: function (enable) { draw(enable) {
this.drawButton.state(enable ? 'deactivate-poi' : 'activate-poi'); this.drawButton.state(enable ? 'deactivate-poi' : 'activate-poi');
if (enable) { if (enable) {
this.routing.draw(false); this.routing.draw(false);
@ -68,7 +68,7 @@ BR.PoiMarkers = L.Control.extend({
} }
}, },
_keydownListener: function (e) { _keydownListener(e) {
if (!BR.Util.keyboardShortcutsAllowed(e)) { if (!BR.Util.keyboardShortcutsAllowed(e)) {
return; return;
} }
@ -79,13 +79,13 @@ BR.PoiMarkers = L.Control.extend({
} }
}, },
onMapClick: function (e) { onMapClick(e) {
var self = this; var self = this;
bootbox.prompt({ bootbox.prompt({
title: i18next.t('map.enter-poi-name'), title: i18next.t('map.enter-poi-name'),
// allow empty name with client-side formatting // allow empty name with client-side formatting
required: !BR.Browser.download, required: !BR.Browser.download,
callback: function (result) { callback(result) {
if (result !== null) { if (result !== null) {
self.addMarker(e.latlng, result); self.addMarker(e.latlng, result);
} }
@ -93,7 +93,7 @@ BR.PoiMarkers = L.Control.extend({
}); });
}, },
addMarker: function (latlng, name) { addMarker(latlng, name) {
var icon = L.VectorMarkers.icon({ var icon = L.VectorMarkers.icon({
icon: 'star', icon: 'star',
markerColor: BR.conf.markerColors.poi, markerColor: BR.conf.markerColors.poi,
@ -107,7 +107,7 @@ BR.PoiMarkers = L.Control.extend({
'<p><button id="remove-poi-marker" class="btn btn-secondary"><i class="fa fa-trash"></i></button></p>'; '<p><button id="remove-poi-marker" class="btn btn-secondary"><i class="fa fa-trash"></i></button></p>';
var self = this; var self = this;
var marker = L.marker(latlng, { icon: icon, draggable: true, name: name }) var marker = L.marker(latlng, { icon, draggable: true, name })
.bindPopup(contentWithAction) .bindPopup(contentWithAction)
.on('dragend', function () { .on('dragend', function () {
self.fire('update'); self.fire('update');
@ -132,11 +132,11 @@ BR.PoiMarkers = L.Control.extend({
} }
}, },
clear: function () { clear() {
this.markersLayer.clearLayers(); this.markersLayer.clearLayers();
}, },
setMarkers: function (latLngNames) { setMarkers(latLngNames) {
this.clear(); this.clear();
if (!latLngNames) return; if (!latLngNames) return;
@ -147,7 +147,7 @@ BR.PoiMarkers = L.Control.extend({
} }
}, },
getMarkers: function () { getMarkers() {
return this.markersLayer.getLayers().map(function (it) { return this.markersLayer.getLayers().map(function (it) {
return { return {
latlng: it.getLatLng(), latlng: it.getLatLng(),

View file

@ -20,7 +20,7 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
}, },
}, },
setDialogDraggable: function (jqDlgHeader) { setDialogDraggable(jqDlgHeader) {
jqDlgHeader.on('mousedown', function (mousedownEvt) { jqDlgHeader.on('mousedown', function (mousedownEvt) {
var $draggable = $(this); var $draggable = $(this);
var x = mousedownEvt.pageX - $draggable.offset().left, var x = mousedownEvt.pageX - $draggable.offset().left,
@ -40,15 +40,15 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
}); });
}, },
getSimplifiedCoords: function (tolerance) { getSimplifiedCoords(tolerance) {
var simplifiedLine = turf.simplify(this._trackPoints.geometry, { var simplifiedLine = turf.simplify(this._trackPoints.geometry, {
tolerance: tolerance, tolerance,
highQuality: true, highQuality: true,
}); });
return simplifiedLine.coordinates; return simplifiedLine.coordinates;
}, },
refreshTestLayer: function () { refreshTestLayer() {
this.onBusyChanged(true); this.onBusyChanged(true);
this._testLayer.clearLayers(); this._testLayer.clearLayers();
@ -73,7 +73,7 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
return true; return true;
}, },
cleanup: function (e) { cleanup(e) {
this._testLayer.clearLayers(); this._testLayer.clearLayers();
if ( if (
this._trackLayer && this._trackLayer &&
@ -98,7 +98,7 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
}; };
}, },
setSliderRange: function () { setSliderRange() {
$slider = $('#simplify_tolerance'); $slider = $('#simplify_tolerance');
$slider.prop('min', -500); $slider.prop('min', -500);
var guessedTolerance = this.guessSimplifyTolerance(this._trackPoints); var guessedTolerance = this.guessSimplifyTolerance(this._trackPoints);
@ -116,7 +116,7 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
this.refreshTestLayer(); this.refreshTestLayer();
}, },
onToleranceSlider: function (e) { onToleranceSlider(e) {
var guess = parseFloat($(e.target).data('guess')); var guess = parseFloat($(e.target).data('guess'));
var f = parseFloat(e.target.value); var f = parseFloat(e.target.value);
var frac = parseFloat($(e.target).prop('max')); var frac = parseFloat($(e.target).prop('max'));
@ -145,7 +145,7 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
} }
}, },
findLowestTolerance: function (min, max, guess, frac) { findLowestTolerance(min, max, guess, frac) {
if (Math.abs(max - min) <= 2) return max; if (Math.abs(max - min) <= 2) return max;
var meridian = Math.round((max + min) / 2); var meridian = Math.round((max + min) / 2);
@ -157,7 +157,7 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
else return this.findLowestTolerance(min, meridian, guess, frac); else return this.findLowestTolerance(min, meridian, guess, frac);
}, },
onBusyChanged: function (isBusy) { onBusyChanged(isBusy) {
if (typeof isBusy === undefined) { if (typeof isBusy === undefined) {
isBusy = false; isBusy = false;
} }
@ -165,7 +165,7 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
else $('#loadedittrack #msg_busy').addClass('invisible'); else $('#loadedittrack #msg_busy').addClass('invisible');
}, },
onManualCollapse: function (e) { onManualCollapse(e) {
//workaround for starting with closed collapse //workaround for starting with closed collapse
if ($('#loadedittrack').is(':hidden')) return; if ($('#loadedittrack').is(':hidden')) return;
this._options.isTestMode = $(e.target).hasClass('show'); this._options.isTestMode = $(e.target).hasClass('show');
@ -176,7 +176,7 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
} else this.cleanup(); } else this.cleanup();
}, },
onAdd: function (map) { onAdd(map) {
$('#loadedittrack').on( $('#loadedittrack').on(
'hidden.bs.modal', 'hidden.bs.modal',
function (e) { function (e) {
@ -238,11 +238,11 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
return dummy; return dummy;
}, },
onRemove: function (map) { onRemove(map) {
// Nothing to do here // Nothing to do here
}, },
onFileChanged: function (e) { onFileChanged(e) {
if (!e.target.files[0]) return; if (!e.target.files[0]) return;
$(e.target).next('label').text(e.target.files[0].name); $(e.target).next('label').text(e.target.files[0].name);
var testmode = this._options.isTestMode; var testmode = this._options.isTestMode;
@ -254,7 +254,7 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
} }
}, },
setLayerNameFromGeojson: function (geoJSON) { setLayerNameFromGeojson(geoJSON) {
if (geoJSON.type == 'Feature' && geoJSON.properties && geoJSON.properties.name) { if (geoJSON.type == 'Feature' && geoJSON.properties && geoJSON.properties.name) {
this._layerName = geoJSON.properties.name; this._layerName = geoJSON.properties.name;
return; return;
@ -270,7 +270,7 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
} }
}, },
getOptions: function () { getOptions() {
this._options.showTrackLayer = $('#cb_showtracklayer')[0].checked; this._options.showTrackLayer = $('#cb_showtracklayer')[0].checked;
this._options.showPointAsPoi = $('#cb_showpois')[0].checked; this._options.showPointAsPoi = $('#cb_showpois')[0].checked;
@ -278,7 +278,7 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
this._bounds = undefined; this._bounds = undefined;
}, },
convertTrackLocal: function () { convertTrackLocal() {
if ($('#loadedittrackFile')[0].files.length == 0) return; if ($('#loadedittrackFile')[0].files.length == 0) return;
this.onBusyChanged(true); this.onBusyChanged(true);
@ -295,7 +295,7 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
reader.readAsText(trackFile); reader.readAsText(trackFile);
}, },
addTrackOverlay: function (geoJSON) { addTrackOverlay(geoJSON) {
this._trackLayer = L.geoJSON(geoJSON, BR.Track.getGeoJsonOptions(layersControl, true)).addTo(map); this._trackLayer = L.geoJSON(geoJSON, BR.Track.getGeoJsonOptions(layersControl, true)).addTo(map);
layersControl.addOverlay(this._trackLayer, BR.Util.sanitizeHTMLContent(this._layerName)); layersControl.addOverlay(this._trackLayer, BR.Util.sanitizeHTMLContent(this._layerName));
@ -305,7 +305,7 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
if (this._bounds) map.fitBounds(this._bounds); if (this._bounds) map.fitBounds(this._bounds);
}, },
getLineStringsFromGeoJSON: function (geoJSON) { getLineStringsFromGeoJSON(geoJSON) {
var allLinePoints = []; var allLinePoints = [];
var flat = turf.flatten(geoJSON); var flat = turf.flatten(geoJSON);
turf.featureEach(flat, function (feature, idx) { turf.featureEach(flat, function (feature, idx) {
@ -321,13 +321,13 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
return linesGeoJSON; return linesGeoJSON;
}, },
guessSimplifyTolerance: function (trackPoints) { guessSimplifyTolerance(trackPoints) {
var tolerance = trackPoints.length / 1000000; var tolerance = trackPoints.length / 1000000;
if (tolerance > 0.8) tolerance = 0.8; if (tolerance > 0.8) tolerance = 0.8;
return tolerance; return tolerance;
}, },
addRoutingPoints: function (geoJSON) { addRoutingPoints(geoJSON) {
if (this._options.simplifyTolerance < 0) if (this._options.simplifyTolerance < 0)
this._options.simplifyTolerance = this.guessSimplifyTolerance(this._trackPoints); this._options.simplifyTolerance = this.guessSimplifyTolerance(this._trackPoints);
@ -361,7 +361,7 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
} }
}, },
processFile: function (e) { processFile(e) {
var res = e.target.result; var res = e.target.result;
var geoJSON = null; var geoJSON = null;
switch (this._options.format) { switch (this._options.format) {
@ -391,7 +391,7 @@ BR.routeLoader = function (map, layersControl, routing, pois) {
this.onBusyChanged(false); this.onBusyChanged(false);
}, },
keydownListener: function (e) { keydownListener(e) {
if ( if (
BR.Util.keyboardShortcutsAllowed(e) && BR.Util.keyboardShortcutsAllowed(e) &&
e.keyCode === this._options.shortcut.open && e.keyCode === this._options.shortcut.open &&

View file

@ -23,7 +23,7 @@ BR.Routing = L.Routing.extend({
// width as base number, multiplied by number of digits + one for padding // width as base number, multiplied by number of digits + one for padding
iconSize: [6, 18], iconSize: [6, 18],
offset: 5000, offset: 5000,
textFunction: function (distance) { textFunction(distance) {
return distance / 1000; return distance / 1000;
}, },
}, },
@ -42,13 +42,13 @@ BR.Routing = L.Routing.extend({
}, },
}, },
initialize: function (profile, options) { initialize(profile, options) {
L.Routing.prototype.initialize.call(this, options); L.Routing.prototype.initialize.call(this, options);
this.profile = profile; this.profile = profile;
}, },
onAdd: function (map) { onAdd(map) {
this.options.tooltips.waypoint = i18next.t('map.route-tooltip-waypoint'); this.options.tooltips.waypoint = i18next.t('map.route-tooltip-waypoint');
this.options.tooltips.segment = i18next.t('map.route-tooltip-segment'); this.options.tooltips.segment = i18next.t('map.route-tooltip-segment');
@ -178,16 +178,19 @@ BR.Routing = L.Routing.extend({
this._show(); this._show();
} }
} }
var hide = function () { var hide = function () {
if (!this._hidden && this._parent._waypoints._first) { if (!this._hidden && this._parent._waypoints._first) {
this._hide(); this._hide();
} }
}.bind(this._draw); }.bind(this._draw);
function hideOverControl(e) { function hideOverControl(e) {
hide(); hide();
// prevent showing trailer when clicking state buttons (causes event that propagates to map) // prevent showing trailer when clicking state buttons (causes event that propagates to map)
L.DomEvent.stopPropagation(e); L.DomEvent.stopPropagation(e);
} }
this._draw.on('enabled', function () { this._draw.on('enabled', function () {
this._map.on('mouseout', hide, this); this._map.on('mouseout', hide, this);
this._map.on('mouseover', show, this); this._map.on('mouseover', show, this);
@ -246,7 +249,7 @@ BR.Routing = L.Routing.extend({
return container; return container;
}, },
_addSegmentCasing: function (e) { _addSegmentCasing(e) {
// extend layer style to inherit beeline dashArray // extend layer style to inherit beeline dashArray
const casingStyle = Object.assign({}, e.layer.options, this.options.styles.trackCasing); const casingStyle = Object.assign({}, e.layer.options, this.options.styles.trackCasing);
const casing = L.polyline(e.layer.getLatLngs(), Object.assign({}, casingStyle, { interactive: false })); const casing = L.polyline(e.layer.getLatLngs(), Object.assign({}, casingStyle, { interactive: false }));
@ -255,11 +258,11 @@ BR.Routing = L.Routing.extend({
this._segments.bringToFront(); this._segments.bringToFront();
}, },
_removeSegmentCasing: function (e) { _removeSegmentCasing(e) {
this._segmentsCasing.removeLayer(e.layer._casing); this._segmentsCasing.removeLayer(e.layer._casing);
}, },
setOpacity: function (opacity) { setOpacity(opacity) {
// Due to the second Polyline layer for casing, the combined opacity is less // Due to the second Polyline layer for casing, the combined opacity is less
// transparent than with a single layer and the slider is non-linear. The // transparent than with a single layer and the slider is non-linear. The
// inverted formula is used to get the same result as with a single layer. // inverted formula is used to get the same result as with a single layer.
@ -286,11 +289,11 @@ BR.Routing = L.Routing.extend({
} }
}, },
_setMarkerOpacity: function (e) { _setMarkerOpacity(e) {
e.layer.setOpacity(this.options.icons.opacity); e.layer.setOpacity(this.options.icons.opacity);
}, },
_removeMarkerEvents: function (marker) { _removeMarkerEvents(marker) {
marker.off('mouseover', this._fireWaypointEvent, this); marker.off('mouseover', this._fireWaypointEvent, this);
marker.off('mouseout', this._fireWaypointEvent, this); marker.off('mouseout', this._fireWaypointEvent, this);
marker.off('dragstart', this._fireWaypointEvent, this); marker.off('dragstart', this._fireWaypointEvent, this);
@ -299,7 +302,7 @@ BR.Routing = L.Routing.extend({
marker.off('click', this._fireWaypointEvent, this); marker.off('click', this._fireWaypointEvent, this);
}, },
clear: function () { clear() {
var drawEnabled = this._draw._enabled; var drawEnabled = this._draw._enabled;
var current = this._waypoints._first; var current = this._waypoints._first;
@ -326,7 +329,7 @@ BR.Routing = L.Routing.extend({
} }
}, },
setWaypoints: function (latLngs, beelineFlags, cb) { setWaypoints(latLngs, beelineFlags, cb) {
var i; var i;
var callbackCount = 0; var callbackCount = 0;
var firstErr; var firstErr;
@ -367,7 +370,7 @@ BR.Routing = L.Routing.extend({
// patch to fix error when line is null or error line // patch to fix error when line is null or error line
// (when called while still segments to calculate, e.g. permalink or fast drawing) // (when called while still segments to calculate, e.g. permalink or fast drawing)
toPolyline: function () { toPolyline() {
var latLngs = []; var latLngs = [];
this._eachSegment(function (m1, m2, line) { this._eachSegment(function (m1, m2, line) {
@ -381,7 +384,7 @@ BR.Routing = L.Routing.extend({
return L.polyline(latLngs); return L.polyline(latLngs);
}, },
_routeSegment: function (m1, m2, cb) { _routeSegment(m1, m2, cb) {
var loadingTrailer; var loadingTrailer;
// change segment color before request to indicate recalculation (mark old) // change segment color before request to indicate recalculation (mark old)
@ -413,7 +416,7 @@ BR.Routing = L.Routing.extend({
); );
}, },
getSegments: function () { getSegments() {
var segments = []; var segments = [];
this._eachSegment(function (m1, m2, line) { this._eachSegment(function (m1, m2, line) {
@ -427,7 +430,7 @@ BR.Routing = L.Routing.extend({
return segments; return segments;
}, },
_keydownListener: function (e) { _keydownListener(e) {
if (!BR.Util.keyboardShortcutsAllowed(e)) { if (!BR.Util.keyboardShortcutsAllowed(e)) {
return; return;
} }
@ -446,17 +449,17 @@ BR.Routing = L.Routing.extend({
} }
}, },
_keyupListener: function (e) { _keyupListener(e) {
if (e.keyCode === this.options.shortcut.draw.beelineModifier) { if (e.keyCode === this.options.shortcut.draw.beelineModifier) {
this._draw._setTrailerStyle(false); this._draw._setTrailerStyle(false);
} }
}, },
isDrawing: function () { isDrawing() {
return this._draw._enabled; return this._draw._enabled;
}, },
reverse: function () { reverse() {
const waypoints = this.getWaypoints(); const waypoints = this.getWaypoints();
const beelineFlags = this.getBeelineFlags(); const beelineFlags = this.getBeelineFlags();
waypoints.reverse(); waypoints.reverse();
@ -465,19 +468,19 @@ BR.Routing = L.Routing.extend({
this.setWaypoints(waypoints, beelineFlags); this.setWaypoints(waypoints, beelineFlags);
}, },
deleteLastPoint: function () { deleteLastPoint() {
if ((lastPoint = this.getLast())) { if ((lastPoint = this.getLast())) {
this.removeWaypoint(lastPoint, function (err, data) {}); this.removeWaypoint(lastPoint, function (err, data) {});
} }
}, },
_removeDistanceMarkers: function () { _removeDistanceMarkers() {
if (this._map && this._distanceMarkers) { if (this._map && this._distanceMarkers) {
this._map.removeLayer(this._distanceMarkers); this._map.removeLayer(this._distanceMarkers);
} }
}, },
_updateDistanceMarkers: function (e) { _updateDistanceMarkers(e) {
this._removeDistanceMarkers(); this._removeDistanceMarkers();
if (this._map) { if (this._map) {
@ -487,7 +490,7 @@ BR.Routing = L.Routing.extend({
} }
}, },
_distance: function (latLng1, latLng2) { _distance(latLng1, latLng2) {
//return Math.round(latLng1.distanceTo(latLng2)); //return Math.round(latLng1.distanceTo(latLng2));
const [ilon1, ilat1] = btools.util.CheapRuler.toIntegerLngLat([latLng1.lng, latLng1.lat]); const [ilon1, ilat1] = btools.util.CheapRuler.toIntegerLngLat([latLng1.lng, latLng1.lat]);
const [ilon2, ilat2] = btools.util.CheapRuler.toIntegerLngLat([latLng2.lng, latLng2.lat]); const [ilon2, ilat2] = btools.util.CheapRuler.toIntegerLngLat([latLng2.lng, latLng2.lat]);
@ -495,7 +498,7 @@ BR.Routing = L.Routing.extend({
return btools.util.CheapRuler.calcDistance(ilon1, ilat1, ilon2, ilat2); return btools.util.CheapRuler.calcDistance(ilon1, ilat1, ilon2, ilat2);
}, },
_computeKinematic: function (distance, deltaHeight, costFactor) { _computeKinematic(distance, deltaHeight, costFactor) {
const rc = new BR.RoutingContext(this.profile); const rc = new BR.RoutingContext(this.profile);
rc.expctxWay = new BR.BExpressionContextWay(undefined, costFactor); rc.expctxWay = new BR.BExpressionContextWay(undefined, costFactor);
const stdPath = new BR.StdPath(); const stdPath = new BR.StdPath();
@ -504,7 +507,7 @@ BR.Routing = L.Routing.extend({
return stdPath; return stdPath;
}, },
_getCostFactor: function (line) { _getCostFactor(line) {
let costFactor; let costFactor;
if (line) { if (line) {
const props = line.feature.properties; const props = line.feature.properties;
@ -517,7 +520,7 @@ BR.Routing = L.Routing.extend({
return costFactor; return costFactor;
}, },
_interpolateBeelines: function (serialBeelines, before, after) { _interpolateBeelines(serialBeelines, before, after) {
let altStart = before?.getLatLngs()[before.getLatLngs().length - 1].alt; let altStart = before?.getLatLngs()[before.getLatLngs().length - 1].alt;
const altEnd = after?.getLatLngs()[0].alt ?? altStart; const altEnd = after?.getLatLngs()[0].alt ?? altStart;
altStart ?? (altStart = altEnd); altStart ?? (altStart = altEnd);
@ -562,7 +565,7 @@ BR.Routing = L.Routing.extend({
} }
}, },
_updateBeelines: function () { _updateBeelines() {
L.Routing.prototype._updateBeelines.call(this); L.Routing.prototype._updateBeelines.call(this);
let serialBeelines = []; let serialBeelines = [];
@ -585,7 +588,7 @@ BR.Routing = L.Routing.extend({
} }
}, },
createBeeline: function (latLng1, latLng2) { createBeeline(latLng1, latLng2) {
const layer = L.Routing.prototype.createBeeline.call(this, latLng1, latLng2); const layer = L.Routing.prototype.createBeeline.call(this, latLng1, latLng2);
// remove alt from cloned LatLngs to show gap in elevation graph to indicate no data inbetween // remove alt from cloned LatLngs to show gap in elevation graph to indicate no data inbetween
delete layer.getLatLngs()[0].alt; delete layer.getLatLngs()[0].alt;

View file

@ -6,7 +6,7 @@ BR.RoutingPathQuality = L.Control.extend({
}, },
}, },
initialize: function (map, layersControl, options) { initialize(map, layersControl, options) {
L.setOptions(this, options); L.setOptions(this, options);
// hotline uses canvas and cannot be moved in front of the svg, so we create another pane // hotline uses canvas and cannot be moved in front of the svg, so we create another pane
@ -35,9 +35,9 @@ BR.RoutingPathQuality = L.Control.extend({
1.0: '#ff0000', // red 1.0: '#ff0000', // red
}, },
outlineColor: 'dimgray', outlineColor: 'dimgray',
renderer: renderer, renderer,
}, },
valueFunction: function (latLng, prevLatLng) { valueFunction(latLng, prevLatLng) {
var deltaAltitude = latLng.alt - prevLatLng.alt, // in m var deltaAltitude = latLng.alt - prevLatLng.alt, // in m
distance = prevLatLng.distanceTo(latLng); // in m distance = prevLatLng.distanceTo(latLng); // in m
if (distance === 0) { if (distance === 0) {
@ -53,9 +53,9 @@ BR.RoutingPathQuality = L.Control.extend({
provider: new HotLineQualityProvider({ provider: new HotLineQualityProvider({
hotlineOptions: { hotlineOptions: {
outlineColor: 'dimgray', outlineColor: 'dimgray',
renderer: renderer, renderer,
}, },
valueFunction: function (latLng) { valueFunction(latLng) {
return latLng.alt; return latLng.alt;
}, },
}), }),
@ -65,7 +65,7 @@ BR.RoutingPathQuality = L.Control.extend({
icon: 'fa-road', icon: 'fa-road',
provider: new HotLineQualityProvider({ provider: new HotLineQualityProvider({
hotlineOptions: { hotlineOptions: {
renderer: renderer, renderer,
palette: { palette: {
// normal range // normal range
0.0: 'red', 0.0: 'red',
@ -103,6 +103,7 @@ BR.RoutingPathQuality = L.Control.extend({
case 'concrete:lanes': case 'concrete:lanes':
case 'concrete:plates': case 'concrete:plates':
surface = 0.6; surface = 0.6;
break;
case 'sett': case 'sett':
case 'gravel': case 'gravel':
case 'pebblestone': case 'pebblestone':
@ -228,9 +229,9 @@ BR.RoutingPathQuality = L.Control.extend({
// disables line simplification, so short segments won't disappear on some zoom levels // disables line simplification, so short segments won't disappear on some zoom levels
smoothFactor: 0, smoothFactor: 0,
outlineColor: 'dimgray', outlineColor: 'dimgray',
renderer: renderer, renderer,
}, },
valueFunction: function (latLng) { valueFunction(latLng) {
var feature = latLng.feature; var feature = latLng.feature;
var cost = feature.cost.perKm; var cost = feature.cost.perKm;
var distance = feature.distance / 1000; // in km var distance = feature.distance / 1000; // in km
@ -251,7 +252,7 @@ BR.RoutingPathQuality = L.Control.extend({
this._muted = false; this._muted = false;
}, },
onAdd: function (map) { onAdd(map) {
this._map = map; this._map = map;
map.on( map.on(
@ -310,28 +311,28 @@ BR.RoutingPathQuality = L.Control.extend({
} }
this.routingPathButton = new L.easyButton({ this.routingPathButton = new L.easyButton({
states: states, states,
}).addTo(map); }).addTo(map);
return new L.DomUtil.create('div'); return new L.DomUtil.create('div');
}, },
_activate: function (btn) { _activate(btn) {
this._active = true; this._active = true;
this._getIcon(btn).classList.add('active'); this._getIcon(btn).classList.add('active');
this._routingSegments.addTo(this._map); this._routingSegments.addTo(this._map);
}, },
_deactivate: function (btn) { _deactivate(btn) {
this._active = false; this._active = false;
this._getIcon(btn).classList.remove('active'); this._getIcon(btn).classList.remove('active');
this._map.removeLayer(this._routingSegments); this._map.removeLayer(this._routingSegments);
}, },
_getIcon: function (btn) { _getIcon(btn) {
return btn.button.firstChild.firstChild; return btn.button.firstChild.firstChild;
}, },
update: function (track, layer) { update(track, layer) {
var segments = []; var segments = [];
layer.eachLayer(function (layer) { layer.eachLayer(function (layer) {
segments.push(layer); segments.push(layer);
@ -340,12 +341,12 @@ BR.RoutingPathQuality = L.Control.extend({
this._update(this.segments); this._update(this.segments);
}, },
setProvider: function (provider) { setProvider(provider) {
this.selectedProvider = provider; this.selectedProvider = provider;
this._update(this.segments); this._update(this.segments);
}, },
_update: function (segments) { _update(segments) {
this._routingSegments.clearLayers(); this._routingSegments.clearLayers();
var layers = this.providers[this.selectedProvider].provider.computeLayers(segments); var layers = this.providers[this.selectedProvider].provider.computeLayers(segments);
if (layers) { if (layers) {
@ -355,7 +356,7 @@ BR.RoutingPathQuality = L.Control.extend({
} }
}, },
_keydownListener: function (e) { _keydownListener(e) {
if (!BR.Util.keyboardShortcutsAllowed(e)) { if (!BR.Util.keyboardShortcutsAllowed(e)) {
return; return;
} }
@ -368,7 +369,7 @@ BR.RoutingPathQuality = L.Control.extend({
} }
}, },
_keyupListener: function (e) { _keyupListener(e) {
if (BR.Util.keyboardShortcutsAllowed(e) && this._muted && e.keyCode === this.options.shortcut.muteKeyCode) { if (BR.Util.keyboardShortcutsAllowed(e) && this._muted && e.keyCode === this.options.shortcut.muteKeyCode) {
this._muted = false; this._muted = false;
this._activate(this.routingPathButton); this._activate(this.routingPathButton);
@ -377,12 +378,12 @@ BR.RoutingPathQuality = L.Control.extend({
}); });
var HotLineQualityProvider = L.Class.extend({ var HotLineQualityProvider = L.Class.extend({
initialize: function (options) { initialize(options) {
this.hotlineOptions = options.hotlineOptions; this.hotlineOptions = options.hotlineOptions;
this.valueFunction = options.valueFunction; this.valueFunction = options.valueFunction;
}, },
computeLayers: function (segments) { computeLayers(segments) {
var layers = []; var layers = [];
if (segments) { if (segments) {
var segmentLatLngs = []; var segmentLatLngs = [];
@ -414,7 +415,7 @@ var HotLineQualityProvider = L.Class.extend({
return layers; return layers;
}, },
_computeLatLngVals: function (segment) { _computeLatLngVals(segment) {
var latLngVals = [], var latLngVals = [],
segmentLatLngs = segment.getLatLngs(), segmentLatLngs = segment.getLatLngs(),
segmentLength = segmentLatLngs.length; segmentLength = segmentLatLngs.length;
@ -432,11 +433,11 @@ var HotLineQualityProvider = L.Class.extend({
return latLngVals; return latLngVals;
}, },
_convertToArray: function (latLng, val) { _convertToArray(latLng, val) {
return [latLng.lat, latLng.lng, val]; return [latLng.lat, latLng.lng, val];
}, },
_calcMinMaxValues: function (lines, pct) { _calcMinMaxValues(lines, pct) {
lines.sort(function (a, b) { lines.sort(function (a, b) {
return a[2] - b[2]; return a[2] - b[2];
}); });
@ -446,8 +447,8 @@ var HotLineQualityProvider = L.Class.extend({
max = min + 1; max = min + 1;
} }
return { return {
min: min, min,
max: max, max,
}; };
}, },
}); });

View file

@ -17,7 +17,7 @@ BR.Sidebar = L.Control.Sidebar.extend({
listeningTabs: {}, listeningTabs: {},
}, },
initialize: function (id, options) { initialize(id, options) {
L.Control.Sidebar.prototype.initialize.call(this, id, options); L.Control.Sidebar.prototype.initialize.call(this, id, options);
this.oldTab = null; this.oldTab = null;
@ -25,7 +25,7 @@ BR.Sidebar = L.Control.Sidebar.extend({
L.DomEvent.addListener(document, 'keydown', this._keydownListener, this); L.DomEvent.addListener(document, 'keydown', this._keydownListener, this);
}, },
addTo: function (map) { addTo(map) {
L.Control.Sidebar.prototype.addTo.call(this, map); L.Control.Sidebar.prototype.addTo.call(this, map);
this.on('content', this._notifyOnContent, this); this.on('content', this._notifyOnContent, this);
@ -59,14 +59,14 @@ BR.Sidebar = L.Control.Sidebar.extend({
return this; return this;
}, },
showPanel: function (id) { showPanel(id) {
var tab = this._getTab(id); var tab = this._getTab(id);
tab.hidden = false; tab.hidden = false;
return this; return this;
}, },
_rememberTabState: function () { _rememberTabState() {
if (BR.Util.localStorageAvailable()) { if (BR.Util.localStorageAvailable()) {
this.on('content closing', this._storeActiveTab, this); this.on('content closing', this._storeActiveTab, this);
@ -85,42 +85,42 @@ BR.Sidebar = L.Control.Sidebar.extend({
} }
}, },
_notifyShow: function (tab) { _notifyShow(tab) {
if (tab && tab.show) { if (tab && tab.show) {
tab.show(); tab.show();
} }
}, },
_notifyHide: function (tab) { _notifyHide(tab) {
if (tab && tab.hide) { if (tab && tab.hide) {
tab.hide(); tab.hide();
} }
}, },
_notifyOnContent: function (e) { _notifyOnContent(e) {
var tab = this.options.listeningTabs[e.id]; var tab = this.options.listeningTabs[e.id];
this._notifyHide(this.oldTab); this._notifyHide(this.oldTab);
this._notifyShow(tab); this._notifyShow(tab);
this.oldTab = tab; this.oldTab = tab;
}, },
_notifyOnClose: function (e) { _notifyOnClose(e) {
this._notifyHide(this.oldTab); this._notifyHide(this.oldTab);
this.oldTab = null; this.oldTab = null;
}, },
_notifyOnResize: function (e) { _notifyOnResize(e) {
var tab = this.oldTab; var tab = this.oldTab;
if (tab && tab.onResize) { if (tab && tab.onResize) {
tab.onResize(); tab.onResize();
} }
}, },
_storeActiveTab: function (e) { _storeActiveTab(e) {
localStorage.setItem(this.storageId, e.id || ''); localStorage.setItem(this.storageId, e.id || '');
}, },
_keydownListener: function (e) { _keydownListener(e) {
if (BR.Util.keyboardShortcutsAllowed(e) && e.keyCode === this.options.shortcut.toggleTabs) { if (BR.Util.keyboardShortcutsAllowed(e) && e.keyCode === this.options.shortcut.toggleTabs) {
if ($('#sidebarTabs > ul > li[class=active]').length) { if ($('#sidebarTabs > ul > li[class=active]').length) {
// sidebar is currently open, close current tab // sidebar is currently open, close current tab

View file

@ -19,7 +19,7 @@ BR.tracksLoader = function (map, layersControl, routing, pois) {
}, },
}, },
_initContainer: function () { _initContainer() {
var thisLoader = this.loader; var thisLoader = this.loader;
var fileInput; var fileInput;
@ -60,7 +60,7 @@ BR.tracksLoader = function (map, layersControl, routing, pois) {
return dummy; return dummy;
}, },
_keydownListener: function (e) { _keydownListener(e) {
if ( if (
BR.Util.keyboardShortcutsAllowed(e) && BR.Util.keyboardShortcutsAllowed(e) &&
e.keyCode === this.options.shortcut.open && e.keyCode === this.options.shortcut.open &&

View file

@ -24,7 +24,7 @@
*/ */
L.DistanceMarkers = L.LayerGroup.extend({ L.DistanceMarkers = L.LayerGroup.extend({
initialize: function (line, map, options) { initialize(line, map, options) {
options = options || {}; options = options || {};
var offset = options.offset || 1000; var offset = options.offset || 1000;
var showAll = Math.min(map.getMaxZoom(), options.showAll || 12); var showAll = Math.min(map.getMaxZoom(), options.showAll || 12);
@ -69,7 +69,7 @@ L.DistanceMarkers = L.LayerGroup.extend({
// width as base number, one for padding + multiply by number of digits // width as base number, one for padding + multiply by number of digits
var size = [iconSize[0] + iconSize[0] * ('' + text).length, iconSize[1]]; var size = [iconSize[0] + iconSize[0] * ('' + text).length, iconSize[1]];
var icon = L.divIcon({ className: cssClass, html: text, iconSize: size }); var icon = L.divIcon({ className: cssClass, html: text, iconSize: size });
var marker = L.marker(position.latLng, { title: text, icon: icon, interactive: false }); var marker = L.marker(position.latLng, { title: text, icon, interactive: false });
// visible only starting at a specific zoom level // visible only starting at a specific zoom level
var zoom = this._minimumZoomLevelForItem(i, showAll); var zoom = this._minimumZoomLevelForItem(i, showAll);
@ -106,7 +106,7 @@ L.DistanceMarkers = L.LayerGroup.extend({
updateMarkerVisibility(); updateMarkerVisibility();
}, },
setOpacity: function (opacity) { setOpacity(opacity) {
var i, var i,
keys = Object.keys(this._zoomLayers), keys = Object.keys(this._zoomLayers),
l = keys.length; l = keys.length;
@ -119,7 +119,7 @@ L.DistanceMarkers = L.LayerGroup.extend({
} }
}, },
_minimumZoomLevelForItem: function (item, showAllLevel) { _minimumZoomLevelForItem(item, showAllLevel) {
var zoom = showAllLevel, var zoom = showAllLevel,
i = item; i = item;
while (i > 0 && i % 2 === 0) { while (i > 0 && i % 2 === 0) {

View file

@ -29,9 +29,9 @@
} else { } else {
return { return {
center: new L.LatLng(lat, lon), center: new L.LatLng(lat, lon),
zoom: zoom, zoom,
layers: layers, layers,
additional: additional, additional,
}; };
} }
} else { } else {
@ -65,7 +65,7 @@
parseHash: L.Hash.parseHash, parseHash: L.Hash.parseHash,
formatHash: L.Hash.formatHash, formatHash: L.Hash.formatHash,
init: function (map, options) { init(map, options) {
this.map = map; this.map = map;
L.Util.setOptions(this, options); L.Util.setOptions(this, options);
@ -78,7 +78,7 @@
} }
}, },
_parseLayers: function (layersParam, layerSeparator) { _parseLayers(layersParam, layerSeparator) {
var layers = layersParam.split(layerSeparator).map( var layers = layersParam.split(layerSeparator).map(
L.bind(function (layerEncoded) { L.bind(function (layerEncoded) {
var obj = null; var obj = null;
@ -95,7 +95,7 @@
return layers; return layers;
}, },
parseLayers: function (layersParam) { parseLayers(layersParam) {
var countFoundLayers = function (count, obj) { var countFoundLayers = function (count, obj) {
if (obj) { if (obj) {
count++; count++;
@ -119,7 +119,7 @@
return layers; return layers;
}, },
activateLayers: function (layers) { activateLayers(layers) {
var layersControl = this.options.layersControl; var layersControl = this.options.layersControl;
var added = false; var added = false;
@ -147,7 +147,7 @@
} }
}, },
formatLayers: function () { formatLayers() {
var objList = this.options.layersControl.getActiveLayers(); var objList = this.options.layersControl.getActiveLayers();
// exclude vector layers (loaded tracks), but not when id set (route quality coding) // exclude vector layers (loaded tracks), but not when id set (route quality coding)
objList = objList.filter(function (obj) { objList = objList.filter(function (obj) {
@ -162,7 +162,7 @@
return layerList.join(this.options.layerSeparator); return layerList.join(this.options.layerSeparator);
}, },
removeFrom: function (map) { removeFrom(map) {
if (this.changeTimeout) { if (this.changeTimeout) {
clearTimeout(this.changeTimeout); clearTimeout(this.changeTimeout);
} }
@ -174,7 +174,7 @@
this.map = null; this.map = null;
}, },
onMapMove: function () { onMapMove() {
// bail if we're moving the map (updating from a hash), // bail if we're moving the map (updating from a hash),
// or if the map is not yet loaded // or if the map is not yet loaded
@ -190,7 +190,7 @@
}, },
movingMap: false, movingMap: false,
update: function () { update() {
var hash = location.hash; var hash = location.hash;
if (hash === this.lastHash) { if (hash === this.lastHash) {
return; return;
@ -226,7 +226,7 @@
// defer hash change updates every 100ms // defer hash change updates every 100ms
changeDefer: 100, changeDefer: 100,
changeTimeout: null, changeTimeout: null,
onHashChange: function () { onHashChange() {
// throttle calls to update() so that they only happen every // throttle calls to update() so that they only happen every
// `changeDefer` ms // `changeDefer` ms
if (!this.changeTimeout) { if (!this.changeTimeout) {
@ -240,7 +240,7 @@
isListening: false, isListening: false,
hashChangeInterval: null, hashChangeInterval: null,
startListening: function () { startListening() {
this.map.on('moveend layeradd layerremove', this.onMapMove, this); this.map.on('moveend layeradd layerremove', this.onMapMove, this);
if (HAS_HASHCHANGE) { if (HAS_HASHCHANGE) {
@ -252,7 +252,7 @@
this.isListening = true; this.isListening = true;
}, },
stopListening: function () { stopListening() {
this.map.off('moveend layeradd layerremove', this.onMapMove, this); this.map.off('moveend layeradd layerremove', this.onMapMove, this);
if (HAS_HASHCHANGE) { if (HAS_HASHCHANGE) {
@ -263,7 +263,7 @@
this.isListening = false; this.isListening = false;
}, },
_keyByValue: function (obj, value) { _keyByValue(obj, value) {
for (var key in obj) { for (var key in obj) {
if (obj.hasOwnProperty(key)) { if (obj.hasOwnProperty(key)) {
if (obj[key] === value) { if (obj[key] === value) {

View file

@ -10,15 +10,16 @@ L.BRouter = L.Class.extend({
GROUP_SEPARATOR: '|', GROUP_SEPARATOR: '|',
ABORTED_ERROR: 'aborted', ABORTED_ERROR: 'aborted',
CUSTOM_PREFIX: 'custom_', CUSTOM_PREFIX: 'custom_',
SUPPORTED_BROUTER_VERSIONS: '< 1.7.0 || >=1.7.2', // compatibility string should be in npm package versioning format SUPPORTED_BROUTER_VERSIONS: '< 1.7.0 || >=1.7.2',
isCustomProfile: function (profileName) { // compatibility string should be in npm package versioning format
isCustomProfile(profileName) {
return profileName && profileName.substring(0, 7) === L.BRouter.CUSTOM_PREFIX; return profileName && profileName.substring(0, 7) === L.BRouter.CUSTOM_PREFIX;
}, },
}, },
options: {}, options: {},
initialize: function (options) { initialize(options) {
L.setOptions(this, options); L.setOptions(this, options);
this.queue = async.queue( this.queue = async.queue(
@ -29,11 +30,11 @@ L.BRouter = L.Class.extend({
); );
}, },
setOptions: function (options) { setOptions(options) {
L.setOptions(this, options); L.setOptions(this, options);
}, },
getUrlParams: function (latLngs, beelineFlags, pois, circlego, format) { getUrlParams(latLngs, beelineFlags, pois, circlego, format) {
params = {}; params = {};
if (this._getLonLatsString(latLngs) != null) params.lonlats = this._getLonLatsString(latLngs); if (this._getLonLatsString(latLngs) != null) params.lonlats = this._getLonLatsString(latLngs);
@ -75,7 +76,7 @@ L.BRouter = L.Class.extend({
return params; return params;
}, },
parseUrlParams: function (params) { parseUrlParams(params) {
var opts = {}; var opts = {};
if (params.lonlats) { if (params.lonlats) {
opts.lonlats = this._parseLonLats(params.lonlats); opts.lonlats = this._parseLonLats(params.lonlats);
@ -116,7 +117,7 @@ L.BRouter = L.Class.extend({
return opts; return opts;
}, },
getUrl: function (latLngs, beelineFlags, pois, circlego, format, trackname, exportWaypoints) { getUrl(latLngs, beelineFlags, pois, circlego, format, trackname, exportWaypoints) {
var urlParams = this.getUrlParams(latLngs, beelineFlags, pois, circlego, format); var urlParams = this.getUrlParams(latLngs, beelineFlags, pois, circlego, format);
var args = []; var args = [];
if (urlParams.lonlats != null && urlParams.lonlats.length > 0) if (urlParams.lonlats != null && urlParams.lonlats.length > 0)
@ -133,7 +134,7 @@ L.BRouter = L.Class.extend({
if (trackname) if (trackname)
args.push( args.push(
L.Util.template('trackname={trackname}', { L.Util.template('trackname={trackname}', {
trackname: trackname, trackname,
}) })
); );
if (exportWaypoints) args.push('exportWaypoints=1'); if (exportWaypoints) args.push('exportWaypoints=1');
@ -143,7 +144,7 @@ L.BRouter = L.Class.extend({
return (prepend_host ? BR.conf.host : '') + '/brouter?' + args.join('&'); return (prepend_host ? BR.conf.host : '') + '/brouter?' + args.join('&');
}, },
getRoute: function (latLngs, cb) { getRoute(latLngs, cb) {
var url = this.getUrl(latLngs, null, null, null, 'geojson'), var url = this.getUrl(latLngs, null, null, null, 'geojson'),
xhr = new XMLHttpRequest(); xhr = new XMLHttpRequest();
@ -164,14 +165,15 @@ L.BRouter = L.Class.extend({
xhr.send(); xhr.send();
}, },
_handleRouteResponse: function (xhr, cb) { _handleRouteResponse(xhr, cb) {
var layer, geojson; var layer, geojson;
if ( if (
xhr.status === 200 && xhr.status === 200 &&
xhr.responseText && xhr.responseText &&
// application error when not GeoJSON format (text/plain for errors) // application error when not GeoJSON format (text/plain for errors)
xhr.getResponseHeader('Content-Type').split(';')[0] === 'application/vnd.geo+json' (xhr.getResponseHeader('Content-Type').split(';')[0] === 'application/geo+json' ||
xhr.getResponseHeader('Content-Type').split(';')[0] === 'application/vnd.geo+json')
) { ) {
// leaflet.spin // leaflet.spin
//gpxLayer.fire('data:loaded'); //gpxLayer.fire('data:loaded');
@ -192,7 +194,7 @@ L.BRouter = L.Class.extend({
}, },
versionCheckDone: false, versionCheckDone: false,
checkBRouterVersion: function (creator) { checkBRouterVersion(creator) {
if (this.versionCheckDone) { if (this.versionCheckDone) {
return; return;
} }
@ -216,11 +218,11 @@ L.BRouter = L.Class.extend({
} }
}, },
getRouteSegment: function (l1, l2, cb) { getRouteSegment(l1, l2, cb) {
this.queue.push({ segment: [l1, l2] }, cb); this.queue.push({ segment: [l1, l2] }, cb);
}, },
uploadProfile: function (profileId, profileText, cb) { uploadProfile(profileId, profileText, cb) {
var url = L.BRouter.URL_PROFILE_UPLOAD; var url = L.BRouter.URL_PROFILE_UPLOAD;
xhr = new XMLHttpRequest(); xhr = new XMLHttpRequest();
@ -240,7 +242,7 @@ L.BRouter = L.Class.extend({
xhr.send(profileText); xhr.send(profileText);
}, },
_assignFeatures: function (segment) { _assignFeatures(segment) {
if (segment.feature.properties.messages) { if (segment.feature.properties.messages) {
var featureMessages = segment.feature.properties.messages, var featureMessages = segment.feature.properties.messages,
segmentLatLngs = segment.getLatLngs(), segmentLatLngs = segment.getLatLngs(),
@ -267,14 +269,14 @@ L.BRouter = L.Class.extend({
return segment; return segment;
}, },
_getFeatureLatLng: function (message) { _getFeatureLatLng(message) {
var lon = message[0] / 1000000, var lon = message[0] / 1000000,
lat = message[1] / 1000000; lat = message[1] / 1000000;
return L.latLng(lat, lon); return L.latLng(lat, lon);
}, },
_handleProfileResponse: function (xhr, cb) { _handleProfileResponse(xhr, cb) {
var response; var response;
if (xhr.status === 200 && xhr.responseText && xhr.responseText.length > 0) { if (xhr.status === 200 && xhr.responseText && xhr.responseText.length > 0) {
@ -285,7 +287,7 @@ L.BRouter = L.Class.extend({
} }
}, },
_getLonLatsString: function (latLngs) { _getLonLatsString(latLngs) {
var s = ''; var s = '';
for (var i = 0; i < latLngs.length; i++) { for (var i = 0; i < latLngs.length; i++) {
s += this._formatLatLng(latLngs[i]); s += this._formatLatLng(latLngs[i]);
@ -296,7 +298,7 @@ L.BRouter = L.Class.extend({
return s; return s;
}, },
_parseLonLats: function (s) { _parseLonLats(s) {
var groups, var groups,
numbers, numbers,
lonlats = []; lonlats = [];
@ -315,7 +317,7 @@ L.BRouter = L.Class.extend({
return lonlats; return lonlats;
}, },
_getBeelineString: function (beelineFlags) { _getBeelineString(beelineFlags) {
var indexes = []; var indexes = [];
for (var i = 0; i < beelineFlags.length; i++) { for (var i = 0; i < beelineFlags.length; i++) {
if (beelineFlags[i]) { if (beelineFlags[i]) {
@ -325,7 +327,7 @@ L.BRouter = L.Class.extend({
return indexes.join(','); return indexes.join(',');
}, },
_parseBeelines: function (s, lonlats) { _parseBeelines(s, lonlats) {
if (!lonlats || lonlats.length < 2) return []; if (!lonlats || lonlats.length < 2) return [];
const beelineFlags = new Array(lonlats.length - 1); const beelineFlags = new Array(lonlats.length - 1);
@ -336,7 +338,7 @@ L.BRouter = L.Class.extend({
return beelineFlags; return beelineFlags;
}, },
_getLonLatsNameString: function (latLngNames) { _getLonLatsNameString(latLngNames) {
var s = ''; var s = '';
for (var i = 0; i < latLngNames.length; i++) { for (var i = 0; i < latLngNames.length; i++) {
s += this._formatLatLng(latLngNames[i].latlng); s += this._formatLatLng(latLngNames[i].latlng);
@ -350,7 +352,7 @@ L.BRouter = L.Class.extend({
return s; return s;
}, },
_parseLonLatNames: function (s) { _parseLonLatNames(s) {
var groups, var groups,
part, part,
lonlatnames = []; lonlatnames = [];
@ -369,7 +371,7 @@ L.BRouter = L.Class.extend({
return lonlatnames; return lonlatnames;
}, },
_getNogosString: function (nogos) { _getNogosString(nogos) {
var s = ''; var s = '';
for (var i = 0, circle; i < nogos.length; i++) { for (var i = 0, circle; i < nogos.length; i++) {
circle = nogos[i]; circle = nogos[i];
@ -392,7 +394,7 @@ L.BRouter = L.Class.extend({
return s; return s;
}, },
_parseNogos: function (s) { _parseNogos(s) {
var groups, var groups,
numbers, numbers,
nogos = []; nogos = [];
@ -418,7 +420,7 @@ L.BRouter = L.Class.extend({
return nogos; return nogos;
}, },
_getNogosPolylinesString: function (nogos) { _getNogosPolylinesString(nogos) {
var s = ''; var s = '';
for (var i = 0, polyline, vertices; i < nogos.length; i++) { for (var i = 0, polyline, vertices; i < nogos.length; i++) {
polyline = nogos[i]; polyline = nogos[i];
@ -445,7 +447,7 @@ L.BRouter = L.Class.extend({
return s; return s;
}, },
_parseNogosPolylines: function (s) { _parseNogosPolylines(s) {
var groups, var groups,
numbers, numbers,
latlngs, latlngs,
@ -465,14 +467,14 @@ L.BRouter = L.Class.extend({
if (j < numbers.length) { if (j < numbers.length) {
nogoWeight = Number.parseFloat(numbers[j++]); nogoWeight = Number.parseFloat(numbers[j++]);
} }
var options = L.extend(BR.NogoAreas.prototype.polylineOptions, { nogoWeight: nogoWeight }); var options = L.extend(BR.NogoAreas.prototype.polylineOptions, { nogoWeight });
nogos.push(L.polyline(latlngs, options)); nogos.push(L.polyline(latlngs, options));
} }
} }
return nogos; return nogos;
}, },
_getNogosPolygonsString: function (nogos) { _getNogosPolygonsString(nogos) {
var s = ''; var s = '';
for (var i = 0, polygon, vertices; i < nogos.length; i++) { for (var i = 0, polygon, vertices; i < nogos.length; i++) {
polygon = nogos[i]; polygon = nogos[i];
@ -499,7 +501,7 @@ L.BRouter = L.Class.extend({
return s; return s;
}, },
_parseNogosPolygons: function (s) { _parseNogosPolygons(s) {
var groups, var groups,
numbers, numbers,
latlngs, latlngs,
@ -519,13 +521,13 @@ L.BRouter = L.Class.extend({
if (j < numbers.length) { if (j < numbers.length) {
nogoWeight = Number.parseFloat(numbers[j++]); nogoWeight = Number.parseFloat(numbers[j++]);
} }
nogos.push(L.polygon(latlngs, { nogoWeight: nogoWeight })); nogos.push(L.polygon(latlngs, { nogoWeight }));
} }
} }
return nogos; return nogos;
}, },
_parseProfile: function (profile) { _parseProfile(profile) {
if (BR.conf.profilesRename?.[profile]) { if (BR.conf.profilesRename?.[profile]) {
return BR.conf.profilesRename[profile]; return BR.conf.profilesRename[profile];
} }
@ -534,7 +536,7 @@ L.BRouter = L.Class.extend({
}, },
// formats L.LatLng object as lng,lat string // formats L.LatLng object as lng,lat string
_formatLatLng: function (latLng) { _formatLatLng(latLng) {
var s = ''; var s = '';
s += L.Util.formatNum(latLng.lng ?? latLng[1], L.BRouter.PRECISION); s += L.Util.formatNum(latLng.lng ?? latLng[1], L.BRouter.PRECISION);
s += L.BRouter.NUMBER_SEPARATOR; s += L.BRouter.NUMBER_SEPARATOR;

View file

@ -24,6 +24,6 @@ var brouterCgi = (function () {
} }
return { return {
getUrl: getUrl, getUrl,
}; };
})(); })();

View file

@ -15,16 +15,16 @@ BR.ClickTolerantBoxZoom = L.Map.BoxZoom.extend({
// already signals dragging to map and thus prevents click // already signals dragging to map and thus prevents click
_preMoved: false, _preMoved: false,
moved: function () { moved() {
return this._preMoved || this._moved; return this._preMoved || this._moved;
}, },
_resetState: function () { _resetState() {
L.Map.BoxZoom.prototype._resetState.call(this); L.Map.BoxZoom.prototype._resetState.call(this);
this._preMoved = false; this._preMoved = false;
}, },
_onMouseMove: function (e) { _onMouseMove(e) {
if (!this._moved) { if (!this._moved) {
const point = this._map.mouseEventToContainerPoint(e); const point = this._map.mouseEventToContainerPoint(e);
@ -44,7 +44,7 @@ BR.ClickTolerantBoxZoom = L.Map.BoxZoom.extend({
L.Map.BoxZoom.prototype._onMouseMove.call(this, e); L.Map.BoxZoom.prototype._onMouseMove.call(this, e);
}, },
_onMouseUp: function (e) { _onMouseUp(e) {
L.Map.BoxZoom.prototype._onMouseUp.call(this, e); L.Map.BoxZoom.prototype._onMouseUp.call(this, e);
if (!this._moved && this._preMoved) { if (!this._moved && this._preMoved) {

View file

@ -33,11 +33,11 @@
* Only load Maplibre bundles when layer is actually added, using dynamic imports * Only load Maplibre bundles when layer is actually added, using dynamic imports
*/ */
BR.MaplibreGlLazyLoader = L.Layer.extend({ BR.MaplibreGlLazyLoader = L.Layer.extend({
initialize: function (options) { initialize(options) {
this.options = options; this.options = options;
}, },
onAdd: function (map) { onAdd(map) {
if (!('maplibreGL' in L)) { if (!('maplibreGL' in L)) {
this._load(); this._load();
} else { } else {
@ -46,7 +46,7 @@
return this; return this;
}, },
onRemove: function (map) { onRemove(map) {
if (this.glLayer) { if (this.glLayer) {
this._map.removeLayer(this.glLayer); this._map.removeLayer(this.glLayer);
} }
@ -55,12 +55,12 @@
}, },
// needed when overlay, also requires `position: absolute` (see css) // needed when overlay, also requires `position: absolute` (see css)
setZIndex: function (zIndex) { setZIndex(zIndex) {
this.options.zIndex = zIndex; this.options.zIndex = zIndex;
return this; return this;
}, },
setOpacity: function (opacity) { setOpacity(opacity) {
if (this.glLayer) { if (this.glLayer) {
const glMap = this.glLayer.getMaplibreMap(); const glMap = this.glLayer.getMaplibreMap();
if (glMap.getLayer('hillshading')) { if (glMap.getLayer('hillshading')) {
@ -71,14 +71,14 @@
} }
}, },
_load: async function () { async _load() {
await importPolyfill('./maplibre-gl.js'); await importPolyfill('./maplibre-gl.js');
await importPolyfill('./leaflet-maplibre-gl.js'); await importPolyfill('./leaflet-maplibre-gl.js');
this._addGlLayer(); this._addGlLayer();
}, },
_addGlLayer: function () { _addGlLayer() {
this.glLayer = L.maplibreGL(this.options); this.glLayer = L.maplibreGL(this.options);
// see LayersConfig.createLayer // see LayersConfig.createLayer
this.glLayer.getAttribution = function () { this.glLayer.getAttribution = function () {
@ -89,7 +89,7 @@
this._updateZIndex(); this._updateZIndex();
}, },
_updateZIndex: function () { _updateZIndex() {
if (this.glLayer && this.glLayer.getContainer() && this.options.zIndex != null) { if (this.glLayer && this.glLayer.getContainer() && this.options.zIndex != null) {
this.glLayer.getContainer().style.zIndex = this.options.zIndex; this.glLayer.getContainer().style.zIndex = this.options.zIndex;
} }

View file

@ -10,7 +10,7 @@ BR.Track = {
* *
* @returns {Object} to pass as `options` parameter to `L.geoJson` * @returns {Object} to pass as `options` parameter to `L.geoJson`
*/ */
getGeoJsonOptions: function (layersControl, filterPois = false) { getGeoJsonOptions(layersControl, filterPois = false) {
// https://github.com/mapbox/simplestyle-spec/tree/master/1.1.0 // https://github.com/mapbox/simplestyle-spec/tree/master/1.1.0
const styleMapping = [ const styleMapping = [
['stroke', 'color'], ['stroke', 'color'],
@ -20,7 +20,7 @@ BR.Track = {
['fill-opacity', 'fillOpacity'], ['fill-opacity', 'fillOpacity'],
]; ];
return { return {
style: function (geoJsonFeature) { style(geoJsonFeature) {
var currentLayerId = layersControl?.getActiveBaseLayer().layer.id; var currentLayerId = layersControl?.getActiveBaseLayer().layer.id;
const featureStyle = { const featureStyle = {
color: currentLayerId === 'cyclosm' ? 'yellow' : 'blue', color: currentLayerId === 'cyclosm' ? 'yellow' : 'blue',
@ -34,14 +34,14 @@ BR.Track = {
return featureStyle; return featureStyle;
}, },
interactive: false, interactive: false,
filter: function (geoJsonFeature) { filter(geoJsonFeature) {
if (filterPois) { if (filterPois) {
// remove POIs, added separately, see `addPoiMarkers` // remove POIs, added separately, see `addPoiMarkers`
return !BR.Track.isPoiPoint(geoJsonFeature); return !BR.Track.isPoiPoint(geoJsonFeature);
} }
return true; return true;
}, },
pointToLayer: function (geoJsonPoint, latlng) { pointToLayer(geoJsonPoint, latlng) {
// route waypoint (type=from/via/to) // route waypoint (type=from/via/to)
return L.marker(latlng, { return L.marker(latlng, {
interactive: false, interactive: false,
@ -60,7 +60,7 @@ BR.Track = {
* @param {BR.PoiMarkers} pois POI control instance * @param {BR.PoiMarkers} pois POI control instance
* @param {Object} geoJson GeoJSON object * @param {Object} geoJson GeoJSON object
*/ */
addPoiMarkers: function (pois, geoJson) { addPoiMarkers(pois, geoJson) {
turf.featureEach(geoJson, function (feature, idx) { turf.featureEach(geoJson, function (feature, idx) {
if (BR.Track.isPoiPoint(feature)) { if (BR.Track.isPoiPoint(feature)) {
var coord = turf.getCoord(feature); var coord = turf.getCoord(feature);
@ -80,7 +80,7 @@ BR.Track = {
* *
* @param {Object} geoJsonPointFeature GeoJSON Point feature * @param {Object} geoJsonPointFeature GeoJSON Point feature
*/ */
isRouteWaypoint: function (geoJsonPointFeature) { isRouteWaypoint(geoJsonPointFeature) {
var props = geoJsonPointFeature.properties; var props = geoJsonPointFeature.properties;
if (props && props.type) { if (props && props.type) {
var wptType = props.type; var wptType = props.type;
@ -96,7 +96,7 @@ BR.Track = {
* *
* @param {Object} geoJsonFeature GeoJSON feature * @param {Object} geoJsonFeature GeoJSON feature
*/ */
isPoiPoint: function (geoJsonFeature) { isPoiPoint(geoJsonFeature) {
return turf.getType(geoJsonFeature) === 'Point' && !BR.Track.isRouteWaypoint(geoJsonFeature); return turf.getType(geoJsonFeature) === 'Point' && !BR.Track.isRouteWaypoint(geoJsonFeature);
}, },
}; };

View file

@ -6,7 +6,7 @@
*/ */
BR.TrackEdges = L.Class.extend({ BR.TrackEdges = L.Class.extend({
statics: { statics: {
getFeature: function (featureMessage) { getFeature(featureMessage) {
//["Longitude", "Latitude", "Elevation", "Distance", "CostPerKm", "ElevCost", "TurnCost", "NodeCost", "InitialCost", "WayTags", "NodeTags"] //["Longitude", "Latitude", "Elevation", "Distance", "CostPerKm", "ElevCost", "TurnCost", "NodeCost", "InitialCost", "WayTags", "NodeTags"]
return { return {
cost: { cost: {
@ -35,7 +35,7 @@ BR.TrackEdges = L.Class.extend({
/** /**
* @param {Array} segments * @param {Array} segments
*/ */
initialize: function (segments) { initialize(segments) {
this.edges = this.getTrackEdges(segments); this.edges = this.getTrackEdges(segments);
}, },
@ -48,7 +48,7 @@ BR.TrackEdges = L.Class.extend({
* *
* @return {number[]} * @return {number[]}
*/ */
getTrackEdges: function (segments) { getTrackEdges(segments) {
var messages, var messages,
segLatLngs, segLatLngs,
length, length,
@ -88,7 +88,7 @@ BR.TrackEdges = L.Class.extend({
return edges; return edges;
}, },
getMessageLatLng: function (message) { getMessageLatLng(message) {
var lon = message[0] / 1000000, var lon = message[0] / 1000000,
lat = message[1] / 1000000; lat = message[1] / 1000000;

View file

@ -146,6 +146,7 @@ BR.confLayers.tree = {
'parking_entrance', 'parking_entrance',
'parking', 'parking',
'parking_space', 'parking_space',
'railway_station',
'taxi', 'taxi',
'vehicle_inspection', 'vehicle_inspection',
] ]

View file

@ -0,0 +1,13 @@
{
"geometry": null,
"properties": {
"name": "Railway station",
"id": "railway_station",
"overlay": true,
"dataSource": "OverpassAPI",
"icon": "temaki-train",
"query": "nwr[railway=station];"
},
"type": "Feature"
}

View file

@ -285,10 +285,67 @@
}, },
"sidebar": { "sidebar": {
"analysis": { "analysis": {
"data": {
"highway": {
"footway": "Footway",
"path": "Path",
"residential": "Residential",
"cycleway": "Cycleway",
"track": "Track",
"service": "Service",
"tertiary": "Tertiary",
"secondary": "Secondary",
"primary": "Primary",
"trunk": "Trunk",
"motorway": "Motorway",
"motorway_link": "Motorway Link",
"primary_link": "Primary Link",
"secondary_link": "Secondary Link",
"tertiary_link": "Tertiary Link",
"trunk_link": "Trunk Link",
"living_street": "Living Street",
"pedestrian": "Pedestrian",
"road": "Road",
"bridleway": "Bridleway",
"steps": "Steps",
"sidewalk": "Sidewalk",
"crossing": "Crossing",
"unclassified": "Unclassified"
},
"surface": {
"asphalt": "Asphalt",
"cobblestone": "Cobblestone",
"compacted": "Compacted",
"dirt": "Dirt",
"fine_gravel": "Fine Gravel",
"grass": "Grass",
"gravel": "Gravel",
"ground": "Ground",
"paved": "Paved",
"sand": "Sand",
"unpaved": "Unpaved",
"wood": "Wood",
"concrete": "Concrete",
"paving_stones": "Paving Stones",
"sett": "Sett"
},
"smoothness": {
"excellent": "Excellent",
"good": "Good",
"intermediate": "Intermediate",
"bad": "Bad",
"very_bad": "Very Bad",
"horrible": "Horrible",
"very_horrible": "Very Horrible",
"impassable": "Impassable"
},
"maxspeed": "{{maxspeed}} km/h"
},
"header": { "header": {
"highway": "Highway", "highway": "Highway",
"smoothness": "Smoothness", "smoothness": "Smoothness",
"surface": "Surface" "surface": "Surface",
"maxspeed": "Maximum Speed"
}, },
"table": { "table": {
"category": "Category", "category": "Category",

View file

@ -39,7 +39,7 @@
"@mapbox/maki": "8.0.1", "@mapbox/maki": "8.0.1",
"@mapbox/polyline": "1.1.1", "@mapbox/polyline": "1.1.1",
"@mapbox/togeojson": "0.16.2", "@mapbox/togeojson": "0.16.2",
"@maplibre/maplibre-gl-leaflet": "0.0.19", "@maplibre/maplibre-gl-leaflet": "0.0.20",
"@turf/turf": "6.5.0", "@turf/turf": "6.5.0",
"Leaflet.vector-markers": "nrenner/Leaflet.vector-markers#2ef80c9", "Leaflet.vector-markers": "nrenner/Leaflet.vector-markers#2ef80c9",
"abortcontroller-polyfill": "1.7.5", "abortcontroller-polyfill": "1.7.5",
@ -54,7 +54,7 @@
"datatables": "1.10.18", "datatables": "1.10.18",
"fit-file-writer": "tbsmark86/fit-file-writer#3eebe13", "fit-file-writer": "tbsmark86/fit-file-writer#3eebe13",
"font-awesome": "4.7.0", "font-awesome": "4.7.0",
"geo-data-exchange": "alexcojocaru/geo-data-exchange#v2.0.0", "geo-data-exchange": "alexcojocaru/geo-data-exchange#v2.2.0",
"i18next": "19.9.2", "i18next": "19.9.2",
"i18next-browser-languagedetector": "7.0.2", "i18next-browser-languagedetector": "7.0.2",
"i18next-xhr-backend": "3.2.2", "i18next-xhr-backend": "3.2.2",
@ -367,7 +367,8 @@
"icons/museum.svg", "icons/museum.svg",
"icons/spotting_scope.svg", "icons/spotting_scope.svg",
"icons/cabin.svg", "icons/cabin.svg",
"icons/picnic_shelter.svg" "icons/picnic_shelter.svg",
"icons/train.svg"
] ]
}, },
"@fortawesome/fontawesome-free": { "@fortawesome/fontawesome-free": {

View file

@ -1397,10 +1397,10 @@
resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe" resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe"
integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q== integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==
"@maplibre/maplibre-gl-leaflet@0.0.19": "@maplibre/maplibre-gl-leaflet@0.0.20":
version "0.0.19" version "0.0.20"
resolved "https://registry.yarnpkg.com/@maplibre/maplibre-gl-leaflet/-/maplibre-gl-leaflet-0.0.19.tgz#adea2fe9890978c705f12a6274a6dc8b1467d02b" resolved "https://registry.yarnpkg.com/@maplibre/maplibre-gl-leaflet/-/maplibre-gl-leaflet-0.0.20.tgz#9b68bcb2226f300f3cf03865aa97647ca95f30ee"
integrity sha512-NwWqmE8Lmx8uMQS8sgHzGTz/CPfLBnbGns5BjXTmj459BUd7leCx3TVVhg04Pea4fzJeGaiyS2+KdWUVtKNuHg== integrity sha512-W36NFgRbhOic/Bv2dU4f6P3BE2QlhPbselQdf0snY4E36kjmhAl9RKEfAGDmfI1T5bUOmPmWzQDRnvEWqGc+jw==
"@mdn/browser-compat-data@^3.3.14": "@mdn/browser-compat-data@^3.3.14":
version "3.3.14" version "3.3.14"
@ -5632,9 +5632,9 @@ gensync@^1.0.0-beta.2:
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
geo-data-exchange@alexcojocaru/geo-data-exchange#v2.0.0: geo-data-exchange@alexcojocaru/geo-data-exchange#v2.2.0:
version "2.0.0" version "2.2.0"
resolved "https://codeload.github.com/alexcojocaru/geo-data-exchange/tar.gz/f3964028483ce194700f98c3d9c241818b54062b" resolved "https://codeload.github.com/alexcojocaru/geo-data-exchange/tar.gz/d6d517dee5e07e32ef948eecd7a151479a6d7938"
dependencies: dependencies:
leaflet "^1.5.0" leaflet "^1.5.0"