Merge branch 'master' into master
This commit is contained in:
commit
42abbbcb75
104 changed files with 26871 additions and 1753 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,4 +1,3 @@
|
|||
bower_components/
|
||||
node_modules/
|
||||
nbproject/
|
||||
.idea/
|
||||
|
|
@ -7,3 +6,4 @@ nbproject/
|
|||
/keys.js
|
||||
/dist
|
||||
brouter-web.*.zip
|
||||
yarn-error.log
|
||||
|
|
|
|||
10
.prettierignore
Normal file
10
.prettierignore
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
LICENSE
|
||||
dist/
|
||||
*.zip
|
||||
yarn.lock
|
||||
.idea
|
||||
.gitignore
|
||||
.prettierignore
|
||||
.tx/
|
||||
layers/
|
||||
locales/*.json
|
||||
4
.prettierrc
Normal file
4
.prettierrc
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"singleQuote": true,
|
||||
"tabWidth": 4
|
||||
}
|
||||
4
.travis.yml
Normal file
4
.travis.yml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- lts/*
|
||||
cache: yarn
|
||||
10
.tx/config
Normal file
10
.tx/config
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[main]
|
||||
host = https://www.transifex.com
|
||||
minimum_perc = 1
|
||||
lang_map = fr_CA:fr-CA,pt_BR:pt-BR,zh_CN:zh-CN,zh_HK:zh-HK,zh_TW:zh-TW,da_DK:da-DK,sv_SE:sv-SE,kn_IN:kn-IN,nl_NL:nl-NL,en_NL:en-NL,gl_ES:gl-ES
|
||||
|
||||
[brouter-web.brouter-website]
|
||||
file_filter = locales/<lang>.json
|
||||
source_file = locales/en.json
|
||||
source_lang = en
|
||||
type = JSON
|
||||
205
CHANGELOG.md
205
CHANGELOG.md
|
|
@ -1,17 +1,137 @@
|
|||
BRouter-Web Changelog
|
||||
=====================
|
||||
# BRouter-Web Changelog
|
||||
|
||||
## 0.10.3 (2019-06-27)
|
||||
|
||||
See also [milestone 0.10.3](https://github.com/nrenner/brouter-web/milestone/11?closed=1)
|
||||
|
||||
### Bugfixes
|
||||
|
||||
- Warn when special characters in export name will get removed ([#194](https://github.com/nrenner/brouter-web/issues/194), [#202](https://github.com/nrenner/brouter-web/issues/202))
|
||||
- Fix %-encoded export file name in Microsoft Edge ([#201](https://github.com/nrenner/brouter-web/issues/201))
|
||||
- Fix error when no elevation data above 60° north, causing empty stats and disabled export, by implementing own missing data handling for elevation diagram ([#203](https://github.com/nrenner/brouter-web/issues/203))
|
||||
|
||||
### Improvements
|
||||
|
||||
- Reduce tile.openstreetmap.org usage ([#205](https://github.com/nrenner/brouter-web/issues/205))
|
||||
- use a worldwide monolingual layer (de, fr, ru) as default when matching the browser language
|
||||
- remember the last selected layers (like map view), so it doesn't load the default layer next time
|
||||
- default zoom level 5 instead of 6, which seems to be cached longer
|
||||
- Upgrade Gulp (build tool) to version 4.0.2 - by [@Phyks](https://github.com/Phyks) ([#209](https://github.com/nrenner/brouter-web/pull/209))
|
||||
- Upgrade leaflet geocoder to properly parse lat/lng - by [@bagage](https://github.com/bagage) ([#134](https://github.com/nrenner/brouter-web/issues/134))
|
||||
- Upgrade to latest Bootstrap (front-end framework) - by [@bagage](https://github.com/bagage) ([#186](https://github.com/nrenner/brouter-web/pull/186))
|
||||
|
||||
## 0.10.2 (2019-06-02)
|
||||
|
||||
See also [milestone 0.10.2](https://github.com/nrenner/brouter-web/milestone/10?closed=1)
|
||||
|
||||
### New Features
|
||||
|
||||
- Polish formatting and behaviour of track statistics bar - by [@rkflx](https://github.com/rkflx) ([#200](https://github.com/nrenner/brouter-web/pull/200))
|
||||
|
||||
### Bugfixes
|
||||
|
||||
- Fix unintentional shortcut activations when typing text - by [@rkflx](https://github.com/rkflx) ([#198](https://github.com/nrenner/brouter-web/pull/198))
|
||||
- Fix export button translation - by [@bagage](https://github.com/bagage) ([#195](https://github.com/nrenner/brouter-web/issues/195))
|
||||
- Fix downloads in Microsoft Edge - by [@bagage](https://github.com/bagage) ([#193](https://github.com/nrenner/brouter-web/issues/193))
|
||||
|
||||
## 0.10.1 (2019-05-22)
|
||||
|
||||
### Bugfixes
|
||||
|
||||
- Really ignore missing elevation points in elevation chart - by [@bagage](https://github.com/bagage)/[@nrenner](https://github.com/nrenner) ([#147](https://github.com/nrenner/brouter-web/issues/147))
|
||||
|
||||
## 0.10.0 (2019-05-21)
|
||||
|
||||
See also [milestone 0.10.0](https://github.com/nrenner/brouter-web/milestone/9?closed=1)
|
||||
|
||||
### New Features
|
||||
|
||||
- Export dialog with input field for file name and track title (replaces Download dropdown) - by [@bagage](https://github.com/bagage) ([#96](https://github.com/nrenner/brouter-web/issues/96))
|
||||
|
||||
### Bugfixes
|
||||
|
||||
- Fix broken nogo's - by [@bagage](https://github.com/bagage)/[@nrenner](https://github.com/nrenner) ([#183](https://github.com/nrenner/brouter-web/issues/183))
|
||||
|
||||
## 0.9.0 (2019-05-18)
|
||||
|
||||
See also [milestone 0.9.0](https://github.com/nrenner/brouter-web/milestone/8?closed=1)
|
||||
|
||||
### New Features
|
||||
|
||||
- Add delete last point button - by [@bagage](https://github.com/bagage) ([#33](https://github.com/nrenner/brouter-web/issues/33))
|
||||
- Add reverse route button - by [@bagage](https://github.com/bagage) ([#54](https://github.com/nrenner/brouter-web/issues/54))
|
||||
|
||||
### Improvements
|
||||
|
||||
- Improve about dialog texts - by [@bagage](https://github.com/bagage) ([#176](https://github.com/nrenner/brouter-web/pull/176))
|
||||
- Replace | with ; in URL - by [@bagage](https://github.com/bagage) ([#109](https://github.com/nrenner/brouter-web/issues/109))
|
||||
|
||||
### Bugfixes
|
||||
|
||||
- Ignore missing elevation points in elevation chart - by [@bagage](https://github.com/bagage) ([#147](https://github.com/nrenner/brouter-web/issues/147))
|
||||
- Fix loading nogos with weight - by [@Phyks](https://github.com/Phyks) ([#174](https://github.com/nrenner/brouter-web/issues/174))
|
||||
- Fix wrong version under tag ([#140](https://github.com/nrenner/brouter-web/issues/140))
|
||||
|
||||
## 0.8.0 (2019-05-04)
|
||||
|
||||
See also [milestone 0.8.0](https://github.com/nrenner/brouter-web/milestone/6?closed=1)
|
||||
|
||||
### New Features
|
||||
|
||||
- Optional layers tree ([#146](https://github.com/nrenner/brouter-web/issues/146))
|
||||
- Let user upload GeoJSON file of nogos - by [@Phyks](https://github.com/Phyks) ([#161](https://github.com/nrenner/brouter-web/pull/161))
|
||||
- Translations: make website localizable (i18n) - by [@bagage](https://github.com/bagage) ([#63](https://github.com/nrenner/brouter-web/issues/63))
|
||||
- Fix polygon edition - by [@Phyks](https://github.com/Phyks) ([#158](https://github.com/nrenner/brouter-web/pull/158))
|
||||
- Render polygons from URL hash and pass it to BRouter server - by [@Phyks](https://github.com/Phyks) ([#157](https://github.com/nrenner/brouter-web/pull/157))
|
||||
- Start support of nogos polylines/polygons - by [@Phyks](https://github.com/Phyks) ([#148](https://github.com/nrenner/brouter-web/pull/148))
|
||||
|
||||
### Improvements
|
||||
|
||||
- Show line numbers in profile editor to help locating error message line ([81f2c08](https://github.com/nrenner/brouter-web/commit/81f2c0863f2569fa9079e5c96f4c9b09ef4c26e2))
|
||||
- Hide StravaSegments control when layer is not active ([eaba5a0](https://github.com/nrenner/brouter-web/commit/eaba5a08217fd026fb7f83ec7beb7c1f1fdc2d69))
|
||||
- Show strava error + update translations - by [@bagage](https://github.com/bagage) ([#163](https://github.com/nrenner/brouter-web/pull/163))
|
||||
- Replace Bower with Yarn/npm - by [@bagage](https://github.com/bagage) ([#116](https://github.com/nrenner/brouter-web/issues/116))
|
||||
- Add strava layer in overlays - by [@bagage](https://github.com/bagage) ([#152](https://github.com/nrenner/brouter-web/pull/152))
|
||||
- Fix release script - by [@bagage](https://github.com/bagage) ([#150](https://github.com/nrenner/brouter-web/pull/150))
|
||||
|
||||
### Bugfixes
|
||||
|
||||
- Overlays hidden under custom layer ([#143](https://github.com/nrenner/brouter-web/issues/143))
|
||||
|
||||
## 0.7.0 (2018-10-10)
|
||||
|
||||
See also [milestone 0.7.0](https://github.com/nrenner/brouter-web/milestone/4?closed=1)
|
||||
|
||||
### New Features
|
||||
|
||||
- Redesign of the user interface to also support mobile devices - by [@bagage](https://github.com/bagage) and [@RoPP](https://github.com/RoPP) ([#34](https://github.com/nrenner/brouter-web/issues/34), [#66](https://github.com/nrenner/brouter-web/issues/66))
|
||||
- Permalink replaced with auto-updating URL address bar - by [@bagage](https://github.com/bagage) ([#62](https://github.com/nrenner/brouter-web/issues/62))
|
||||
- Allow user to add custom layers - by [@bagage](https://github.com/bagage) ([#77](https://github.com/nrenner/brouter-web/pull/77))
|
||||
- Profile and data table now in a collapsible, full-height sidebar ([#90](https://github.com/nrenner/brouter-web/issues/90), [#114](https://github.com/nrenner/brouter-web/issues/114))
|
||||
- No-go areas individually editable and deletable ([#100](https://github.com/nrenner/brouter-web/issues/100))
|
||||
|
||||
### Improvements
|
||||
|
||||
- New gulp debug task and watch CSS folder - by [@bagage](https://github.com/bagage) ([#58](https://github.com/nrenner/brouter-web/pull/58))
|
||||
- Locate button not shown when no https ([#60](https://github.com/nrenner/brouter-web/issues/60))
|
||||
- Support Leaflet 1.0 ([#65](https://github.com/nrenner/brouter-web/issues/65), [#69](https://github.com/nrenner/brouter-web/issues/69))
|
||||
- Add a gulp command for release - by [@RoPP](https://github.com/RoPP) ([#85](https://github.com/nrenner/brouter-web/pull/85))
|
||||
- Use https scheme whenever possible, to avoid mixed content issues - by [@bagage](https://github.com/bagage) ([#87](https://github.com/nrenner/brouter-web/pull/87))
|
||||
- Add car-eco/fast profiles + display energy/time - by [@abrensch](https://github.com/abrensch) ([#95](https://github.com/nrenner/brouter-web/pull/95))
|
||||
- Improve error message if no route found - by [@bagage](https://github.com/bagage) ([#99](https://github.com/nrenner/brouter-web/issues/99))
|
||||
- Support zoom 19 for German style - by [@giggls](https://github.com/giggls) ([#128](https://github.com/nrenner/brouter-web/pull/128))
|
||||
|
||||
## 0.6.3 (2017-03-16)
|
||||
|
||||
* Fix data tab showing only two rows (regression from v0.6.2) ([#72](https://github.com/nrenner/brouter-web/issues/72))
|
||||
- Fix data tab showing only two rows (regression from v0.6.2) ([#72](https://github.com/nrenner/brouter-web/issues/72))
|
||||
|
||||
## 0.6.2 (2017-03-14)
|
||||
|
||||
* Fix "API Key Required" in OpenCycleMap & Outdoors by registering for Thunderforest "Hobby Project" plan ([#70](https://github.com/nrenner/brouter-web/issues/70))
|
||||
- Fix "API Key Required" in OpenCycleMap & Outdoors by registering for Thunderforest "Hobby Project" plan ([#70](https://github.com/nrenner/brouter-web/issues/70))
|
||||
|
||||
## 0.6.1 (2016-12-12)
|
||||
|
||||
* Add Esri World Imagery layer (DigitalGlobe is now also blocked because monthly usage limit is exceeded)
|
||||
- Add Esri World Imagery layer (DigitalGlobe is now also blocked because monthly usage limit is exceeded)
|
||||
|
||||
## 0.6.0 (2016-10-11)
|
||||
|
||||
|
|
@ -19,66 +139,65 @@ See also [milestone 0.6.0](https://github.com/nrenner/brouter-web/milestone/1?cl
|
|||
|
||||
### Features/Improvements
|
||||
|
||||
* Update OpenTopoMap zoom range to 0-17
|
||||
* [local installation] Option to remove default base layers ([#27](https://github.com/nrenner/brouter-web/issues/27))
|
||||
* Add tooltip to display length in meter precision (3 digits) ([#38](https://github.com/nrenner/brouter-web/issues/38))
|
||||
* Add "mean cost" to route statistics ([#39](https://github.com/nrenner/brouter-web/issues/39))
|
||||
* Set route transparency slider to partially transparent by default ([#36](https://github.com/nrenner/brouter-web/issues/36))
|
||||
* Show position in elevation diagram when hovering path on map ([#29](https://github.com/nrenner/brouter-web/issues/29))
|
||||
* [local installation] Added ability to specify custom overlays in configuration - by [@saesh](https://github.com/saesh) ([#46](https://github.com/nrenner/brouter-web/pull/46))
|
||||
* Add button to get/follow the current location (leaflet.locatecontrol plugin) - by [@bagage](https://github.com/bagage) ([#49](https://github.com/nrenner/brouter-web/pull/49))
|
||||
* Save and restore last map position (leaflet.restoreview.js plugin) - by [@bagage](https://github.com/bagage) ([#49](https://github.com/nrenner/brouter-web/pull/49))
|
||||
* Toggle drawing mode via panel button - by [@bagage](https://github.com/bagage) ([#50](https://github.com/nrenner/brouter-web/pull/50))
|
||||
* [local installation] add keys.js to configure API keys instead of bingkey request
|
||||
* Switch to new icon set (Font Awesome) with more options
|
||||
- Update OpenTopoMap zoom range to 0-17
|
||||
- [local installation] Option to remove default base layers ([#27](https://github.com/nrenner/brouter-web/issues/27))
|
||||
- Add tooltip to display length in meter precision (3 digits) ([#38](https://github.com/nrenner/brouter-web/issues/38))
|
||||
- Add "mean cost" to route statistics ([#39](https://github.com/nrenner/brouter-web/issues/39))
|
||||
- Set route transparency slider to partially transparent by default ([#36](https://github.com/nrenner/brouter-web/issues/36))
|
||||
- Show position in elevation diagram when hovering path on map ([#29](https://github.com/nrenner/brouter-web/issues/29))
|
||||
- [local installation] Added ability to specify custom overlays in configuration - by [@saesh](https://github.com/saesh) ([#46](https://github.com/nrenner/brouter-web/pull/46))
|
||||
- Add button to get/follow the current location (leaflet.locatecontrol plugin) - by [@bagage](https://github.com/bagage) ([#49](https://github.com/nrenner/brouter-web/pull/49))
|
||||
- Save and restore last map position (leaflet.restoreview.js plugin) - by [@bagage](https://github.com/bagage) ([#49](https://github.com/nrenner/brouter-web/pull/49))
|
||||
- Toggle drawing mode via panel button - by [@bagage](https://github.com/bagage) ([#50](https://github.com/nrenner/brouter-web/pull/50))
|
||||
- [local installation] add keys.js to configure API keys instead of bingkey request
|
||||
- Switch to new icon set (Font Awesome) with more options
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Replace Bing (usage limit exceeded) with DigitalGlobe Recent Imagery layer (newer images, but sometimes cloudy)
|
||||
* [local installation] Show error message for invalid server response with custom profiles on Windows (still needs to be fixed) ([#53](https://github.com/nrenner/brouter-web/issues/53))
|
||||
* Restrictive Cookie settings caused app to stop responding ([#47](https://github.com/nrenner/brouter-web/issues/47))
|
||||
- Replace Bing (usage limit exceeded) with DigitalGlobe Recent Imagery layer (newer images, but sometimes cloudy)
|
||||
- [local installation] Show error message for invalid server response with custom profiles on Windows (still needs to be fixed) ([#53](https://github.com/nrenner/brouter-web/issues/53))
|
||||
- Restrictive Cookie settings caused app to stop responding ([#47](https://github.com/nrenner/brouter-web/issues/47))
|
||||
|
||||
## 0.5.2 (2015-08-27)
|
||||
|
||||
* switch search from MapQuest to Nominatim (MapQuest licensing change)
|
||||
- switch search from MapQuest to Nominatim (MapQuest licensing change)
|
||||
|
||||
## 0.5.1 (2015-07-24)
|
||||
|
||||
* config option ``baseLayers`` to add custom base layers locally (#24)
|
||||
* reset slider on page load to minimum opacity (#22),
|
||||
customizable locally with config setting ``minOpacity``
|
||||
* set OpenTopoMap max zoom back to z15 while on fallback server (#21),
|
||||
- config option `baseLayers` to add custom base layers locally (#24)
|
||||
- reset slider on page load to minimum opacity (#22),
|
||||
customizable locally with config setting `minOpacity`
|
||||
- set OpenTopoMap max zoom back to z15 while on fallback server (#21),
|
||||
also fix max zoom of other services
|
||||
* overscale tiles to common max zoom (avoids gray screen when switching)
|
||||
- overscale tiles to common max zoom (avoids gray screen when switching)
|
||||
|
||||
## 0.5.0 (2015-07-01)
|
||||
|
||||
### Features
|
||||
|
||||
* Load profile content for selected profile (needs extra server locally)
|
||||
* Bing maps aerial layer (not working locally)
|
||||
* track color magenta instead of blue + white casing, for better contrast
|
||||
- Load profile content for selected profile (needs extra server locally)
|
||||
- Bing maps aerial layer (not working locally)
|
||||
- track color magenta instead of blue + white casing, for better contrast
|
||||
with background map (esp. OpenCycleMap)
|
||||
* transparency slider for route track and markers
|
||||
* button to delete route (#10)
|
||||
* map scale
|
||||
* download all dependencies in a bundle, instead using CDNs and separate files (#18)
|
||||
* switch search plugin for result-dependent zoom
|
||||
* "about" popup with a bit more infos and links
|
||||
* closable error/warning messages, profile messages in place
|
||||
- transparency slider for route track and markers
|
||||
- button to delete route (#10)
|
||||
- map scale
|
||||
- download all dependencies in a bundle, instead using CDNs and separate files (#18)
|
||||
- switch search plugin for result-dependent zoom
|
||||
- "about" popup with a bit more infos and links
|
||||
- closable error/warning messages, profile messages in place
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* keys to enable/disable drawing (d, q/esc) now always work, not only when map is focused
|
||||
* fix adding new waypoint after deleting the last (#11)
|
||||
* fix profile/data scrolling on Firefox
|
||||
* hide trailer over controls and outside map
|
||||
|
||||
- keys to enable/disable drawing (d, q/esc) now always work, not only when map is focused
|
||||
- fix adding new waypoint after deleting the last (#11)
|
||||
- fix profile/data scrolling on Firefox
|
||||
- hide trailer over controls and outside map
|
||||
|
||||
## BRouter 1.2
|
||||
|
||||
* data/CSV aggregated over segments with same tags (for better performance)
|
||||
- data/CSV aggregated over segments with same tags (for better performance)
|
||||
|
||||
## 0.4.0 (2015-03-08)
|
||||
|
||||
* data tab (slow with long routes, exp. on Firefox)
|
||||
- data tab (slow with long routes, exp. on Firefox)
|
||||
|
|
|
|||
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Norbert Renner and contributors
|
||||
Copyright (c) 2018 Norbert Renner and contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
|
|
|||
191
README.md
191
README.md
|
|
@ -1,22 +1,33 @@
|
|||
brouter-web
|
||||
===========
|
||||
# brouter-web
|
||||
|
||||
Web client (by [@nrenner](https://github.com/nrenner)) for the BRouter routing engine (by [@abrensch](https://github.com/abrensch)). *Work in progress*.
|
||||
Web client (by [@nrenner](https://github.com/nrenner) and [contributors](https://github.com/nrenner/brouter-web/graphs/contributors)) for the BRouter routing engine (by [@abrensch](https://github.com/abrensch)). _Work in progress_.
|
||||
|
||||
**New web client available mobile-ready to test on [brouter.damsy.net](http://brouter.damsy.net).
|
||||
Feedbacks are appreciated, do not hesitate to create issues about it!**
|
||||
Instances:
|
||||
|
||||
BRouter online service (provided by [@abrensch](https://github.com/abrensch)):
|
||||
http://brouter.de/brouter-web/
|
||||
- [brouter.de/brouter-web](http://brouter.de/brouter-web/) _(provided by [@abrensch](https://github.com/abrensch))_
|
||||
- [brouter.damsy.net](http://brouter.damsy.net) _(provided by [@bagage](https://github.com/bagage))_
|
||||
|
||||
This repository is only about the frontend. For the server/backend, BRouter routing engine, Android app, profiles, brouter.de site, see:
|
||||
**This repository is only about the frontend**.
|
||||
For the server/backend, BRouter routing engine, Android app, profiles, brouter.de site, see:
|
||||
https://github.com/abrensch/brouter
|
||||
|
||||
More information:
|
||||
http://brouter.de
|
||||
|
||||
## Contact
|
||||
|
||||
General BRouter discussions/questions, support:
|
||||
https://groups.google.com/group/osm-android-bikerouting
|
||||
|
||||
- [`#brouter` on IRC OFTC](https://webchat.oftc.net/?channels=#brouter). You can also use [Riot](https://riot.im/app/#/room/#_oftc_#brouter:matrix.org).
|
||||
- [Google Group](https://groups.google.com/group/osm-android-bikerouting)
|
||||
|
||||
## Translating
|
||||
|
||||
Translations are managed using the
|
||||
[Transifex](https://www.transifex.com/openstreetmap/brouter-web/) platform. After
|
||||
signing up, you can go to [BRouter's project
|
||||
page](https://www.transifex.com/openstreetmap/brouter-web/dashboard/), select a language and
|
||||
click **Translate** to start translating.
|
||||
|
||||
## Installation
|
||||
|
||||
|
|
@ -25,115 +36,147 @@ As an alternative to the above online version, the standalone server of BRouter
|
|||
### Install BRouter (server with routing engine)
|
||||
|
||||
1. download and unzip latest [BRouter revision](http://brouter.de/brouter/revisions.html)
|
||||
e.g. for Linux (replace ``~/opt/`` with your preferred install dir and ``1_4_1`` with latest version):
|
||||
e.g. for Linux (replace `~/opt/` with your preferred install directory and `1_4_11` with latest version):
|
||||
|
||||
mkdir ~/opt/brouter
|
||||
cd ~/opt/brouter
|
||||
wget http://brouter.de/brouter_bin/brouter_1_4_1.zip
|
||||
unzip brouter_1_4_1.zip
|
||||
wget http://brouter.de/brouter_bin/brouter_1_4_11.zip
|
||||
unzip brouter_1_4_11.zip
|
||||
chmod +x ./standalone/server.sh
|
||||
|
||||
2. download one or more [data file(s)](http://brouter.de/brouter/segments4/) (rd5) into ``segments4`` dir
|
||||
2. download one or more [data file(s)](http://brouter.de/brouter/segments4/) (rd5) into `segments4` directory
|
||||
|
||||
### Install BRouter-Web (client)
|
||||
|
||||
1. download BRouter-Web as subdirectory ``brouter-web`` of the ``brouter`` directory
|
||||
* using the latest stable release - adjust to current version number - from
|
||||
1. download BRouter-Web as subdirectory `brouter-web` of the `brouter` directory
|
||||
|
||||
- using the latest stable release - adjust to current version number - from
|
||||
https://github.com/nrenner/brouter-web/releases:
|
||||
|
||||
wget https://github.com/nrenner/brouter-web/archive/0.6.3.zip
|
||||
unzip 0.6.3.zip
|
||||
mv brouter-web-0.6.3 brouter-web
|
||||
wget https://github.com/nrenner/brouter-web/releases/download/0.7.0/brouter-web-0.7.0.zip
|
||||
unzip brouter-web-0.7.0.zip -d brouter-web
|
||||
|
||||
* OR the current development state (potentially instable and without runtime distributables):
|
||||
- OR the current development state (potentially instable and without runtime distributables):
|
||||
|
||||
wget https://github.com/nrenner/brouter-web/archive/master.zip
|
||||
unzip master.zip
|
||||
mv brouter-web-master brouter-web
|
||||
|
||||
* build the distributable files required for runtime (only for development state), see section [Build](#build)
|
||||
- build the distributable files required for runtime (only for development state), see section [Build](#build)
|
||||
|
||||
2. copy ``config.template.js`` to ``config.js``
|
||||
3. configure URL to ``profiles2`` directory
|
||||
set ``BR.conf.profilesUrl`` in config.js, e.g. uncomment:
|
||||
2. copy `config.template.js` to `config.js`
|
||||
3. configure URL to `profiles2` directory
|
||||
set `BR.conf.profilesUrl` in config.js, e.g. uncomment:
|
||||
|
||||
BR.conf.profilesUrl = 'http://localhost:8000/profiles2/';
|
||||
|
||||
4. add your API keys (optional)
|
||||
copy ``keys.template.js`` to ``keys.js`` and edit to add your keys
|
||||
copy `keys.template.js` to `keys.js` and edit to add your keys
|
||||
|
||||
### Run
|
||||
|
||||
1. start BRouter server in the ``standalone`` directory with ``./server.sh`` or ``server.cmd`` (Windows)
|
||||
2. serve the ``brouter`` directory for BRouter-Web
|
||||
This is needed for pre-loading the selected profile (unless you allowed local file access in the Browser). Depending on your setup (see [How to run things locally](https://github.com/mrdoob/three.js/wiki/How-to-run-things-locally)), start a web server in the ``brouter`` directory, e.g.:
|
||||
1. start BRouter server in the `standalone` directory with `./server.sh` or `server.cmd` (Windows)
|
||||
2. serve the `brouter` directory for BRouter-Web
|
||||
This is needed for pre-loading the selected profile (unless you allowed local file access in the Browser). Depending on your setup (see [How to run things locally](https://github.com/mrdoob/three.js/wiki/How-to-run-things-locally)), start a web server in the `brouter` directory, e.g.:
|
||||
|
||||
python -m SimpleHTTPServer
|
||||
|
||||
2. open http://localhost:8000/brouter-web/
|
||||
3. open http://localhost:8000/brouter-web/
|
||||
|
||||
## Build
|
||||
|
||||
### Dependencies
|
||||
|
||||
Requires [Node and npm](https://nodejs.org/) (or [io.js](https://iojs.org)), [Bower](https://bower.io/) and [Gulp](http://gulpjs.com/):
|
||||
|
||||
npm install -g bower
|
||||
npm install -g gulp
|
||||
Requires [Node.js](https://nodejs.org/) and [Yarn](https://yarnpkg.com/en/).
|
||||
|
||||
### Install
|
||||
|
||||
npm install
|
||||
bower install
|
||||
yarn
|
||||
|
||||
### Build
|
||||
|
||||
gulp #for release
|
||||
gulp debug #for development
|
||||
yarn build #for release
|
||||
yarn build debug #for development
|
||||
|
||||
### Develop
|
||||
|
||||
gulp watch
|
||||
yarn build watch
|
||||
|
||||
## License
|
||||
|
||||
Copyright (c) 2016 Norbert Renner and [contributors](https://github.com/nrenner/brouter-web/graphs/contributors), licensed under the [MIT License (MIT)](LICENSE)
|
||||
Copyright (c) 2018 Norbert Renner and [contributors](https://github.com/nrenner/brouter-web/graphs/contributors), licensed under the [MIT License (MIT)](LICENSE)
|
||||
|
||||
## Credits and Licenses
|
||||
|
||||
* [BRouter](https://github.com/abrensch/brouter) (not included)
|
||||
by abrensch; [GNU General Public License, version 3.0 (GPLv3)](https://github.com/abrensch/brouter/blob/master/LICENSE)
|
||||
* [Leaflet](http://leafletjs.com/)
|
||||
Copyright (c) 2010-2014, Vladimir Agafonkin; Copyright (c) 2010-2011, CloudMade; [2-clause BSD License](https://github.com/Leaflet/Leaflet/blob/master/LICENSE)
|
||||
* [leaflet-routing](https://github.com/Turistforeningen/leaflet-routing)
|
||||
Copyright (c) 2013, Turistforeningen, Hans Kristian Flaatten. All rights reserved. [2-clause BSD License](https://github.com/Turistforeningen/leaflet-routing/blob/gh-pages/LICENSE)
|
||||
* [Leaflet.Elevation](https://github.com/MrMufflon/Leaflet.Elevation)
|
||||
Copyright (c) 2013 Felix Bache; [MIT License](https://github.com/MrMufflon/Leaflet.Elevation/blob/master/LICENSE)
|
||||
* [D3.js](https://github.com/mbostock/d3)
|
||||
Copyright (c) 2013, Michael Bostock. All rights reserved.; [3-clause BSD License](https://github.com/mbostock/d3/blob/master/LICENSE)
|
||||
* [Leaflet.draw](https://github.com/Leaflet/Leaflet.draw)
|
||||
Copyright 2012 Jacob Toye; [MIT License](https://github.com/Leaflet/Leaflet.draw/blob/master/MIT-LICENCE.txt)
|
||||
* [Leaflet Control Geocoder](https://github.com/perliedman/leaflet-control-geocoder)
|
||||
Copyright (c) 2012 [sa3m](https://github.com/sa3m), Copyright (c) 2013 Per Liedman; [2-clause BSD License](https://github.com/perliedman/leaflet-control-geocoder/blob/master/LICENSE)
|
||||
* [leaflet-plugins](https://github.com/shramov/leaflet-plugins)
|
||||
Copyright (c) 2011-2012, Pavel Shramov; [2-clause BSD License](https://github.com/shramov/leaflet-plugins/blob/master/LICENSE)
|
||||
* [Async.js](https://github.com/caolan/async)
|
||||
Copyright (c) 2010-2014 Caolan McMahon; [MIT License](https://github.com/caolan/async/blob/master/LICENSE)
|
||||
* [Bootstrap](https://getbootstrap.com/)
|
||||
Copyright (c) 2011-2014 Twitter, Inc; [MIT License](https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* [jQuery](https://github.com/jquery/jquery)
|
||||
Copyright 2005, 2014 jQuery Foundation and other contributors; [MIT License](https://github.com/jquery/jquery/blob/master/LICENSE.txt)
|
||||
* [DataTables](https://github.com/DataTables/DataTables)
|
||||
Copyright (C) 2008-2014, SpryMedia Ltd.; [MIT License](https://www.datatables.net/license/MIT-LICENCE)
|
||||
* [Leaflet.EasyButton](https://github.com/CliffCloud/Leaflet.EasyButton)
|
||||
Copyright (C) 2014 Daniel Montague; [MIT License](https://github.com/CliffCloud/Leaflet.EasyButton/blob/master/LICENSE)
|
||||
* [Bootbox](https://github.com/makeusabrew/bootbox)
|
||||
Copyright (C) 2011-2014 by Nick Payne; [MIT License](https://github.com/makeusabrew/bootbox/blob/master/LICENSE.md)
|
||||
* [bootstrap-slider](https://github.com/seiyria/bootstrap-slider)
|
||||
Copyright (c) 2015 Kyle Kemp, Rohit Kalkur, and contributors; [MIT License](https://github.com/seiyria/bootstrap-slider/blob/master/LICENSE.md)
|
||||
* [Leaflet.RestoreView](https://github.com/makinacorpus/Leaflet.RestoreView)
|
||||
Copyright (c) 2012 Makina Corpus, [MIT License](https://github.com/makinacorpus/Leaflet.RestoreView/blob/master/LICENSE)
|
||||
* [Leaflet.Locate](https://github.com/domoritz/leaflet-locatecontrol)
|
||||
Copyright (c) 2014 Dominik Moritz, [MIT License](https://github.com/domoritz/leaflet-locatecontrol/blob/gh-pages/LICENSE)
|
||||
* [Font Awesome](http://fontawesome.io/license/)
|
||||
by Dave Gandy; [SIL OFL 1.1](https://scripts.sil.org/OFL) (Font), MIT License (Code), CC BY 3.0 (Documentation)
|
||||
- [BRouter](https://github.com/abrensch/brouter) (not included)
|
||||
by abrensch; [GNU General Public License, version 3.0 (GPLv3)](https://github.com/abrensch/brouter/blob/master/LICENSE)
|
||||
- [Leaflet](http://leafletjs.com/)
|
||||
Copyright (c) 2010-2014, Vladimir Agafonkin; Copyright (c) 2010-2011, CloudMade; [2-clause BSD License](https://github.com/Leaflet/Leaflet/blob/master/LICENSE)
|
||||
- [leaflet-routing](https://github.com/Turistforeningen/leaflet-routing)
|
||||
Copyright (c) 2013, Turistforeningen, Hans Kristian Flaatten. All rights reserved. [2-clause BSD License](https://github.com/Turistforeningen/leaflet-routing/blob/gh-pages/LICENSE)
|
||||
- [Leaflet.Elevation](https://github.com/MrMufflon/Leaflet.Elevation)
|
||||
Copyright (c) 2013 Felix Bache; [MIT License](https://github.com/MrMufflon/Leaflet.Elevation/blob/master/LICENSE)
|
||||
- [D3.js](https://github.com/mbostock/d3)
|
||||
Copyright (c) 2013, Michael Bostock. All rights reserved.; [3-clause BSD License](https://github.com/mbostock/d3/blob/master/LICENSE)
|
||||
- [Leaflet.Editable](https://github.com/Leaflet/Leaflet.Editable)
|
||||
Yohan Boniface; WTFPL licence
|
||||
- [Leaflet Control Geocoder](https://github.com/perliedman/leaflet-control-geocoder)
|
||||
Copyright (c) 2012 [sa3m](https://github.com/sa3m), Copyright (c) 2013 Per Liedman; [2-clause BSD License](https://github.com/perliedman/leaflet-control-geocoder/blob/master/LICENSE)
|
||||
- [leaflet-plugins](https://github.com/shramov/leaflet-plugins)
|
||||
Copyright (c) 2011-2012, Pavel Shramov; [2-clause BSD License](https://github.com/shramov/leaflet-plugins/blob/master/LICENSE)
|
||||
- [Async.js](https://github.com/caolan/async)
|
||||
Copyright (c) 2010-2014 Caolan McMahon; [MIT License](https://github.com/caolan/async/blob/master/LICENSE)
|
||||
- [Bootstrap](https://getbootstrap.com/)
|
||||
Copyright (c) 2011-2014 Twitter, Inc; [MIT License](https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
- [jQuery](https://github.com/jquery/jquery)
|
||||
Copyright 2005, 2014 jQuery Foundation and other contributors; [MIT License](https://github.com/jquery/jquery/blob/master/LICENSE.txt)
|
||||
- [DataTables](https://github.com/DataTables/DataTables)
|
||||
Copyright (C) 2008-2014, SpryMedia Ltd.; [MIT License](https://www.datatables.net/license/MIT-LICENCE)
|
||||
- [Leaflet.EasyButton](https://github.com/CliffCloud/Leaflet.EasyButton)
|
||||
Copyright (C) 2014 Daniel Montague; [MIT License](https://github.com/CliffCloud/Leaflet.EasyButton/blob/master/LICENSE)
|
||||
- [Bootbox](https://github.com/makeusabrew/bootbox)
|
||||
Copyright (C) 2011-2014 by Nick Payne; [MIT License](https://github.com/makeusabrew/bootbox/blob/master/LICENSE.md)
|
||||
- [bootstrap-slider](https://github.com/seiyria/bootstrap-slider)
|
||||
Copyright (c) 2015 Kyle Kemp, Rohit Kalkur, and contributors; [MIT License](https://github.com/seiyria/bootstrap-slider/blob/master/LICENSE.md)
|
||||
- [Leaflet.RestoreView](https://github.com/makinacorpus/Leaflet.RestoreView)
|
||||
Copyright (c) 2012 Makina Corpus, [MIT License](https://github.com/makinacorpus/Leaflet.RestoreView/blob/master/LICENSE)
|
||||
- [Leaflet.Locate](https://github.com/domoritz/leaflet-locatecontrol)
|
||||
Copyright (c) 2014 Dominik Moritz, [MIT License](https://github.com/domoritz/leaflet-locatecontrol/blob/gh-pages/LICENSE)
|
||||
- [Font Awesome](http://fontawesome.io/license/)
|
||||
by Dave Gandy; [SIL OFL 1.1](https://scripts.sil.org/OFL) (Font), MIT License (Code), CC BY 3.0 (Documentation)
|
||||
- [url-search-params](https://github.com/WebReflection/url-search-params)
|
||||
Copyright (C) 2015-2017 Andrea Giammarchi - @WebReflection; [MIT License](https://github.com/WebReflection/url-search-params/blob/master/LICENSE.txt)
|
||||
- [bootstrap-select](https://github.com/snapappointments/bootstrap-select)
|
||||
Copyright (c) 2012-2018 SnapAppointments, LLC; [MIT License](https://github.com/snapappointments/bootstrap-select/blob/v1.13.0-dev/LICENSE)
|
||||
- [leaflet-sidebar-v2](https://github.com/nickpeihl/leaflet-sidebar-v2)
|
||||
Copyright (c) 2013 Tobias Bieniek; [MIT License](https://github.com/nickpeihl/leaflet-sidebar-v2/blob/master/LICENSE)
|
||||
- [CodeMirror](https://github.com/codemirror/CodeMirror)
|
||||
Copyright (C) 2017 by Marijn Haverbeke <marijnh@gmail.com> and others; [MIT License](https://github.com/codemirror/CodeMirror/blob/master/LICENSE)
|
||||
- [Map BBCode](https://github.com/MapBBCode/mapbbcode)
|
||||
Ilya Zverev; [Do What The F\*ck You Want To Public License](https://github.com/MapBBCode/mapbbcode/blob/master/LICENSE)
|
||||
- [Leafet.StravaSegments](https://gitlab.com/bagage/leaflet.stravasegments)
|
||||
Copyright (c) 2018 Gautier Pelloux-Prayer; [MIT License](https://gitlab.com/bagage/leaflet.stravasegments/blob/master/LICENSE)
|
||||
- [polyline](https://github.com/mapbox/polyline)
|
||||
Copyright (c), Development Seed; [BSD 3-Clause License](https://github.com/mapbox/polyline/blob/master/LICENSE)
|
||||
- [leaflet-fullHash](https://github.com/KoGor/leaflet-fullHash)
|
||||
Copyright (c) 2014 KoGor; [MIT License](https://github.com/KoGor/leaflet-fullHash/blob/master/LICENSE)
|
||||
- [Turf.js](https://github.com/Turfjs/turf)
|
||||
Copyright (c) 2019 Morgan Herlocker; [MIT License](https://github.com/Turfjs/turf/blob/master/LICENSE)
|
||||
- [i18next](https://github.com/i18next/i18next), [i18next-browser-languageDetector](https://github.com/i18next/i18next-browser-languageDetector), [i18next-xhr-backend](https://github.com/i18next/i18next-xhr-backend), [jquery-i18next](https://github.com/i18next/jquery-i18next/blob/master/LICENSE)
|
||||
Copyright (c) 2017 i18next; [MIT License](https://github.com/i18next/i18next/blob/master/LICENSE)
|
||||
- [Leaflet TriangleMarker](https://github.com/themeler/leaflet-triangle-marker)
|
||||
Copyright (c) 2018 Przemysław Melnarowicz; [MIT License](https://github.com/themeler/leaflet-triangle-marker/blob/master/LICENSE)
|
||||
- [jsTree ](https://github.com/vakata/jstree)
|
||||
Copyright (c) 2014 Ivan Bozhanov; [MIT License](https://github.com/vakata/jstree/blob/master/LICENSE-MIT)
|
||||
- [Leaflet.snogylop](https://github.com/ebrelsford/leaflet.snogylop)
|
||||
Copyright (c) 2014 Eric Brelsford; [MIT License](https://github.com/ebrelsford/Leaflet.snogylop/blob/master/LICENSE)
|
||||
- [JOSM maps](https://josm.openstreetmap.de/wiki/Maps)
|
||||
imagery database is licensed under [CC-BY-SA](https://creativecommons.org/licenses/by-sa/3.0/)
|
||||
- [LayersCollection](https://github.com/Edward17/LayersCollection/tree/gh-pages)
|
||||
Copyright (c) 2016 Eduard <edward17>; [MIT License](https://github.com/Edward17/LayersCollection/blob/gh-pages/LICENSE.md)
|
||||
- [Leaflet-providers](https://github.com/leaflet-extras/leaflet-providers)
|
||||
Copyright (c) 2013 Leaflet Providers contributors All rights reserved.; [2-clause BSD License](https://github.com/leaflet-extras/leaflet-providers/blob/master/license.md)
|
||||
- [Fetch polyfill](https://github.com/Github/fetch)
|
||||
Copyright (c) 2014-2016 GitHub, Inc.; [MIT License](https://github.com/github/fetch/blob/master/LICENSE)
|
||||
- [Promise Polyfill](https://github.com/taylorhakes/promise-polyfill)
|
||||
Copyright (c) 2014 Taylor Hakes, Copyright (c) 2014 Forbes Lindesay; [MIT License](https://github.com/taylorhakes/promise-polyfill/blob/master/LICENSE)
|
||||
|
|
|
|||
117
bower.json
117
bower.json
|
|
@ -1,117 +0,0 @@
|
|||
{
|
||||
"name": "brouter-web",
|
||||
"version": "0.6.3",
|
||||
"main": [
|
||||
"dist/brouter-web.css",
|
||||
"dist/brouter-web.js"
|
||||
],
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"bower_components"
|
||||
],
|
||||
"dependencies": {
|
||||
"leaflet": "^1.0.3",
|
||||
"leaflet-plugins": "~3.0.0",
|
||||
"leaflet-routing": "nrenner/leaflet-routing#leaflet-1.0",
|
||||
"async": "~0.9.2",
|
||||
"d3": "~3.5.5",
|
||||
"leaflet.draw": "~0.4.9",
|
||||
"bootstrap": "4.0.0-alpha.5",
|
||||
"DataTables": "~1.10.13",
|
||||
"leaflet.elevation": "MrMufflon/Leaflet.Elevation#master",
|
||||
"leaflet-control-geocoder": "1.5.3",
|
||||
"Leaflet.EasyButton": "*",
|
||||
"bootbox": "~4.4.0",
|
||||
"seiyria-bootstrap-slider": "^9.8.1",
|
||||
"url-search-params": "~0.5.0",
|
||||
"Leaflet.RestoreView": "makinacorpus/Leaflet.RestoreView#master",
|
||||
"leaflet.locatecontrol": "^0.60.0",
|
||||
"font-awesome": "^4.7.0",
|
||||
"bootstrap-select": "hugdx/bootstrap-select#patch-1",
|
||||
"leaflet-sidebar": "^0.1.9",
|
||||
"autosize": "^3.0.20"
|
||||
},
|
||||
"overrides": {
|
||||
"leaflet": {
|
||||
"main": [
|
||||
"dist/leaflet-src.js",
|
||||
"dist/leaflet.css",
|
||||
"dist/images/*.png"
|
||||
]
|
||||
},
|
||||
"leaflet-plugins": {
|
||||
"main": [
|
||||
"layer/tile/Bing.js"
|
||||
]
|
||||
},
|
||||
"leaflet-routing": {
|
||||
"main": [
|
||||
"src/utils/LineUtil.Snapping.js",
|
||||
"src/utils/Marker.Snapping.js",
|
||||
"src/L.Routing.js",
|
||||
"src/L.Routing.Draw.js",
|
||||
"src/L.Routing.Edit.js"
|
||||
]
|
||||
},
|
||||
"leaflet.draw": {
|
||||
"main": [
|
||||
"dist/leaflet.draw-src.js",
|
||||
"dist/leaflet.draw.css",
|
||||
"dist/images/*.png",
|
||||
"dist/images/*.svg"
|
||||
],
|
||||
"dependencies": null
|
||||
},
|
||||
"bootstrap-select": {
|
||||
"main": [
|
||||
"js/bootstrap-select.js",
|
||||
"dist/css/bootstrap-select.css"
|
||||
]
|
||||
},
|
||||
"bootstrap": {
|
||||
"main": [
|
||||
"dist/js/bootstrap.js",
|
||||
"dist/css/bootstrap.css"
|
||||
]
|
||||
},
|
||||
"leaflet.elevation": {
|
||||
"main": [
|
||||
"dist/leaflet.elevation-0.0.4.src.js",
|
||||
"dist/leaflet.elevation-0.0.4.css",
|
||||
"dist/images/*.png"
|
||||
],
|
||||
"dependencies": null
|
||||
},
|
||||
"leaflet-control-geocoder": {
|
||||
"main": [
|
||||
"dist/Control.Geocoder.js",
|
||||
"dist/Control.Geocoder.css",
|
||||
"images/*.+(png|gif)"
|
||||
]
|
||||
},
|
||||
"url-search-params": {
|
||||
"main": "build/url-search-params.js"
|
||||
},
|
||||
"Leaflet.RestoreView": {
|
||||
"main": "leaflet.restoreview.js"
|
||||
},
|
||||
"font-awesome": {
|
||||
"main": [
|
||||
"css/font-awesome.css",
|
||||
"fonts/*"
|
||||
]
|
||||
},
|
||||
"autosize": {
|
||||
"main": "dist/autosize.js"
|
||||
},
|
||||
"seiyria-bootstrap-slider": {
|
||||
"dependencies": {
|
||||
"jquery": "*",
|
||||
"bootstrap": "*"
|
||||
}
|
||||
}
|
||||
},
|
||||
"resolutions": {
|
||||
"leaflet": "^1.0.3"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
(function() {
|
||||
|
||||
var hostname = window.location.hostname;
|
||||
var params = new URLSearchParams(window.location.search.slice(1));
|
||||
|
||||
|
|
@ -13,13 +12,13 @@
|
|||
//BR.conf.transit = params.has('transit') && (params.get('transit') === 'true');
|
||||
|
||||
if (hostname === 'brouter.de' ) {
|
||||
|
||||
// online service (brouter.de) configuration
|
||||
|
||||
BR.conf.profiles = [
|
||||
'trekking',
|
||||
'fastbike',
|
||||
'car-test',
|
||||
'car-eco',
|
||||
'car-fast',
|
||||
'safety',
|
||||
'shortest',
|
||||
'trekking-ignore-cr',
|
||||
|
|
@ -38,17 +37,20 @@
|
|||
|
||||
BR.conf.host = 'http://brouter.de:443';
|
||||
BR.conf.profilesUrl = 'http://brouter.de/brouter/profiles2/';
|
||||
|
||||
} else {
|
||||
|
||||
// desktop configuration
|
||||
|
||||
BR.conf.profiles = [
|
||||
'trekking',
|
||||
'fastbike',
|
||||
'car-eco',
|
||||
'car-fast',
|
||||
'shortest',
|
||||
'moped',
|
||||
'car-test'
|
||||
'vm-forum-liegerad-schnell',
|
||||
'vm-forum-velomobil-schnell',
|
||||
'fastbike-lowtraffic',
|
||||
'fastbike-asia-pacific'
|
||||
];
|
||||
|
||||
BR.conf.host = 'http://0.0.0.0:17777';
|
||||
|
|
@ -73,6 +75,9 @@
|
|||
//'Mapsforge Tile Server': 'http://localhost:6090/{z}/{x}/{y}.png'
|
||||
};
|
||||
|
||||
// Base layer to show on start, as position number in the layer switcher, starting from 0, default is first
|
||||
BR.conf.defaultBaseLayerIndex = 0;
|
||||
|
||||
// Initial route line transparency (0-1, overridden by stored slider setting)
|
||||
BR.conf.defaultOpacity = 0.67;
|
||||
|
||||
|
|
@ -105,7 +110,6 @@
|
|||
|
||||
// transit (intermodal routing) demo config
|
||||
if (BR.conf.transit) {
|
||||
|
||||
BR.conf.profiles = [
|
||||
'../im/bike',
|
||||
'../im/foot',
|
||||
|
|
@ -117,6 +121,8 @@
|
|||
'moped',
|
||||
'car-test'
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
// regex needs to be in sync with server, see ServerHandler.getTrackName()
|
||||
BR.conf.tracknameAllowedChars = 'a-zA-Z0-9 \\._\\-';
|
||||
})();
|
||||
|
|
|
|||
417
css/style.css
417
css/style.css
|
|
@ -1,48 +1,83 @@
|
|||
html, body, #map {
|
||||
html,
|
||||
body,
|
||||
#map {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* This is important so that bootstrap-select list goes over leaflet buttons
|
||||
Since the list is in navbar and leaflet buttons within map, we create a
|
||||
stacking context on their common ancestor */
|
||||
body, #content {
|
||||
body,
|
||||
#content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.flexcolumn {
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
#content {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.flexcolumn,
|
||||
.leaflet-sidebar-pane.active,
|
||||
.dataTables_wrapper,
|
||||
.dataTables_scroll,
|
||||
.dataTables_scrollBody {
|
||||
display: flex;
|
||||
|
||||
flex-flow: column;
|
||||
}
|
||||
|
||||
.flexrow {
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#content {
|
||||
-webkit-box-flex: 1;
|
||||
-moz-box-flex: 1;
|
||||
-webkit-flex: 1;
|
||||
-ms-flex: 1;
|
||||
.flexgrow {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* 'auto' (1 1 auto) instead of '1' (1 1 0) needed for DataTables tab in Firefox */
|
||||
.dataTables_wrapper,
|
||||
.dataTables_scroll,
|
||||
.dataTables_scrollBody,
|
||||
table.dataTable {
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
/* wrap toolbar controls */
|
||||
.leaflet-top.leaflet-left {
|
||||
bottom: 0;
|
||||
margin-bottom: 10px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
/* bottom underneath top controls when overlapping */
|
||||
.leaflet-bottom {
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
/* align with leaflet-control */
|
||||
padding: 0.5rem 10px;
|
||||
}
|
||||
.nav-link .fa {
|
||||
margin-right: 0.2em;
|
||||
}
|
||||
.navbar-dark .navbar-toggler {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
/* disabled style for "Custom" option, but not for selected items */
|
||||
.bootstrap-select.btn-group .dropdown-menu li.disabled:not(.selected) a {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
footer {
|
||||
-webkit-box-flex: none;
|
||||
-moz-box-flex: none;
|
||||
-webkit-flex: none;
|
||||
-ms-flex: none;
|
||||
flex: none;
|
||||
|
||||
background-color: #f7f7f9;
|
||||
|
|
@ -52,39 +87,76 @@ footer {
|
|||
flex-grow: 1;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
#stats li {
|
||||
margin: 0 1rem;
|
||||
display: inline-block;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
#stats li {
|
||||
margin: 0 0.5rem;
|
||||
}
|
||||
#stats {
|
||||
padding-top: 0.4em;
|
||||
}
|
||||
p.stats-label {
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
}
|
||||
|
||||
#elevation-chart {
|
||||
height: 175px;
|
||||
font-size: 80%;
|
||||
.stats-label {
|
||||
word-break: break-all;
|
||||
font-weight: bold;
|
||||
}
|
||||
.stats-label abbr[title],
|
||||
#distance {
|
||||
text-decoration: none;
|
||||
border-bottom: 1px dotted #818a91;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 0
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.bootstrap-select.btn-group:not(.input-group-btn),
|
||||
.bootstrap-select.btn-group[class*="col-"] {
|
||||
margin-left: 10px;
|
||||
input#trackname:invalid,
|
||||
input#trackname:focus:invalid {
|
||||
border-color: orange;
|
||||
}
|
||||
:not(output):-moz-ui-invalid:not(:focus),
|
||||
:not(output):-moz-ui-invalid:-moz-focusring:not(:focus) {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.validation-warning {
|
||||
color: orange;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.axis path,
|
||||
.axis line {
|
||||
stroke: #818a91;
|
||||
fill: none;
|
||||
/*
|
||||
* elevation diagram
|
||||
*/
|
||||
|
||||
.steelblue-theme.leaflet-control.elevation .background {
|
||||
display: block;
|
||||
font-size: 80%;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
/* diagram colors lighter, less dominant */
|
||||
.steelblue-theme.leaflet-control.elevation .background {
|
||||
background-color: rgba(105, 155, 196, 0.2);
|
||||
}
|
||||
.steelblue-theme.leaflet-control.elevation .axis path,
|
||||
.steelblue-theme.leaflet-control.elevation .axis line {
|
||||
stroke: #8398aa;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
|
||||
.axis text {
|
||||
fill: #818a91;
|
||||
.steelblue-theme.leaflet-control.elevation .axis text {
|
||||
fill: #8398aa;
|
||||
}
|
||||
|
||||
.area {
|
||||
fill: rgba(129, 138, 145, 0.45);
|
||||
.steelblue-theme.leaflet-control.elevation .area {
|
||||
fill: #699bc4;
|
||||
}
|
||||
|
||||
#elevation-btn {
|
||||
|
|
@ -96,24 +168,48 @@ footer {
|
|||
cursor: crosshair;
|
||||
}
|
||||
|
||||
#map {
|
||||
/* center error message horizontally */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
/* map click/drag selects text in controls in Firefox because of display flex */
|
||||
-moz-user-select: none;
|
||||
}
|
||||
.leaflet-control-container,
|
||||
#message .alert {
|
||||
-moz-user-select: text;
|
||||
}
|
||||
#message {
|
||||
position: absolute;
|
||||
left: 446px; /* 400 + 10 + 26 + 10 */
|
||||
top: 0px;
|
||||
margin-top: 10px;
|
||||
margin: 10px 46px; /* 10 + 26 + 10 */
|
||||
z-index: 3000;
|
||||
font-size: 1rem;
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
#profile_buttons {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
/* track messages (data tab) */
|
||||
#tab_data, #profile_upload {
|
||||
#tab_data,
|
||||
.CodeMirror {
|
||||
font-size: x-small;
|
||||
}
|
||||
|
||||
/* transit demo */
|
||||
#itinerary pre {
|
||||
font-size: small;
|
||||
/* turn off bootstrap 'break-word' */
|
||||
word-wrap: normal;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* dashed line animation, derived from Chris Coyier and others
|
||||
https://css-tricks.com/svg-line-animation-works/
|
||||
*/
|
||||
.loading-trailer {
|
||||
-webkit-animation: dash 0.4s linear infinite;
|
||||
animation: dash 0.4s linear infinite;
|
||||
}
|
||||
@-webkit-keyframes dash {
|
||||
|
|
@ -140,12 +236,19 @@ https://css-tricks.com/svg-line-animation-works/
|
|||
.control-slider {
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.slider#overlay {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.slider.slider-vertical {
|
||||
height: 80px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
.slider.slider-horizontal {
|
||||
width: 180px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
/* invert track and selection styles to get partial gradient for "selection" */
|
||||
|
|
@ -153,16 +256,22 @@ https://css-tricks.com/svg-line-animation-works/
|
|||
width: 8px;
|
||||
margin-left: 1px;
|
||||
background-image: linear-gradient(to right, #f0f0f0 0%, #e9e9e9 100%);
|
||||
box-shadow: inset -1px -0px 1px rgba(55, 55, 55, 0.3), inset 1px 0px 1px rgba(230, 230, 230, 1);
|
||||
box-shadow: inset -1px -0px 1px rgba(55, 55, 55, 0.3),
|
||||
inset 1px 0px 1px rgba(230, 230, 230, 1);
|
||||
}
|
||||
.slider.slider-horizontal .slider-track {
|
||||
background-image: linear-gradient(to bottom, #f0f0f0 0%, #e9e9e9 100%);
|
||||
box-shadow: inset -0px -1px 1px rgba(55, 55, 55, 0.3),
|
||||
inset 0px 1px 1px rgba(230, 230, 230, 1);
|
||||
}
|
||||
|
||||
.control-slider:hover .slider-track,
|
||||
.control-slider:active .slider-track {
|
||||
.control-slider:hover #route .slider-track,
|
||||
.control-slider:active #route .slider-track {
|
||||
background-image: linear-gradient(to bottom, magenta 0%, white 100%);
|
||||
}
|
||||
|
||||
.slider-selection {
|
||||
background-color: #C6C6C6;
|
||||
background-color: #c6c6c6;
|
||||
background-image: none;
|
||||
box-shadow: inset 1px 1px 3px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
|
@ -170,27 +279,56 @@ https://css-tricks.com/svg-line-animation-works/
|
|||
.slider.slider-vertical .slider-tick,
|
||||
.slider.slider-vertical .slider-handle {
|
||||
cursor: ns-resize;
|
||||
}
|
||||
|
||||
.slider .slider-tick,
|
||||
.slider .slider-handle {
|
||||
cursor: ew-resize;
|
||||
box-sizing: border-box;
|
||||
background: none;
|
||||
outline: none;
|
||||
|
||||
/* bootstrap .btn-default */
|
||||
background-image: linear-gradient(to bottom,#fff 0,#e0e0e0 100%);
|
||||
/* bootstrap .btn-secondary */
|
||||
background-image: linear-gradient(to bottom, #fff 0, #e0e0e0 100%);
|
||||
background-repeat: repeat-x;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15),
|
||||
0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
border: 1px solid #adadad;
|
||||
}
|
||||
|
||||
/* activated Font Awesome icon and Bootstrap button
|
||||
(for EasyButton add ' active' to icon class property) */
|
||||
.fa.active, .btn.active, .btn.active:hover, .btn.active:focus {
|
||||
/* activated Font Awesome icon (for EasyButton add ' active' to icon class property) */
|
||||
.fa.active {
|
||||
/* use same color as leaflet-locatecontrol */
|
||||
color: #2074B6;
|
||||
color: #2074b6;
|
||||
}
|
||||
/* Bootstrap button */
|
||||
.btn-secondary:not(:disabled):not(.disabled).active,
|
||||
.btn-secondary.active,
|
||||
.btn-secondary:hover,
|
||||
.btn-outline-secondary:not(:disabled):not(.disabled).active,
|
||||
.btn-outline-secondary:hover {
|
||||
/* use same color as leaflet-locatecontrol */
|
||||
color: #2074b6;
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
|
||||
.stats-label {
|
||||
word-break: break-all;
|
||||
font-weight: bold;
|
||||
button.btn {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.leaflet-bar button {
|
||||
/* override button for horizontal fa center in Firefox */
|
||||
padding: 0;
|
||||
}
|
||||
.leaflet-bar .fa {
|
||||
font-size: 14px;
|
||||
|
||||
/* override fa with Leaflet button height for vertical center */
|
||||
line-height: 26px;
|
||||
}
|
||||
.leaflet-touch .leaflet-bar .fa {
|
||||
font-size: 16px;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
/* smaller tab height */
|
||||
|
|
@ -198,10 +336,29 @@ https://css-tricks.com/svg-line-animation-works/
|
|||
padding: 2px 15px;
|
||||
}
|
||||
|
||||
#profile_message .alert {
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.alert {
|
||||
margin-bottom: 0px;
|
||||
padding-left: 35px;
|
||||
}
|
||||
.alert span.fa {
|
||||
position: relative;
|
||||
left: -23px;
|
||||
margin-right: -1em;
|
||||
}
|
||||
|
||||
/*
|
||||
* DataTables
|
||||
*/
|
||||
|
||||
table.dataTable {
|
||||
/* avoid getting centered and header misaligned with flex row (sidebar) */
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
table.dataTable.mini thead th,
|
||||
table.dataTable.mini thead td {
|
||||
padding: 3px 13px 3px 2px;
|
||||
|
|
@ -224,5 +381,147 @@ table.dataTable.hover tbody tr.even:hover,
|
|||
table.dataTable.display tbody tr:hover,
|
||||
table.dataTable.display tbody tr.odd:hover,
|
||||
table.dataTable.display tbody tr.even:hover {
|
||||
background-color: rgba(255,255,0,0.2);
|
||||
background-color: rgba(255, 255, 0, 0.2);
|
||||
}
|
||||
|
||||
/*
|
||||
* No-go areas
|
||||
*/
|
||||
|
||||
.nogo-delete-marker {
|
||||
text-align: center;
|
||||
line-height: 15px;
|
||||
font-size: 11px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.leaflet-touch .nogo-delete-marker {
|
||||
border-radius: 12px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
/* tooltip */
|
||||
|
||||
.editing-tooltip,
|
||||
.editing-tooltip-create {
|
||||
color: #fff;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
/* for direction arrows that inherit */
|
||||
border-color: rgba(0, 0, 0, 0.7);
|
||||
/* no border but still set a color for direction arrows */
|
||||
border-width: 0px;
|
||||
}
|
||||
.editing-tooltip-create {
|
||||
/* no (invisible) direction arrow for cursor tooltip */
|
||||
border-color: transparent;
|
||||
}
|
||||
.leaflet-tooltip-bottom:before {
|
||||
border-bottom-color: inherit;
|
||||
}
|
||||
.leaflet-tooltip-right:before {
|
||||
border-right-color: inherit;
|
||||
}
|
||||
|
||||
/*
|
||||
* leaflet-sidebar-v2
|
||||
*/
|
||||
|
||||
.leaflet-sidebar-pane#tab_profile,
|
||||
.leaflet-sidebar-pane#tab_data,
|
||||
.leaflet-sidebar-pane#tab_itinerary {
|
||||
/* Full height for content with inner scrolling,
|
||||
overrides scroll fix for long content in Firefox */
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.leaflet-sidebar-content {
|
||||
/* for optional-layers-tree */
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
/* layers control as sidebar tab */
|
||||
#tab_layers_control {
|
||||
font-size: 0.9rem;
|
||||
line-height: normal;
|
||||
}
|
||||
#layers-control-wrapper label {
|
||||
/* override Bootstrap/Reboot label */
|
||||
display: block;
|
||||
margin-bottom: 0px;
|
||||
/* normalize label height
|
||||
| Firefox | Chrome |
|
||||
Leaflet only | 21 | 20 |
|
||||
Bootstrap | 23 | 22 |*/
|
||||
height: 23px;
|
||||
}
|
||||
|
||||
#layers-button-group {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
#tree-button-group {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
#optional-layers-tree {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.tree-code {
|
||||
font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console,
|
||||
monospace;
|
||||
margin-right: 7px;
|
||||
color: #666; /* like root nodes, jstree-disabled */
|
||||
}
|
||||
|
||||
/* hide currently unused bottom tabs container because of touch border artefacts */
|
||||
.leaflet-sidebar-tabs > ul:last-child {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* layers svg icon not properly centered */
|
||||
.leaflet-sidebar-tabs > ul > li > a[href='#tab_layers_control'] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/*
|
||||
* CodeMirror
|
||||
*/
|
||||
|
||||
.CodeMirror {
|
||||
/* auto instead of 1 to avoid overflow to content height in Firefox */
|
||||
flex: auto;
|
||||
/* override default 300px, behaves like min-height with flex auto */
|
||||
height: 0;
|
||||
|
||||
border: 1px solid #ddd;
|
||||
|
||||
font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console,
|
||||
monospace;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
#loadNogos fieldset {
|
||||
display: block;
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
padding-top: 0.35em;
|
||||
padding-bottom: 0.625em;
|
||||
padding-left: 0.75em;
|
||||
padding-right: 0.75em;
|
||||
border: 2px groove;
|
||||
}
|
||||
|
||||
#loadNogos legend {
|
||||
display: block;
|
||||
padding-left: 2px;
|
||||
padding-right: 2px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.nav-link.disabled {
|
||||
/* by default, even if disabled, modals are opened by disabled nav-link
|
||||
so we ignore pointer events in this situation to avoid that*/
|
||||
pointer-events: none;
|
||||
}
|
||||
|
|
|
|||
402
gulpfile.js
402
gulpfile.js
|
|
@ -1,13 +1,12 @@
|
|||
var gulp = require('gulp');
|
||||
var concat = require('gulp-concat');
|
||||
var concatCss = require('gulp-concat-css');
|
||||
var minifyCss = require('gulp-minify-css');
|
||||
var postcss = require('gulp-postcss');
|
||||
var autoprefixer = require('autoprefixer');
|
||||
var uglify = require('gulp-uglify');
|
||||
var sourcemaps = require('gulp-sourcemaps');
|
||||
var gulpDebug = require('gulp-debug');
|
||||
var mainBowerFiles = require('main-bower-files');
|
||||
var mainNpmFiles = require('npmfiles');
|
||||
var del = require('del');
|
||||
var tap = require('gulp-tap');
|
||||
var path = require('path');
|
||||
var cached = require('gulp-cached');
|
||||
var remember = require('gulp-remember');
|
||||
|
|
@ -20,46 +19,87 @@ var semver = require('semver');
|
|||
var git = require('gulp-git');
|
||||
var replace = require('gulp-replace');
|
||||
var release = require('gulp-github-release');
|
||||
var cleanCSS = require('gulp-clean-css');
|
||||
var modifyCssUrls = require('gulp-modify-css-urls');
|
||||
var sort = require('gulp-sort');
|
||||
var scanner = require('i18next-scanner');
|
||||
var jsonConcat = require('gulp-json-concat');
|
||||
var rename = require('gulp-rename');
|
||||
|
||||
var debug = false;
|
||||
|
||||
var paths = {
|
||||
// see overrides in bower.json
|
||||
scriptsConfig: mainBowerFiles('**/url-search-params/**/*.js'),
|
||||
scripts: mainBowerFiles([
|
||||
'**/*.js',
|
||||
'!**/*.min.js',
|
||||
'!**/url-search-params/**/*.js'
|
||||
]).concat([
|
||||
// see overrides in package.json
|
||||
scriptsConfig: mainNpmFiles().filter(f =>
|
||||
RegExp('url-search-params/.*\\.js', 'i').test(f)
|
||||
),
|
||||
scripts: [
|
||||
'node_modules/jquery/dist/jquery.js',
|
||||
'node_modules/tether/dist/js/tether.js',
|
||||
'node_modules/async/lib/async.js',
|
||||
'node_modules/leaflet/dist/leaflet-src.js'
|
||||
]
|
||||
.concat(
|
||||
mainNpmFiles().filter(
|
||||
f =>
|
||||
RegExp('.*\\.js', 'i').test(f) &&
|
||||
!RegExp('.*\\.min\\.js', 'i').test(f) &&
|
||||
!RegExp('url-search-params/.*\\.js', 'i').test(f)
|
||||
)
|
||||
)
|
||||
.concat([
|
||||
'js/Browser.js',
|
||||
'js/Util.js',
|
||||
'js/Map.js',
|
||||
'js/LayersConfig.js',
|
||||
'js/router/BRouter.js',
|
||||
'js/plugin/*.js',
|
||||
'js/control/*.js',
|
||||
'js/index.js'
|
||||
]),
|
||||
styles: mainBowerFiles('**/*.css').concat('css/*.css'),
|
||||
images: mainBowerFiles('**/*.+(png|gif|svg)'),
|
||||
fonts: mainBowerFiles('**/font-awesome/fonts/*'),
|
||||
styles: mainNpmFiles()
|
||||
.filter(
|
||||
f =>
|
||||
RegExp('.*\\.css', 'i').test(f) &&
|
||||
!RegExp('.*\\.min\\.css', 'i').test(f)
|
||||
)
|
||||
.concat('css/*.css'),
|
||||
images: mainNpmFiles().filter(f =>
|
||||
RegExp('.*.+(png|gif|svg)', 'i').test(f)
|
||||
),
|
||||
fonts: mainNpmFiles().filter(f =>
|
||||
RegExp('font-awesome/fonts/.*', 'i').test(f)
|
||||
),
|
||||
locales: 'locales/*.json',
|
||||
layers: 'layers/**/*.geojson',
|
||||
layersDestName: 'layers.js',
|
||||
layersConfig: [
|
||||
'layers/config/config.js',
|
||||
'layers/config/tree.js',
|
||||
'layers/config/overrides.js',
|
||||
'layers/config/geometry.js'
|
||||
],
|
||||
layersConfigDestName: 'layersConf.js',
|
||||
dest: 'dist',
|
||||
destName: 'brouter-web'
|
||||
};
|
||||
|
||||
gulp.task('clean', function(cb) {
|
||||
del(paths.dest + '/**/*', cb);
|
||||
});
|
||||
|
||||
// libs that require loading before config.js
|
||||
gulp.task('scripts_config', ['clean'], function() {
|
||||
gulp.task('scripts_config', function() {
|
||||
// just copy for now
|
||||
return gulp.src(paths.scriptsConfig)
|
||||
.pipe(gulp.dest(paths.dest));
|
||||
return gulp.src(paths.scriptsConfig).pipe(gulp.dest(paths.dest));
|
||||
});
|
||||
|
||||
gulp.task('scripts', function() {
|
||||
if (debug)
|
||||
gutil.log( gutil.colors.yellow('Running in Debug mode') );
|
||||
else
|
||||
gutil.log( gutil.colors.green('Running in Release mode') );
|
||||
if (debug) gutil.log(gutil.colors.yellow('Running in Debug mode'));
|
||||
else gutil.log(gutil.colors.green('Running in Release mode'));
|
||||
|
||||
return gulp.src(paths.scripts, { base: '.' })
|
||||
return gulp
|
||||
.src(paths.scripts, { base: '.' })
|
||||
.pipe(sourcemaps.init())
|
||||
.pipe(cached('scripts'))
|
||||
.pipe(gulpif(!debug, uglify()))
|
||||
|
|
@ -71,168 +111,284 @@ gulp.task('scripts', function() {
|
|||
|
||||
// separate, fallback task for debugging (switch manually in index.html)
|
||||
gulp.task('concat', function() {
|
||||
return gulp.src(paths.scripts)
|
||||
return gulp
|
||||
.src(paths.scripts)
|
||||
.pipe(concat(paths.destName + '.src.js'))
|
||||
.pipe(gulp.dest(paths.dest));
|
||||
});
|
||||
|
||||
gulp.task('styles', function() {
|
||||
return gulp.src(paths.styles)
|
||||
// hack for rewriting relative URLs to images/fonts in gulp-concat-css
|
||||
// when src in css subfolder (remove '../')
|
||||
// see also (?) https://github.com/mariocasciaro/gulp-concat-css/pull/10
|
||||
.pipe(tap(function (file) {
|
||||
if (path.basename(file.base) === 'css') {
|
||||
file.path = 'css/' + file.relative;
|
||||
file.base = './css';
|
||||
} else {
|
||||
file.path = file.relative;
|
||||
file.base = '.';
|
||||
return gulp
|
||||
.src(paths.styles)
|
||||
.pipe(
|
||||
modifyCssUrls({
|
||||
modify(url, filePath) {
|
||||
var distUrl = url;
|
||||
var imageExt = ['.png', '.gif', '.svg'];
|
||||
|
||||
if (imageExt.indexOf(path.extname(url)) !== -1) {
|
||||
distUrl = 'images/' + path.basename(url);
|
||||
} else if (url.indexOf('font') !== -1) {
|
||||
distUrl = 'fonts/' + path.basename(url);
|
||||
}
|
||||
}))
|
||||
.pipe(concatCss(paths.destName + '.css'))
|
||||
.pipe(minifyCss({
|
||||
|
||||
return distUrl;
|
||||
}
|
||||
})
|
||||
)
|
||||
.pipe(concat(paths.destName + '.css'))
|
||||
.pipe(
|
||||
cleanCSS({
|
||||
rebase: false
|
||||
}))
|
||||
})
|
||||
)
|
||||
.pipe(postcss([autoprefixer({ remove: false })]))
|
||||
.pipe(gulp.dest(paths.dest));
|
||||
});
|
||||
|
||||
gulp.task('images', ['clean'], function() {
|
||||
return gulp.src(paths.images)
|
||||
.pipe(gulp.dest(paths.dest + '/images'));
|
||||
gulp.task('images', function() {
|
||||
return gulp.src(paths.images).pipe(gulp.dest(paths.dest + '/images'));
|
||||
});
|
||||
|
||||
gulp.task('fonts', ['clean'], function() {
|
||||
return gulp.src(paths.fonts)
|
||||
.pipe(gulp.dest(paths.dest + '/fonts'));
|
||||
gulp.task('fonts', function() {
|
||||
return gulp.src(paths.fonts).pipe(gulp.dest(paths.dest + '/fonts'));
|
||||
});
|
||||
|
||||
gulp.task('clean', function(cb) {
|
||||
del(paths.dest + '/**/*' , cb);
|
||||
gulp.task('locales', function() {
|
||||
return gulp.src(paths.locales).pipe(gulp.dest(paths.dest + '/locales'));
|
||||
});
|
||||
|
||||
gulp.task('watch', function() {
|
||||
debug = true;
|
||||
var watcher = gulp.watch(paths.scripts, ['scripts']);
|
||||
watcher.on('change', function (event) {
|
||||
var watcher = gulp.watch(paths.scripts, gulp.series('scripts'));
|
||||
watcher.on('change', function(event) {
|
||||
if (event.type === 'deleted') {
|
||||
delete cached.caches.scripts[event.path];
|
||||
remember.forget('scripts', event.path);
|
||||
}
|
||||
});
|
||||
gulp.watch(paths.styles, ['styles']);
|
||||
gulp.watch(paths.styles, gulp.series('styles'));
|
||||
gulp.watch(paths.layersConfig, gulp.series('layers_config'));
|
||||
});
|
||||
|
||||
// Print paths to console, for manually debugging the gulp build
|
||||
// (comment out corresponding line of paths to print)
|
||||
gulp.task('log', function() {
|
||||
//return gulp.src(mainBowerFiles(['**/*.js', '!**/*.min.js']))
|
||||
//return gulp.src(mainBowerFiles('**/*.css'))
|
||||
return gulp.src(paths.scripts)
|
||||
//return gulp.src(paths.scripts)
|
||||
//return gulp.src(paths.styles)
|
||||
//return gulp.src(paths.images)
|
||||
// return gulp.src(paths.locales)
|
||||
return gulp
|
||||
.src(
|
||||
paths.scripts
|
||||
.concat(paths.styles)
|
||||
.concat(paths.images)
|
||||
.concat(paths.locales)
|
||||
)
|
||||
.pipe(gulpDebug());
|
||||
|
||||
//return gulp.src(mainBowerFiles({debugging: true}));
|
||||
});
|
||||
|
||||
gulp.task('inject', function () {
|
||||
gulp.task('inject', function() {
|
||||
var target = gulp.src('index.html');
|
||||
var sources = gulp.src(paths.scripts, { base: '.', read: false });
|
||||
var sources = gulp.src(paths.scripts.concat(paths.styles), {
|
||||
base: '.',
|
||||
read: false
|
||||
});
|
||||
|
||||
return target.pipe(inject(sources, { relative: true }))
|
||||
return target
|
||||
.pipe(inject(sources, { relative: true }))
|
||||
.pipe(gulp.dest('.'));
|
||||
});
|
||||
|
||||
gulp.task('default', ['clean', 'scripts_config', 'scripts', 'styles', 'images', 'fonts']);
|
||||
|
||||
gulp.task('debug', function() {
|
||||
debug = true;
|
||||
gulp.start('default');
|
||||
});
|
||||
|
||||
var pkg = require('./package.json');
|
||||
var tags = {patch: 'patch', minor: 'minor', major: 'major'};
|
||||
var tags = { patch: 'patch', minor: 'minor', major: 'major' };
|
||||
var nextVersion;
|
||||
var ghToken;
|
||||
|
||||
gulp.task('release:init', function() {
|
||||
gulp.task('release:init', function(cb) {
|
||||
var tag = gutil.env.tag;
|
||||
if (!tag) {
|
||||
gutil.log(gutil.colors.red('--tag is required'));
|
||||
process.exit(1);
|
||||
return cb(new Error('--tag is required'));
|
||||
}
|
||||
if (['major', 'minor', 'patch'].indexOf(tag) < 0) {
|
||||
gutil.log(gutil.colors.red('--tag must be major, minor or patch'));
|
||||
process.exit(2);
|
||||
return cb(new Error('--tag must be major, minor or patch'));
|
||||
}
|
||||
ghToken = gutil.env.token;
|
||||
if (!ghToken) {
|
||||
gutil.log(gutil.colors.red('--token is required (github personnal access token)'));
|
||||
process.exit(3);
|
||||
return cb(
|
||||
new Error('--token is required (github personnal access token')
|
||||
);
|
||||
}
|
||||
if (ghToken.length != 40) {
|
||||
gutil.log(gutil.colors.red('--token length must be 40'));
|
||||
process.exit(4);
|
||||
return cb(new Error('--token length must be 40'));
|
||||
}
|
||||
git.status({args: '--porcelain', quiet: true}, function(err, stdout) {
|
||||
if (err) throw err;
|
||||
if (stdout.length > 0) {
|
||||
gutil.log(gutil.colors.red('Repository is not clean. Please commit or stash your pending modification'));
|
||||
process.exit(5);
|
||||
}
|
||||
});
|
||||
|
||||
nextVersion = semver.inc(pkg.version, tag);
|
||||
return;
|
||||
});
|
||||
|
||||
gulp.task('bump', ['bump:json', 'bump:html']);
|
||||
git.status({ args: '--porcelain', quiet: true }, function(err, stdout) {
|
||||
if (err) return cb(err);
|
||||
if (stdout.length > 0) {
|
||||
return cb(
|
||||
new Error(
|
||||
'Repository is not clean. Please commit or stash your pending modification'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
gulp.task('bump:json', ['release:init'], function() {
|
||||
gutil.log(gutil.colors.green('Bump to '+nextVersion));
|
||||
return(gulp.src(['./package.json', './bower.json'])
|
||||
.pipe(bump({version: nextVersion}))
|
||||
.pipe(gulp.dest('./')));
|
||||
});
|
||||
|
||||
gulp.task('bump:html', ['release:init'], function() {
|
||||
return(gulp.src('./index.html')
|
||||
.pipe(replace(/<sup class="version">(.*)<\/sup>/, '<sup class="version">'+nextVersion+'</sup>'))
|
||||
.pipe(gulp.dest('.')));
|
||||
});
|
||||
|
||||
gulp.task('release:commit', ['bump'], function() {
|
||||
gulp.src(['./index.html', './package.json', './bower.json'])
|
||||
.pipe(git.commit('release: '+nextVersion));
|
||||
});
|
||||
|
||||
gulp.task('release:tag', ['release:commit'], function() {
|
||||
return(git.tag(nextVersion, '', function(err) {
|
||||
if (err) throw err;
|
||||
}));
|
||||
});
|
||||
|
||||
gulp.task('release:push', ['release:tag'], function() {
|
||||
git.push('origin', 'master', {args: '--tags'}, function(err) {
|
||||
if (err) throw err;
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('release:zip', ['release:tag', 'default'], function() {
|
||||
gutil.log(gutil.colors.green('Build brouter-web.'+nextVersion+'.zip'));
|
||||
return(gulp.src(['dist/**', 'index.html', 'config.template.js', 'keys.template.js'], {'base': '.'})
|
||||
.pipe(zip('brouter-web.'+nextVersion+'.zip'))
|
||||
.pipe(gulp.dest('.')));
|
||||
gulp.task('bump:json', function() {
|
||||
gutil.log(gutil.colors.green('Bump to ' + nextVersion));
|
||||
return gulp
|
||||
.src(['./package.json'])
|
||||
.pipe(bump({ version: nextVersion }))
|
||||
.pipe(gulp.dest('./'));
|
||||
});
|
||||
|
||||
gulp.task('release:publish', ['release:zip'], function() {
|
||||
gulp.src('./brouter-web.'+nextVersion+'.zip')
|
||||
.pipe(release({
|
||||
gulp.task('bump:html', function() {
|
||||
return gulp
|
||||
.src('./index.html')
|
||||
.pipe(
|
||||
replace(
|
||||
/<sup class="version">(.*)<\/sup>/,
|
||||
'<sup class="version">' + nextVersion + '</sup>'
|
||||
)
|
||||
)
|
||||
.pipe(gulp.dest('.'));
|
||||
});
|
||||
|
||||
gulp.task('bump', gulp.series('bump:json', 'bump:html'));
|
||||
|
||||
gulp.task('release:commit', function() {
|
||||
return gulp
|
||||
.src(['./index.html', './package.json'])
|
||||
.pipe(git.commit('release: ' + nextVersion));
|
||||
});
|
||||
|
||||
gulp.task('release:tag', function(cb) {
|
||||
return git.tag(nextVersion, '', cb);
|
||||
});
|
||||
|
||||
gulp.task('release:push', function(cb) {
|
||||
git.push('origin', 'master', { args: '--tags' }, cb);
|
||||
});
|
||||
|
||||
gulp.task('i18next', function() {
|
||||
return gulp
|
||||
.src([
|
||||
'index.html',
|
||||
'locales/keys.js',
|
||||
'layers/config/overrides.js',
|
||||
'js/**/*.js'
|
||||
])
|
||||
.pipe(sort())
|
||||
.pipe(
|
||||
scanner({
|
||||
lngs: ['en'], // we only generate English version, other languages are handled by transifex via yarn transifex-pull/push
|
||||
removeUnusedKeys: true,
|
||||
sort: true,
|
||||
resource: {
|
||||
// the source path is relative to current working directory
|
||||
loadPath: 'locales/{{lng}}.json',
|
||||
|
||||
// the destination path is relative to your `gulp.dest()` path
|
||||
savePath: 'locales/{{lng}}.json'
|
||||
}
|
||||
})
|
||||
)
|
||||
.pipe(gulp.dest('.'));
|
||||
});
|
||||
|
||||
gulp.task('layers_config', function() {
|
||||
return gulp
|
||||
.src(paths.layersConfig)
|
||||
.pipe(concat(paths.layersConfigDestName))
|
||||
.pipe(gulp.dest(paths.dest));
|
||||
});
|
||||
|
||||
// Bundles layer files. To download and extract run "yarn layers"
|
||||
gulp.task('layers', function() {
|
||||
return (
|
||||
gulp
|
||||
.src(paths.layers)
|
||||
// Workaround to get file extension removed from the dictionary key
|
||||
.pipe(rename({ extname: '.json' }))
|
||||
.pipe(
|
||||
jsonConcat(paths.layersDestName, function(data) {
|
||||
var header =
|
||||
'// Licensed under the MIT License (https://github.com/nrenner/brouter-web#license + Credits and Licenses),\n' +
|
||||
'// except JOSM imagery database (dataSource=JOSM) is licensed under Creative Commons (CC-BY-SA),\n' +
|
||||
'// see https://josm.openstreetmap.de/wiki/Maps#Otherimportantinformation\n';
|
||||
return Buffer.from(
|
||||
header +
|
||||
'BR.layerIndex = ' +
|
||||
JSON.stringify(data, null, 2) +
|
||||
';'
|
||||
);
|
||||
})
|
||||
)
|
||||
.pipe(gulp.dest(paths.dest))
|
||||
);
|
||||
});
|
||||
|
||||
gulp.task(
|
||||
'default',
|
||||
gulp.series(
|
||||
'clean',
|
||||
'scripts_config',
|
||||
'layers_config',
|
||||
'layers',
|
||||
'scripts',
|
||||
'styles',
|
||||
'images',
|
||||
'fonts',
|
||||
'locales'
|
||||
)
|
||||
);
|
||||
|
||||
gulp.task(
|
||||
'debug',
|
||||
gulp.series(function(cb) {
|
||||
debug = true;
|
||||
cb();
|
||||
}, 'default')
|
||||
);
|
||||
|
||||
gulp.task('release:zip', function() {
|
||||
gutil.log(gutil.colors.green('Build brouter-web.' + nextVersion + '.zip'));
|
||||
return gulp
|
||||
.src(
|
||||
['dist/**', 'index.html', 'config.template.js', 'keys.template.js'],
|
||||
{
|
||||
base: '.'
|
||||
}
|
||||
)
|
||||
.pipe(zip('brouter-web.' + nextVersion + '.zip'))
|
||||
.pipe(gulp.dest('.'));
|
||||
});
|
||||
|
||||
gulp.task('release:publish', function() {
|
||||
return gulp.src('./brouter-web.' + nextVersion + '.zip').pipe(
|
||||
release({
|
||||
tag: nextVersion,
|
||||
token: ghToken,
|
||||
manifeste: pkg,
|
||||
}))
|
||||
manifest: pkg
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
gulp.task('release', ['release:init', 'bump', 'release:commit', 'release:tag',
|
||||
'release:push', 'release:zip', 'release:publish']);
|
||||
gulp.task(
|
||||
'release',
|
||||
gulp.series(
|
||||
'release:init',
|
||||
'bump',
|
||||
'release:commit',
|
||||
'release:tag',
|
||||
'release:push',
|
||||
'default',
|
||||
'release:zip',
|
||||
'release:publish'
|
||||
)
|
||||
);
|
||||
|
|
|
|||
1118
index.html
1118
index.html
File diff suppressed because it is too large
Load diff
|
|
@ -1,24 +1,28 @@
|
|||
(function () {
|
||||
|
||||
var touchScreen = (function () {
|
||||
(function() {
|
||||
var touchScreen = (function() {
|
||||
var result = null;
|
||||
|
||||
if ('maxTouchPoints' in navigator) {
|
||||
result = navigator.maxTouchPoints > 0;
|
||||
} else if (window.matchMedia && window.matchMedia('(any-pointer:coarse),(any-pointer:fine),(any-pointer:none)').matches) {
|
||||
result = window.matchMedia("(any-pointer:coarse)").matches;
|
||||
} else if (
|
||||
window.matchMedia &&
|
||||
window.matchMedia(
|
||||
'(any-pointer:coarse),(any-pointer:fine),(any-pointer:none)'
|
||||
).matches
|
||||
) {
|
||||
result = window.matchMedia('(any-pointer:coarse)').matches;
|
||||
} else if ('msMaxTouchPoints' in navigator) {
|
||||
result = navigator.msMaxTouchPoints > 0;
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
}()),
|
||||
touchScreenDetectable = touchScreen !== null;
|
||||
|
||||
})(),
|
||||
touchScreenDetectable = touchScreen !== null,
|
||||
touch = touchScreenDetectable ? touchScreen : L.Browser.touch;
|
||||
|
||||
BR.Browser = {
|
||||
touchScreen: touchScreen,
|
||||
touchScreenDetectable: touchScreenDetectable
|
||||
touchScreenDetectable: touchScreenDetectable,
|
||||
touch: touch
|
||||
};
|
||||
|
||||
}());
|
||||
})();
|
||||
|
|
|
|||
311
js/LayersConfig.js
Normal file
311
js/LayersConfig.js
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
BR.LayersConfig = L.Class.extend({
|
||||
defaultBaseLayers: BR.confLayers.defaultBaseLayers,
|
||||
defaultOverlays: BR.confLayers.defaultOverlays,
|
||||
legacyNameToIdMap: BR.confLayers.legacyNameToIdMap,
|
||||
|
||||
initialize: function(map) {
|
||||
this._map = map;
|
||||
|
||||
this._addLeafletProvidersLayers();
|
||||
this._customizeLayers();
|
||||
this.loadDefaultLayers();
|
||||
this._addLanguageDefaultLayer();
|
||||
},
|
||||
|
||||
loadDefaultLayers: function() {
|
||||
if (BR.Util.localStorageAvailable()) {
|
||||
var item = localStorage.getItem('map/defaultLayers');
|
||||
if (item) {
|
||||
var defaultLayers = JSON.parse(item);
|
||||
this.defaultBaseLayers = defaultLayers.baseLayers;
|
||||
this.defaultOverlays = defaultLayers.overlays;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
storeDefaultLayers: function(baseLayers, overlays) {
|
||||
if (BR.Util.localStorageAvailable()) {
|
||||
var defaultLayers = {
|
||||
baseLayers: baseLayers,
|
||||
overlays: overlays
|
||||
};
|
||||
localStorage.setItem(
|
||||
'map/defaultLayers',
|
||||
JSON.stringify(defaultLayers)
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
_addLeafletProvidersLayers: function() {
|
||||
var includeList = BR.confLayers.leafletProvidersIncludeList;
|
||||
|
||||
for (var i = 0; i < includeList.length; i++) {
|
||||
var id = includeList[i];
|
||||
var obj = {
|
||||
geometry: null,
|
||||
properties: {
|
||||
id: id,
|
||||
name: id.replace('.', ' '),
|
||||
dataSource: 'leaflet-providers'
|
||||
},
|
||||
type: 'Feature'
|
||||
};
|
||||
BR.layerIndex[id] = obj;
|
||||
}
|
||||
},
|
||||
|
||||
_customizeLayers: function() {
|
||||
var propertyOverrides = BR.confLayers.getPropertyOverrides();
|
||||
|
||||
for (id in propertyOverrides) {
|
||||
var layer = BR.layerIndex[id];
|
||||
|
||||
if (layer) {
|
||||
var properties = propertyOverrides[id];
|
||||
|
||||
for (key in properties) {
|
||||
var value = properties[key];
|
||||
layer.properties[key] = value;
|
||||
}
|
||||
} else {
|
||||
console.error('Layer not found: ' + id);
|
||||
}
|
||||
}
|
||||
|
||||
BR.layerIndex['MtbMap'].geometry = BR.confLayers.europeGeofabrik;
|
||||
BR.layerIndex['1069'].geometry = BR.confLayers.europeGeofabrik;
|
||||
|
||||
BR.layerIndex['OpenStreetMap.CH'].geometry =
|
||||
BR.confLayers.switzerlandPadded;
|
||||
|
||||
BR.layerIndex['1017'].geometry = BR.confLayers.osmapaPl;
|
||||
},
|
||||
|
||||
_addLanguageDefaultLayer: function() {
|
||||
// language code -> layer id
|
||||
var languageLayersMap = {};
|
||||
var i;
|
||||
|
||||
for (i = 0; i < BR.confLayers.languageDefaultLayers.length; i++) {
|
||||
var id = BR.confLayers.languageDefaultLayers[i];
|
||||
var layer = BR.layerIndex[id];
|
||||
if (layer) {
|
||||
var layerLanguage = layer.properties['language_code'];
|
||||
if (layerLanguage) {
|
||||
languageLayersMap[layerLanguage] = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// iterate language code hierarchy, e.g ["de-DE", "de", "en"] (includes `i18next.options.fallbackLng`)
|
||||
for (i = 0; i < i18next.languages.length; i++) {
|
||||
var language = i18next.languages[i];
|
||||
var layerId = languageLayersMap[language];
|
||||
|
||||
if (layerId) {
|
||||
this.defaultBaseLayers.unshift(layerId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
isDefaultLayer: function(id, overlay) {
|
||||
var result = false;
|
||||
if (overlay) {
|
||||
result = this.defaultOverlays.indexOf(id) > -1;
|
||||
} else {
|
||||
result = this.defaultBaseLayers.indexOf(id) > -1;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
getBaseLayers: function() {
|
||||
return this._getLayers(this.defaultBaseLayers);
|
||||
},
|
||||
|
||||
getOverlays: function() {
|
||||
return this._getLayers(this.defaultOverlays);
|
||||
},
|
||||
|
||||
_getLayers: function(ids) {
|
||||
var layers = {};
|
||||
|
||||
for (var i = 0; i < ids.length; i++) {
|
||||
var layerId = ids[i];
|
||||
var layerData = BR.layerIndex[layerId];
|
||||
|
||||
if (layerData) {
|
||||
// when key required only add if configured
|
||||
var keyObj = this.getKeyName(layerData.properties.url);
|
||||
if (!keyObj || (keyObj && BR.keys[keyObj.name])) {
|
||||
layers[layerData.properties.name] = this.createLayer(
|
||||
layerData
|
||||
);
|
||||
}
|
||||
} else {
|
||||
console.error('Layer not found: ' + layerId);
|
||||
}
|
||||
}
|
||||
|
||||
return layers;
|
||||
},
|
||||
|
||||
// own convention: key placeholder with prefix
|
||||
// e.g. ?api_key={keys_openrouteservice}
|
||||
getKeyName: function(url) {
|
||||
var result = null;
|
||||
// L.Util.template only matches [\w_-]
|
||||
var prefix = 'keys_';
|
||||
var regex = new RegExp('{' + prefix + '([^}]*)}');
|
||||
var found, name;
|
||||
|
||||
if (!url) return result;
|
||||
|
||||
found = url.match(regex);
|
||||
if (found) {
|
||||
name = found[1];
|
||||
result = {
|
||||
name: name,
|
||||
urlVar: prefix + name
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
createLayer: function(layerData) {
|
||||
var props = layerData.properties;
|
||||
var url = props.url;
|
||||
var layer;
|
||||
|
||||
// JOSM: https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png
|
||||
// Leaflet: https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png
|
||||
function convertUrlJosm(url) {
|
||||
var rxSwitch = /{switch:[^}]*}/;
|
||||
var rxZoom = /{zoom}/g;
|
||||
var result = url.replace(rxSwitch, '{s}');
|
||||
result = result.replace(rxZoom, '{z}');
|
||||
return result;
|
||||
}
|
||||
|
||||
// JOSM: https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png
|
||||
// Leaflet: ['a','b','c']
|
||||
function getSubdomains(url) {
|
||||
var result = 'abc';
|
||||
var regex = /{switch:([^}]*)}/;
|
||||
var found = url.match(regex);
|
||||
if (found) {
|
||||
result = found[1].split(',');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function convertAttributionJosm(props) {
|
||||
var result = '';
|
||||
var attr = props.attribution;
|
||||
|
||||
if (attr) {
|
||||
if (attr.html) {
|
||||
result = attr.html;
|
||||
} else if (attr.url && attr.text) {
|
||||
result =
|
||||
'<a href="' +
|
||||
attr.url +
|
||||
'" target="_blank" rel="noopener">' +
|
||||
attr.text +
|
||||
'</a>';
|
||||
} else if (attr.text) {
|
||||
result = attr.text;
|
||||
}
|
||||
}
|
||||
if (!result) {
|
||||
console.warn('No attribution: ' + props.id);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
var options = {
|
||||
maxZoom: this._map.getMaxZoom(),
|
||||
bounds:
|
||||
layerData.geometry && !props.worldTiles
|
||||
? L.geoJson(layerData.geometry).getBounds()
|
||||
: null
|
||||
};
|
||||
if (props.mapUrl) {
|
||||
options.mapLink =
|
||||
'<a target="_blank" href="' +
|
||||
props.mapUrl +
|
||||
'">' +
|
||||
(props.nameShort || props.name) +
|
||||
'</a>';
|
||||
}
|
||||
if (props.attribution) {
|
||||
options.attribution = props.attribution;
|
||||
}
|
||||
|
||||
var keyObj = this.getKeyName(url);
|
||||
if (keyObj && BR.keys[keyObj.name]) {
|
||||
options[keyObj.urlVar] = BR.keys[keyObj.name];
|
||||
}
|
||||
|
||||
if (props.dataSource === 'leaflet-providers') {
|
||||
layer = L.tileLayer.provider(props.id);
|
||||
|
||||
var layerOptions = L.Util.extend(options, {
|
||||
maxNativeZoom: layer.options.maxZoom
|
||||
});
|
||||
L.setOptions(layer, layerOptions);
|
||||
} else if (props.dataSource === 'LayersCollection') {
|
||||
layer = L.tileLayer(
|
||||
url,
|
||||
L.Util.extend(options, {
|
||||
minZoom: props.minZoom || 0,
|
||||
maxNativeZoom: props.maxZoom
|
||||
})
|
||||
);
|
||||
if (props.subdomains) {
|
||||
layer.subdomains = props.subdomains;
|
||||
}
|
||||
} else {
|
||||
// JOSM
|
||||
var josmUrl = url;
|
||||
var url = convertUrlJosm(josmUrl);
|
||||
|
||||
var josmOptions = L.Util.extend(options, {
|
||||
minZoom: props.min_zoom || 0,
|
||||
maxNativeZoom: props.max_zoom,
|
||||
subdomains: getSubdomains(josmUrl),
|
||||
attribution: convertAttributionJosm(props)
|
||||
});
|
||||
|
||||
if (props.type && props.type === 'wms') {
|
||||
layer = L.tileLayer.wms(
|
||||
url,
|
||||
L.Util.extend(josmOptions, {
|
||||
layers: props.layers,
|
||||
format: props.format
|
||||
})
|
||||
);
|
||||
} else {
|
||||
layer = L.tileLayer(url, josmOptions);
|
||||
}
|
||||
}
|
||||
|
||||
// Layer attribution here only as short link to original site,
|
||||
// to keep current position use placeholders: {zoom}/{lat}/{lon}
|
||||
// Copyright attribution in index.html #credits
|
||||
var getAttribution = function() {
|
||||
return this.options.mapLink;
|
||||
};
|
||||
layer.getAttribution = getAttribution;
|
||||
|
||||
layer.id = props.id;
|
||||
|
||||
return layer;
|
||||
}
|
||||
});
|
||||
|
||||
BR.layersConfig = function(map) {
|
||||
return new BR.LayersConfig(map);
|
||||
};
|
||||
178
js/Map.js
178
js/Map.js
|
|
@ -1,94 +1,74 @@
|
|||
BR.Map = {
|
||||
|
||||
initMap: function() {
|
||||
var map,
|
||||
layersControl;
|
||||
var map, layersControl;
|
||||
|
||||
BR.keys = BR.keys || {};
|
||||
|
||||
var maxZoom = 19;
|
||||
|
||||
var osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: maxZoom
|
||||
});
|
||||
|
||||
var osmde = L.tileLayer('https://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png', {
|
||||
maxNativeZoom: 18,
|
||||
maxZoom: maxZoom
|
||||
});
|
||||
|
||||
var topo = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
|
||||
maxNativeZoom: 17,
|
||||
maxZoom: maxZoom
|
||||
});
|
||||
|
||||
var thunderforestAttribution = 'tiles © <a target="_blank" href="https://www.thunderforest.com">Thunderforest</a> '
|
||||
+ '(<a target="_blank" href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA 2.0</a>)';
|
||||
var thunderforestAuth = BR.keys.thunderforest ? '?apikey=' + BR.keys.thunderforest : '';
|
||||
var cycle = L.tileLayer('https://{s}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png' + thunderforestAuth, {
|
||||
maxNativeZoom: 18,
|
||||
maxZoom: maxZoom
|
||||
});
|
||||
var outdoors = L.tileLayer('https://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png' + thunderforestAuth, {
|
||||
maxNativeZoom: 18,
|
||||
maxZoom: maxZoom
|
||||
});
|
||||
|
||||
var esri = L.tileLayer('https://{s}.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
|
||||
maxNativeZoom: 19,
|
||||
maxZoom: maxZoom,
|
||||
subdomains: ['server', 'services'],
|
||||
attribution: '<a target="_blank" href="http://goto.arcgisonline.com/maps/World_Imagery">World Imagery</a> '
|
||||
+ '© <a target="_blank" href="https://www.esri.com/">Esri</a>, sources: '
|
||||
+ 'Esri, DigitalGlobe, Earthstar Geographics, CNES/Airbus DS, GeoEye, USDA FSA, USGS, Getmapping, Aerogrid, IGN, IGP, and the GIS User Community'
|
||||
});
|
||||
|
||||
var cycling = L.tileLayer('https://tile.waymarkedtrails.org/cycling/{z}/{x}/{y}.png', {
|
||||
maxNativeZoom: 18,
|
||||
opacity: 0.7,
|
||||
maxZoom: maxZoom
|
||||
});
|
||||
var hiking = L.tileLayer('https://tile.waymarkedtrails.org/hiking/{z}/{x}/{y}.png', {
|
||||
maxNativeZoom: 18,
|
||||
opacity: 0.7,
|
||||
maxZoom: maxZoom
|
||||
});
|
||||
|
||||
map = new L.Map('map', {
|
||||
worldCopyJump: true
|
||||
zoomControl: false, // add it manually so that we can translate it
|
||||
worldCopyJump: true,
|
||||
minZoom: 0,
|
||||
maxZoom: maxZoom
|
||||
});
|
||||
L.control
|
||||
.zoom({
|
||||
zoomInTitle: i18next.t('map.zoomInTitle'),
|
||||
zoomOutTitle: i18next.t('map.zoomOutTitle')
|
||||
})
|
||||
.addTo(map);
|
||||
if (!map.restoreView()) {
|
||||
map.setView([50.99, 9.86], 6);
|
||||
map.setView([50.99, 9.86], 5);
|
||||
}
|
||||
|
||||
// two attribution lines by adding two controls, prevents ugly wrapping on
|
||||
// small screens, better separates static from layer-specific attribution
|
||||
var osmAttribution =
|
||||
$(map.getContainer()).outerWidth() >= 400
|
||||
? i18next.t('map.attribution-osm-long')
|
||||
: i18next.t('map.attribution-osm-short');
|
||||
map.attributionControl.setPrefix(
|
||||
'© <a target="_blank" href="https://www.openstreetmap.org/copyright">' +
|
||||
osmAttribution +
|
||||
'</a>' +
|
||||
' · <a href="" data-toggle="modal" data-target="#credits">' +
|
||||
i18next.t('map.copyright') +
|
||||
'</a>' +
|
||||
' · <a target="_blank" href="http://brouter.de/privacypolicy.html">' +
|
||||
i18next.t('map.privacy') +
|
||||
'</a>'
|
||||
);
|
||||
|
||||
$('#credits').on('show.bs.modal', function(event) {
|
||||
BR.Map._renderLayerCredits(layersControl._layers);
|
||||
});
|
||||
|
||||
new L.Control.PermalinkAttribution().addTo(map);
|
||||
map.attributionControl.setPrefix(false);
|
||||
map.attributionControl.addAttribution('<a href="" data-toggle="modal" data-target="#credits">Copyright & credits</a>')
|
||||
|
||||
|
||||
var baseLayers = {
|
||||
'OpenStreetMap': osm,
|
||||
'OpenStreetMap.de': osmde,
|
||||
'OpenTopoMap': topo,
|
||||
'OpenCycleMap (Thunderf.)': cycle,
|
||||
'Outdoors (Thunderforest)': outdoors,
|
||||
'Esri World Imagery': esri
|
||||
};
|
||||
var overlays = {
|
||||
'Cycling (Waymarked Trails)': cycling,
|
||||
'Hiking (Waymarked Trails)': hiking
|
||||
};
|
||||
var layersConfig = BR.layersConfig(map);
|
||||
var baseLayers = layersConfig.getBaseLayers();
|
||||
var overlays = layersConfig.getOverlays();
|
||||
|
||||
if (BR.keys.bing) {
|
||||
baseLayers['Bing Aerial'] = new BR.BingLayer(BR.keys.bing);
|
||||
baseLayers[i18next.t('map.layer.bing')] = new BR.BingLayer(
|
||||
BR.keys.bing
|
||||
);
|
||||
}
|
||||
|
||||
if (BR.keys.digitalGlobe) {
|
||||
var recent = new L.tileLayer('https://{s}.tiles.mapbox.com/v4/digitalglobe.nal0g75k/{z}/{x}/{y}.png?access_token=' + BR.keys.digitalGlobe, {
|
||||
var recent = new L.tileLayer(
|
||||
'https://{s}.tiles.mapbox.com/v4/digitalglobe.nal0g75k/{z}/{x}/{y}.png?access_token=' +
|
||||
BR.keys.digitalGlobe,
|
||||
{
|
||||
minZoom: 1,
|
||||
maxZoom: 19,
|
||||
attribution: '© <a href="https://www.digitalglobe.com/platforms/mapsapi">DigitalGlobe</a> ('
|
||||
+ '<a href="https://bit.ly/mapsapiview">Terms of Use</a>)'
|
||||
});
|
||||
baseLayers['DigitalGlobe Recent Imagery'] = recent;
|
||||
attribution:
|
||||
'© <a href="https://www.digitalglobe.com/platforms/mapsapi">DigitalGlobe</a> (<a href="https://bit.ly/mapsapiview">Terms of Use</a>)'
|
||||
}
|
||||
);
|
||||
baseLayers[i18next.t('map.layer.digitalglobe')] = recent;
|
||||
}
|
||||
|
||||
if (BR.conf.clearBaseLayers) {
|
||||
|
|
@ -105,18 +85,26 @@ BR.Map = {
|
|||
overlays[i] = L.tileLayer(BR.conf.overlays[i]);
|
||||
}
|
||||
}
|
||||
// after applying custom base layer configurations, add first base layer to map
|
||||
var firstLayer = baseLayers[Object.keys(baseLayers)[0]];
|
||||
if (firstLayer) {
|
||||
map.addLayer(firstLayer);
|
||||
}
|
||||
|
||||
layersControl = L.control.layers(baseLayers, overlays).addTo(map);
|
||||
layersControl = BR.layersTab(layersConfig, baseLayers, overlays).addTo(
|
||||
map
|
||||
);
|
||||
|
||||
L.control.locate({
|
||||
var secureContext =
|
||||
'isSecureContext' in window
|
||||
? isSecureContext
|
||||
: location.protocol === 'https:';
|
||||
if (secureContext) {
|
||||
L.control
|
||||
.locate({
|
||||
strings: {
|
||||
title: i18next.t('map.locate-me')
|
||||
},
|
||||
icon: 'fa fa-location-arrow',
|
||||
iconLoading: 'fa fa-spinner fa-pulse',
|
||||
}).addTo(map);
|
||||
iconLoading: 'fa fa-spinner fa-pulse'
|
||||
})
|
||||
.addTo(map);
|
||||
}
|
||||
|
||||
L.control.scale().addTo(map);
|
||||
|
||||
|
|
@ -126,15 +114,31 @@ BR.Map = {
|
|||
BR.debug = BR.debug || {};
|
||||
BR.debug.map = map;
|
||||
|
||||
var layersAndOverlays = baseLayers;
|
||||
for (var o in overlays) {
|
||||
layersAndOverlays[o] = overlays[o];
|
||||
}
|
||||
return {
|
||||
map: map,
|
||||
layersControl: layersControl,
|
||||
layers: layersAndOverlays
|
||||
layersControl: layersControl
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
_renderLayerCredits: function(layers) {
|
||||
var dl = document.getElementById('credits-maps');
|
||||
var i, obj, dt, dd, attribution;
|
||||
|
||||
L.DomUtil.empty(dl);
|
||||
|
||||
for (i = 0; i < layers.length; i++) {
|
||||
obj = layers[i];
|
||||
attribution = obj.layer.options.attribution;
|
||||
|
||||
if (attribution) {
|
||||
dt = document.createElement('dt');
|
||||
dt.innerHTML = obj.name;
|
||||
dd = document.createElement('dd');
|
||||
dd.innerHTML = obj.layer.options.attribution;
|
||||
|
||||
dl.appendChild(dt);
|
||||
dl.appendChild(dd);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
BR.Util = {
|
||||
|
||||
get: function(url, cb) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
|
|
@ -16,13 +15,13 @@ BR.Util = {
|
|||
};
|
||||
try {
|
||||
xhr.send();
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
cb(e);
|
||||
}
|
||||
},
|
||||
|
||||
getError: function(xhr) {
|
||||
var msg = 'no response from server';
|
||||
var msg = i18next.t('warning.no-response');
|
||||
if (xhr.responseText) {
|
||||
msg = xhr.responseText;
|
||||
} else if (xhr.status || xhr.statusText) {
|
||||
|
|
@ -46,8 +45,7 @@ BR.Util = {
|
|||
storage.setItem(x, x);
|
||||
storage.removeItem(x);
|
||||
return true;
|
||||
}
|
||||
catch(e) {
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
99
js/control/Control.Layers.js
Normal file
99
js/control/Control.Layers.js
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
BR.ControlLayers = L.Control.Layers.extend({
|
||||
getActiveLayers: function() {
|
||||
var result = [];
|
||||
|
||||
for (var i = 0; i < this._layers.length; i++) {
|
||||
var obj = this._layers[i];
|
||||
if (this._map.hasLayer(obj.layer)) {
|
||||
if (obj.overlay) {
|
||||
result.push(obj);
|
||||
} else {
|
||||
result.unshift(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
getActiveBaseLayer: function() {
|
||||
var activeLayers = this.getActiveLayers();
|
||||
for (var i = 0; i < activeLayers.length; i++) {
|
||||
var obj = activeLayers[i];
|
||||
if (!obj.overlay) {
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
removeActiveLayers: function() {
|
||||
var removed = [];
|
||||
|
||||
for (var i = 0; i < this._layers.length; i++) {
|
||||
var obj = this._layers[i];
|
||||
if (this._map.hasLayer(obj.layer)) {
|
||||
this._map.removeLayer(obj.layer);
|
||||
removed.push(obj);
|
||||
}
|
||||
}
|
||||
|
||||
return removed;
|
||||
},
|
||||
|
||||
getLayer: function(name) {
|
||||
for (var i = 0; i < this._layers.length; i++) {
|
||||
var obj = this._layers[i];
|
||||
if (obj.name === name) {
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
getBaseLayers: function() {
|
||||
return this._layers.filter(function(obj) {
|
||||
return !obj.overlay;
|
||||
});
|
||||
},
|
||||
|
||||
activateLayer: function(obj) {
|
||||
if (!this._map.hasLayer(obj.layer)) {
|
||||
this._map.addLayer(obj.layer);
|
||||
}
|
||||
},
|
||||
|
||||
activateFirstLayer: function() {
|
||||
for (var i = 0; i < this._layers.length; i++) {
|
||||
var obj = this._layers[i];
|
||||
if (!obj.overlay) {
|
||||
this.activateLayer(obj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
activateBaseLayerIndex: function(index) {
|
||||
var baseLayers = this.getBaseLayers();
|
||||
var obj = baseLayers[index];
|
||||
|
||||
this.activateLayer(obj);
|
||||
},
|
||||
|
||||
_addLayer: function(layer, name, overlay) {
|
||||
L.Control.Layers.prototype._addLayer.call(this, layer, name, overlay);
|
||||
|
||||
// override z-index assignment to fix that base layers added later
|
||||
// are on top of overlays; set all base layers to 0
|
||||
if (this.options.autoZIndex && layer.setZIndex) {
|
||||
if (!overlay) {
|
||||
// undo increase in super method
|
||||
this._lastZIndex--;
|
||||
|
||||
layer.setZIndex(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
BR.Control = L.Control.extend({
|
||||
options: {
|
||||
position: 'bottomleft'
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
var container = L.DomUtil.create('div', 'info'),
|
||||
heading,
|
||||
div;
|
||||
|
||||
if (this.options.heading) {
|
||||
heading = L.DomUtil.create('div', 'heading', container);
|
||||
heading.innerHTML = this.options.heading;
|
||||
this._content = L.DomUtil.create('div', 'content', container);
|
||||
} else {
|
||||
this._content = container;
|
||||
}
|
||||
|
||||
if (this.options.divId) {
|
||||
div = L.DomUtil.get(this.options.divId);
|
||||
L.DomUtil.removeClass(div, 'hidden');
|
||||
this._content.appendChild(div);
|
||||
}
|
||||
|
||||
var stop = L.DomEvent.stopPropagation;
|
||||
L.DomEvent
|
||||
.on(container, 'click', stop)
|
||||
.on(container, 'mousedown', stop)
|
||||
.on(container, 'dblclick', stop)
|
||||
.on(container, 'mousewheel', stop)
|
||||
.on(container, 'MozMousePixelScroll', stop);
|
||||
// disabled because links not working, remove?
|
||||
//L.DomEvent.on(container, 'click', L.DomEvent.preventDefault);
|
||||
|
||||
return container;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
BR.Download = L.Class.extend({
|
||||
update: function (urls) {
|
||||
if (urls) {
|
||||
['gpx', 'kml', 'geojson', 'csv'].forEach(function(e, i, a) {
|
||||
var a = L.DomUtil.get('dl-'+e);
|
||||
a.setAttribute('href', urls[e]);
|
||||
a.setAttribute('download', 'brouter.'+e);
|
||||
a.removeAttribute('disabled');
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
BR.download = function() {
|
||||
return new BR.Download();
|
||||
};
|
||||
167
js/control/Export.js
Normal file
167
js/control/Export.js
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
BR.Export = L.Class.extend({
|
||||
latLngs: [],
|
||||
|
||||
initialize: function(router) {
|
||||
this.router = router;
|
||||
this.exportButton = $('#exportButton');
|
||||
var trackname = (this.trackname = document.getElementById('trackname'));
|
||||
this.tracknameAllowedChars = BR.conf.tracknameAllowedChars;
|
||||
|
||||
if (this.tracknameAllowedChars) {
|
||||
this.tracknameMessage = document.getElementById(
|
||||
'trackname-message'
|
||||
);
|
||||
var patternRegex = new RegExp(
|
||||
'[' + this.tracknameAllowedChars + ']+'
|
||||
);
|
||||
|
||||
// warn about special characters getting removed by server quick fix (#194)
|
||||
trackname.pattern = patternRegex.toString().slice(1, -1);
|
||||
trackname.addEventListener(
|
||||
'input',
|
||||
L.bind(this._validationMessage, this)
|
||||
);
|
||||
}
|
||||
|
||||
this.exportButton.on('click', L.bind(this._generateTrackname, this));
|
||||
L.DomUtil.get('submitExport').onclick = L.bind(this._export, this);
|
||||
|
||||
this.update([]);
|
||||
},
|
||||
|
||||
update: function(latLngs) {
|
||||
this.latLngs = latLngs;
|
||||
|
||||
if (latLngs.length < 2) {
|
||||
this.exportButton.addClass('disabled');
|
||||
} else {
|
||||
this.exportButton.removeClass('disabled');
|
||||
}
|
||||
},
|
||||
|
||||
_export: function() {
|
||||
var exportForm = document.forms['export'];
|
||||
var format =
|
||||
exportForm['format'].value ||
|
||||
$('#export-format input:radio:checked').val();
|
||||
var name = encodeURIComponent(exportForm['trackname'].value);
|
||||
var includeWaypoints = exportForm['include-waypoints'].checked;
|
||||
|
||||
var uri = this.router.getUrl(
|
||||
this.latLngs,
|
||||
format,
|
||||
name,
|
||||
includeWaypoints
|
||||
);
|
||||
|
||||
var evt = document.createEvent('MouseEvents');
|
||||
evt.initMouseEvent(
|
||||
'click',
|
||||
true,
|
||||
true,
|
||||
window,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
0,
|
||||
null
|
||||
);
|
||||
var link = document.createElement('a');
|
||||
link.href = uri;
|
||||
link.dispatchEvent(evt);
|
||||
},
|
||||
|
||||
_validationMessage: function() {
|
||||
var trackname = this.trackname;
|
||||
var replaceRegex = new RegExp(
|
||||
'[^' + this.tracknameAllowedChars + ']',
|
||||
'g'
|
||||
);
|
||||
|
||||
if (trackname.validity.patternMismatch) {
|
||||
var replaced = trackname.value.replace(replaceRegex, '');
|
||||
var patternStr = this.tracknameAllowedChars.replace(/\\/g, '');
|
||||
this.tracknameMessage.textContent =
|
||||
'[' + patternStr + '] --> ' + replaced;
|
||||
} else {
|
||||
this.tracknameMessage.textContent = '';
|
||||
}
|
||||
},
|
||||
|
||||
_generateTrackname: function() {
|
||||
var trackname = this.trackname;
|
||||
this._getCityAtPosition(
|
||||
this.latLngs[0],
|
||||
L.bind(function(from) {
|
||||
this._getCityAtPosition(
|
||||
this.latLngs[this.latLngs.length - 1],
|
||||
L.bind(function(to) {
|
||||
var distance = document.getElementById('distance')
|
||||
.innerHTML;
|
||||
if (this.tracknameAllowedChars) {
|
||||
distance = distance.replace(',', '.'); // temp. fix (#202)
|
||||
}
|
||||
if (!from || !to) {
|
||||
trackname.value = null;
|
||||
} else if (from === to) {
|
||||
trackname.value = i18next.t('export.route-loop', {
|
||||
from: from,
|
||||
distance: distance
|
||||
});
|
||||
} else {
|
||||
trackname.value = i18next.t(
|
||||
'export.route-from-to',
|
||||
{ from: from, to: to, distance: distance }
|
||||
);
|
||||
}
|
||||
|
||||
if (this.tracknameAllowedChars) {
|
||||
// temp. fix: replace and remove characters that will get removed by server quick fix (#194)
|
||||
trackname.value = trackname.value
|
||||
.replace(/[>)]/g, '')
|
||||
.replace(/ \(/g, ' - ');
|
||||
this._validationMessage();
|
||||
}
|
||||
}, this)
|
||||
);
|
||||
}, this)
|
||||
);
|
||||
},
|
||||
|
||||
_getCityAtPosition: function(lonlat, cb) {
|
||||
var url = L.Util.template(
|
||||
'https://nominatim.openstreetmap.org/reverse?lon={lng}&lat={lat}&format=json',
|
||||
lonlat
|
||||
);
|
||||
BR.Util.get(
|
||||
url,
|
||||
L.bind(function(err, response) {
|
||||
try {
|
||||
var addr = JSON.parse(response).address;
|
||||
cb(
|
||||
addr.village ||
|
||||
addr.town ||
|
||||
addr.hamlet ||
|
||||
addr.city_district ||
|
||||
addr.city
|
||||
);
|
||||
} catch (err) {
|
||||
BR.message.showError(
|
||||
'Error getting position city "' + lonlat + '": ' + err
|
||||
);
|
||||
return cb(null);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
BR.export = function() {
|
||||
return new BR.Export();
|
||||
};
|
||||
|
|
@ -1,23 +1,19 @@
|
|||
BR.Itinerary = L.Class.extend({
|
||||
options: {
|
||||
heading: 'Itinerary'
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
initialize: function() {
|
||||
this._content = document.getElementById('itinerary');
|
||||
L.DomUtil.removeClass(this._content.parentElement, 'hidden');
|
||||
this.update();
|
||||
},
|
||||
|
||||
update: function (polyline, segments) {
|
||||
var i, j, iter, html = '';
|
||||
update: function(polyline, segments) {
|
||||
var i,
|
||||
j,
|
||||
iter,
|
||||
html = '';
|
||||
|
||||
html += '<pre>';
|
||||
for (i = 0; segments && i < segments.length; i++)
|
||||
{
|
||||
html += '<pre class="flexgrow">';
|
||||
for (i = 0; segments && i < segments.length; i++) {
|
||||
iter = segments[i].feature.iternity;
|
||||
for (j = 0; iter && j < iter.length; j++)
|
||||
{
|
||||
for (j = 0; iter && j < iter.length; j++) {
|
||||
html += iter[j] + '\n';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
BR.Layers = L.Class.extend({
|
||||
|
||||
_loadLayers: function() {
|
||||
this._customLayers = {};
|
||||
|
||||
if (BR.Util.localStorageAvailable()) {
|
||||
var layers = JSON.parse(localStorage.getItem("map/customLayers"));
|
||||
var layers = JSON.parse(localStorage.getItem('map/customLayers'));
|
||||
for (a in layers) {
|
||||
this._addLayer(a, layers[a].layer, layers[a].isOverlay);
|
||||
}
|
||||
|
|
@ -14,7 +13,11 @@ BR.Layers = L.Class.extend({
|
|||
_loadTable: function() {
|
||||
var layersData = [];
|
||||
for (layer in this._customLayers) {
|
||||
layersData.push([layer, this._customLayers[layer].layer._url, this._customLayers[layer].isOverlay ? "Overlay" : "Layer"]);
|
||||
layersData.push([
|
||||
layer,
|
||||
this._customLayers[layer].layer._url,
|
||||
this._customLayers[layer].isOverlay ? 'Overlay' : 'Layer'
|
||||
]);
|
||||
}
|
||||
if (this._layersTable != null) {
|
||||
this._layersTable.destroy();
|
||||
|
|
@ -25,10 +28,13 @@ BR.Layers = L.Class.extend({
|
|||
info: false,
|
||||
searching: false,
|
||||
paging: false,
|
||||
language: {
|
||||
emptyTable: i18next.t('sidebar.layers.table.empty')
|
||||
},
|
||||
columns: [
|
||||
{ title: "Name" },
|
||||
{ title: "URL" },
|
||||
{ title: "Type" }
|
||||
{ title: i18next.t('sidebar.layers.table.name') },
|
||||
{ title: i18next.t('sidebar.layers.table.URL') },
|
||||
{ title: i18next.t('sidebar.layers.table.type') }
|
||||
]
|
||||
});
|
||||
},
|
||||
|
|
@ -36,22 +42,29 @@ BR.Layers = L.Class.extend({
|
|||
init: function(map, layersControl, baseLayers, overlays) {
|
||||
this._layersControl = layersControl;
|
||||
this._map = map;
|
||||
this._layers = {}
|
||||
for (var l in overlays)
|
||||
this._layers[l] = [overlays[l], true];
|
||||
for (var l in baseLayers)
|
||||
this._layers[l] = [baseLayers[l], false];
|
||||
this._layers = {};
|
||||
for (var l in overlays) this._layers[l] = [overlays[l], true];
|
||||
for (var l in baseLayers) this._layers[l] = [baseLayers[l], false];
|
||||
|
||||
L.DomUtil.get('custom_layers_add_base').onclick = L.bind(this._addBaseLayer, this);
|
||||
L.DomUtil.get('custom_layers_add_overlay').onclick = L.bind(this._addOverlay, this);
|
||||
L.DomUtil.get('custom_layers_remove').onclick = L.bind(this._remove, this);
|
||||
L.DomUtil.get('custom_layers_add_base').onclick = L.bind(
|
||||
this._addBaseLayer,
|
||||
this
|
||||
);
|
||||
L.DomUtil.get('custom_layers_add_overlay').onclick = L.bind(
|
||||
this._addOverlay,
|
||||
this
|
||||
);
|
||||
L.DomUtil.get('custom_layers_remove').onclick = L.bind(
|
||||
this._remove,
|
||||
this
|
||||
);
|
||||
|
||||
this._loadLayers();
|
||||
this._loadTable();
|
||||
|
||||
var table = this._layersTable;
|
||||
$('#custom_layers_table tbody').on( 'click', 'tr', function () {
|
||||
if ( $(this).hasClass('selected') ) {
|
||||
$('#custom_layers_table tbody').on('click', 'tr', function() {
|
||||
if ($(this).hasClass('selected')) {
|
||||
$(this).removeClass('selected');
|
||||
} else {
|
||||
table.$('tr.selected').removeClass('selected');
|
||||
|
|
@ -59,16 +72,9 @@ BR.Layers = L.Class.extend({
|
|||
}
|
||||
});
|
||||
|
||||
addLayer = L.easyButton(
|
||||
'fa-plus-square',
|
||||
function () {
|
||||
L.DomUtil.get('custom_layers_button').onclick = function() {
|
||||
$('#custom_layers').modal();
|
||||
},
|
||||
'Add or remove custom layers',
|
||||
{
|
||||
position: 'topright'
|
||||
}
|
||||
).addTo(map);
|
||||
};
|
||||
},
|
||||
|
||||
_remove: function(evt) {
|
||||
|
|
@ -78,7 +84,10 @@ BR.Layers = L.Class.extend({
|
|||
this._layersControl.removeLayer(this._customLayers[name].layer);
|
||||
this._map.removeLayer(this._customLayers[name].layer);
|
||||
delete this._customLayers[name];
|
||||
this._layersTable.row('.selected').remove().draw( false );
|
||||
this._layersTable
|
||||
.row('.selected')
|
||||
.remove()
|
||||
.draw(false);
|
||||
this._sync();
|
||||
}
|
||||
},
|
||||
|
|
@ -98,16 +107,17 @@ BR.Layers = L.Class.extend({
|
|||
},
|
||||
|
||||
_addLayer: function(layerName, layerUrl, isOverlay) {
|
||||
if (layerName in this._layers)
|
||||
return
|
||||
if (layerName in this._layers) return;
|
||||
|
||||
if (layerName in this._customLayers)
|
||||
return
|
||||
if (layerName in this._customLayers) return;
|
||||
|
||||
try {
|
||||
var layer = L.tileLayer(layerUrl);
|
||||
|
||||
this._customLayers[layerName] = {layer: layer, isOverlay: isOverlay};
|
||||
this._customLayers[layerName] = {
|
||||
layer: layer,
|
||||
isOverlay: isOverlay
|
||||
};
|
||||
|
||||
if (isOverlay) {
|
||||
this._layersControl.addOverlay(layer, layerName);
|
||||
|
|
@ -118,17 +128,20 @@ BR.Layers = L.Class.extend({
|
|||
this._sync();
|
||||
return layer;
|
||||
} catch (e) {
|
||||
console.warn("Oops:", e);
|
||||
return
|
||||
console.warn('Oops:', e);
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
_sync: function() {
|
||||
if (BR.Util.localStorageAvailable()) {
|
||||
localStorage.setItem("map/customLayers", JSON.stringify(this._customLayers, function(k, v) {
|
||||
localStorage.setItem(
|
||||
'map/customLayers',
|
||||
JSON.stringify(this._customLayers, function(k, v) {
|
||||
// dont write Leaflet.Layer in localStorage; simply keep the URL
|
||||
return v._url || v;
|
||||
}));
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
484
js/control/LayersTab.js
Normal file
484
js/control/LayersTab.js
Normal file
|
|
@ -0,0 +1,484 @@
|
|||
BR.LayersTab = BR.ControlLayers.extend({
|
||||
previewLayer: null,
|
||||
previewBounds: null,
|
||||
saveLayers: [],
|
||||
|
||||
initialize: function(layersConfig, baseLayers, overlays, options) {
|
||||
L.Control.Layers.prototype.initialize.call(
|
||||
this,
|
||||
baseLayers,
|
||||
overlays,
|
||||
options
|
||||
);
|
||||
|
||||
this.layersConfig = layersConfig;
|
||||
},
|
||||
|
||||
addTo: function(map) {
|
||||
this._map = map;
|
||||
this.onAdd(map);
|
||||
|
||||
L.DomUtil.get('layers-control-wrapper').appendChild(this._section);
|
||||
|
||||
this.initOpacitySlider(map);
|
||||
this.initButtons();
|
||||
this.initJsTree();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
onAdd: function(map) {
|
||||
BR.ControlLayers.prototype.onAdd.call(this, map);
|
||||
|
||||
map.on(
|
||||
'baselayerchange overlayadd overlayremove',
|
||||
this.storeActiveLayers,
|
||||
this
|
||||
);
|
||||
},
|
||||
|
||||
onRemove: function(map) {
|
||||
BR.ControlLayers.prototype.onRemove.call(this, map);
|
||||
|
||||
map.off(
|
||||
'baselayerchange overlayadd overlayremove',
|
||||
this.storeActiveLayers,
|
||||
this
|
||||
);
|
||||
},
|
||||
|
||||
initOpacitySlider: function(map) {
|
||||
var self = this;
|
||||
var overlayOpacitySlider = new BR.OpacitySlider({
|
||||
id: 'overlay',
|
||||
reversed: false,
|
||||
orientation: 'horizontal',
|
||||
defaultValue: 1,
|
||||
title: i18next.t('layers.opacity-slider'),
|
||||
callback: function(opacity) {
|
||||
for (var i = 0; i < self._layers.length; i++) {
|
||||
if (
|
||||
!self._layers[i].overlay ||
|
||||
!map.hasLayer(self._layers[i].layer)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
self._layers[i].layer.setOpacity(opacity);
|
||||
}
|
||||
}
|
||||
});
|
||||
L.DomUtil.get(
|
||||
'leaflet-control-layers-overlays-opacity-slider'
|
||||
).appendChild(overlayOpacitySlider.getElement());
|
||||
},
|
||||
|
||||
initButtons: function() {
|
||||
var expandTree = function(e) {
|
||||
this.jstree.open_all();
|
||||
};
|
||||
var collapseTree = function(e) {
|
||||
this.jstree.close_all();
|
||||
};
|
||||
|
||||
var toggleOptionalLayers = function(e) {
|
||||
var button = L.DomUtil.get('optional_layers_button');
|
||||
var treeButtons = L.DomUtil.get('tree-button-group');
|
||||
var div = L.DomUtil.get('optional-layers-tree');
|
||||
|
||||
div.hidden = !div.hidden;
|
||||
treeButtons.hidden = !treeButtons.hidden;
|
||||
button.classList.toggle('active');
|
||||
|
||||
if (div.hidden) {
|
||||
this.deselectNode();
|
||||
}
|
||||
};
|
||||
|
||||
L.DomUtil.get('expand_tree_button').onclick = L.bind(expandTree, this);
|
||||
L.DomUtil.get('collapse_tree_button').onclick = L.bind(
|
||||
collapseTree,
|
||||
this
|
||||
);
|
||||
|
||||
L.DomUtil.get('optional_layers_button').onclick = L.bind(
|
||||
toggleOptionalLayers,
|
||||
this
|
||||
);
|
||||
},
|
||||
|
||||
initJsTree: function() {
|
||||
var layerIndex = BR.layerIndex;
|
||||
var treeData = this.toJsTree(BR.confLayers.tree);
|
||||
var oldSelected = null;
|
||||
|
||||
var onSelectNode = function(e, data) {
|
||||
var layerData = layerIndex[data.node.id];
|
||||
var selected = data.selected[0];
|
||||
|
||||
if (selected !== oldSelected) {
|
||||
this.showPreview(layerData);
|
||||
oldSelected = selected;
|
||||
} else {
|
||||
data.instance.deselect_node(data.node);
|
||||
}
|
||||
};
|
||||
|
||||
var onDeselectNode = function(e, data) {
|
||||
this.hidePreview();
|
||||
oldSelected = null;
|
||||
};
|
||||
|
||||
var onCheckNode = function(e, data) {
|
||||
var layerData = layerIndex[data.node.id];
|
||||
var layer = this.createLayer(layerData);
|
||||
var name = layerData.properties.name;
|
||||
var overlay = layerData.properties.overlay;
|
||||
|
||||
if (overlay) {
|
||||
this.addOverlay(layer, name);
|
||||
} else {
|
||||
this.addBaseLayer(layer, name);
|
||||
}
|
||||
|
||||
this.storeDefaultLayers();
|
||||
};
|
||||
|
||||
var onUncheckNode = function(e, data) {
|
||||
var obj = this.getLayerById(data.node.id);
|
||||
if (!obj) return;
|
||||
|
||||
this.removeLayer(obj.layer);
|
||||
|
||||
if (this._map.hasLayer(obj.layer)) {
|
||||
this._map.removeLayer(obj.layer);
|
||||
if (!obj.overlay) {
|
||||
this.activateFirstLayer();
|
||||
}
|
||||
}
|
||||
|
||||
this.storeDefaultLayers();
|
||||
};
|
||||
|
||||
$('#optional-layers-tree')
|
||||
.on('select_node.jstree', L.bind(onSelectNode, this))
|
||||
.on('deselect_node.jstree', L.bind(onDeselectNode, this))
|
||||
.on('check_node.jstree', L.bind(onCheckNode, this))
|
||||
.on('uncheck_node.jstree', L.bind(onUncheckNode, this))
|
||||
.on('ready.jstree', function(e, data) {
|
||||
data.instance.open_all();
|
||||
})
|
||||
.jstree({
|
||||
plugins: ['checkbox'],
|
||||
checkbox: {
|
||||
whole_node: false,
|
||||
tie_selection: false
|
||||
},
|
||||
core: {
|
||||
multiple: false,
|
||||
themes: {
|
||||
icons: false,
|
||||
dots: false
|
||||
},
|
||||
data: treeData
|
||||
}
|
||||
});
|
||||
this.jstree = $('#optional-layers-tree').jstree(true);
|
||||
},
|
||||
|
||||
toJsTree: function(layerTree) {
|
||||
var data = {
|
||||
children: []
|
||||
};
|
||||
var self = this;
|
||||
|
||||
function createRootNode(name) {
|
||||
var rootNode = {
|
||||
text: i18next.t('sidebar.layers.category.' + name, name),
|
||||
state: {
|
||||
disabled: true
|
||||
},
|
||||
children: []
|
||||
};
|
||||
return rootNode;
|
||||
}
|
||||
|
||||
function getText(props, parent) {
|
||||
var text = '';
|
||||
var code = props.country_code || props.language_code;
|
||||
if (code && parent.text !== code) {
|
||||
text += '<span class="tree-code">' + code + '</span>';
|
||||
}
|
||||
text += props.name;
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
function createNode(id, layerData, parent) {
|
||||
var props = layerData.properties;
|
||||
var url = props.url;
|
||||
var keyObj = self.layersConfig.getKeyName(url);
|
||||
var childNode = null;
|
||||
|
||||
// when key required only add if configured
|
||||
if (!keyObj || (keyObj && BR.keys[keyObj.name])) {
|
||||
childNode = {
|
||||
id: id,
|
||||
text: getText(props, parent),
|
||||
state: {
|
||||
checked: self.layersConfig.isDefaultLayer(
|
||||
id,
|
||||
props.overlay
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
return childNode;
|
||||
}
|
||||
|
||||
function walkTree(inTree, outTree) {
|
||||
function walkObject(obj) {
|
||||
for (name in obj) {
|
||||
var value = obj[name];
|
||||
var rootNode = createRootNode(name);
|
||||
|
||||
outTree.children.push(rootNode);
|
||||
walkTree(value, rootNode);
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(inTree)) {
|
||||
for (var i = 0; i < inTree.length; i++) {
|
||||
var entry = inTree[i];
|
||||
if (typeof entry === 'object') {
|
||||
walkObject(entry);
|
||||
} else {
|
||||
var layer = BR.layerIndex[entry];
|
||||
|
||||
if (layer) {
|
||||
var childNode = createNode(entry, layer, outTree);
|
||||
if (childNode) {
|
||||
outTree.children.push(childNode);
|
||||
}
|
||||
} else {
|
||||
console.error('Layer "' + entry + '" not found');
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
walkObject(inTree);
|
||||
}
|
||||
}
|
||||
walkTree(layerTree, data);
|
||||
|
||||
return data.children;
|
||||
},
|
||||
|
||||
storeDefaultLayers: function() {
|
||||
var baseLayers = [];
|
||||
var overlays = [];
|
||||
|
||||
for (var i = 0; i < this._layers.length; i++) {
|
||||
var obj = this._layers[i];
|
||||
// id set in LayersConfig.createLayer
|
||||
var id = obj.layer.id;
|
||||
if (id) {
|
||||
if (obj.overlay) {
|
||||
overlays.push(id);
|
||||
} else {
|
||||
baseLayers.push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.layersConfig.storeDefaultLayers(baseLayers, overlays);
|
||||
},
|
||||
|
||||
createLayer: function(layerData) {
|
||||
var layer = this.layersConfig.createLayer(layerData);
|
||||
var overlay = layerData.properties.overlay;
|
||||
|
||||
// preview z-index, like in BR.ControlLayers._addLayer
|
||||
layer.options.zIndex = overlay ? this._lastZIndex + 1 : 0;
|
||||
|
||||
return layer;
|
||||
},
|
||||
|
||||
getLayerById: function(id) {
|
||||
for (var i = 0; i < this._layers.length; i++) {
|
||||
var obj = this._layers[i];
|
||||
if (obj.layer.id === id) {
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
getLayerByLegacyName: function(legacyName) {
|
||||
var obj = null;
|
||||
var id = this.layersConfig.legacyNameToIdMap[legacyName];
|
||||
|
||||
if (id) {
|
||||
obj = this.getLayerById(id);
|
||||
}
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
activateDefaultBaseLayer: function() {
|
||||
var index = BR.conf.defaultBaseLayerIndex || 0;
|
||||
var activeBaseLayer = this.getActiveBaseLayer();
|
||||
if (!activeBaseLayer) {
|
||||
this.activateBaseLayerIndex(index);
|
||||
}
|
||||
},
|
||||
|
||||
saveRemoveActiveLayers: function() {
|
||||
this.saveLayers = this.removeActiveLayers();
|
||||
},
|
||||
|
||||
restoreActiveLayers: function(overlaysOnly) {
|
||||
for (var i = 0; i < this.saveLayers.length; i++) {
|
||||
var obj = this.saveLayers[i];
|
||||
|
||||
if (!overlaysOnly || (overlaysOnly && obj.overlay)) {
|
||||
var hasLayer = !!this._getLayer(L.Util.stamp(obj.layer));
|
||||
if (hasLayer) {
|
||||
this.activateLayer(obj);
|
||||
} else if (!obj.overlay) {
|
||||
// saved base layer has been removed during preview, select first
|
||||
this.activateFirstLayer();
|
||||
}
|
||||
}
|
||||
}
|
||||
this.saveLayers = [];
|
||||
},
|
||||
|
||||
removePreviewLayer: function() {
|
||||
if (this.previewLayer && this._map.hasLayer(this.previewLayer)) {
|
||||
this._map.removeLayer(this.previewLayer);
|
||||
this.previewLayer = null;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
showPreviewBounds: function(layerData) {
|
||||
if (layerData.geometry) {
|
||||
this.previewBounds = L.geoJson(layerData.geometry, {
|
||||
// fill/mask outside of bounds polygon with Leaflet.snogylop
|
||||
invert: true,
|
||||
// reduce unmasked areas appearing due to clipping while panning and zooming out
|
||||
renderer: L.svg({ padding: 1 }),
|
||||
color: '#333',
|
||||
fillOpacity: 0.4,
|
||||
weight: 2
|
||||
}).addTo(this._map);
|
||||
}
|
||||
},
|
||||
|
||||
removePreviewBounds: function() {
|
||||
if (this.previewBounds && this._map.hasLayer(this.previewBounds)) {
|
||||
this._map.removeLayer(this.previewBounds);
|
||||
this.previewBounds = null;
|
||||
}
|
||||
},
|
||||
|
||||
deselectNode: function() {
|
||||
var selected = this.jstree.get_selected();
|
||||
if (selected.length > 0) {
|
||||
this.jstree.deselect_node(selected[0]);
|
||||
}
|
||||
},
|
||||
|
||||
onBaselayerchange: function() {
|
||||
// execute after current input click handler,
|
||||
// otherwise added overlay checkbox state doesn't update
|
||||
setTimeout(
|
||||
L.Util.bind(function() {
|
||||
this.removePreviewBounds();
|
||||
this.removePreviewLayer();
|
||||
this.restoreActiveLayers(true);
|
||||
this.deselectNode();
|
||||
}, this),
|
||||
0
|
||||
);
|
||||
},
|
||||
|
||||
showPreview: function(layerData) {
|
||||
var layer = this.createLayer(layerData);
|
||||
this._map.addLayer(layer);
|
||||
this.removePreviewBounds();
|
||||
if (!this.removePreviewLayer()) {
|
||||
this.saveRemoveActiveLayers();
|
||||
this._map.once('baselayerchange', this.onBaselayerchange, this);
|
||||
}
|
||||
this.previewLayer = layer;
|
||||
|
||||
this.showPreviewBounds(layerData);
|
||||
},
|
||||
|
||||
hidePreview: function(layer) {
|
||||
this._map.off('baselayerchange', this.onBaselayerchange, this);
|
||||
this.removePreviewBounds();
|
||||
this.removePreviewLayer();
|
||||
this.restoreActiveLayers();
|
||||
},
|
||||
|
||||
toLayerString: function(obj) {
|
||||
return obj.layer.id ? obj.layer.id : obj.name;
|
||||
},
|
||||
|
||||
getLayerFromString: function(layerString) {
|
||||
var obj = this.getLayerById(layerString);
|
||||
|
||||
if (!obj) {
|
||||
// fallback to name for custom and config layers
|
||||
obj = this.getLayer(layerString);
|
||||
|
||||
if (!obj) {
|
||||
// legacy layer name support
|
||||
obj = this.getLayerByLegacyName(layerString);
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
storeActiveLayers: function() {
|
||||
if (BR.Util.localStorageAvailable()) {
|
||||
var objList = this.getActiveLayers();
|
||||
var idList = objList.map(
|
||||
L.bind(function(obj) {
|
||||
return this.toLayerString(obj);
|
||||
}, this)
|
||||
);
|
||||
var str = JSON.stringify(idList);
|
||||
|
||||
localStorage.setItem('map/activeLayers', str);
|
||||
}
|
||||
},
|
||||
|
||||
loadActiveLayers: function() {
|
||||
if (BR.Util.localStorageAvailable()) {
|
||||
var item = localStorage.getItem('map/activeLayers');
|
||||
|
||||
if (item) {
|
||||
var idList = JSON.parse(item);
|
||||
|
||||
for (var i = 0; i < idList.length; i++) {
|
||||
var id = idList[i];
|
||||
var obj = this.getLayerFromString(id);
|
||||
|
||||
if (obj) {
|
||||
this.activateLayer(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
BR.layersTab = function(baseLayers, overlays, options) {
|
||||
return new BR.LayersTab(baseLayers, overlays, options);
|
||||
};
|
||||
|
|
@ -5,39 +5,51 @@ BR.Message = L.Class.extend({
|
|||
alert: false
|
||||
},
|
||||
|
||||
initialize: function (id, options) {
|
||||
initialize: function(id, options) {
|
||||
L.setOptions(this, options);
|
||||
this.id = id;
|
||||
},
|
||||
|
||||
_show: function (msg, type) {
|
||||
_show: function(msg, type) {
|
||||
var ele = L.DomUtil.get(this.id),
|
||||
iconClass = (type === 'warning') ? 'fa-exclamation-triangle' : 'fa-times-circle',
|
||||
alertClass = (type === 'warning') ? 'alert-warning' : 'alert-danger';
|
||||
iconClass =
|
||||
type === 'warning'
|
||||
? 'fa-exclamation-triangle'
|
||||
: 'fa-times-circle',
|
||||
alertClass = type === 'warning' ? 'alert-warning' : 'alert-danger';
|
||||
|
||||
L.DomEvent.disableClickPropagation(ele);
|
||||
|
||||
ele.innerHTML =
|
||||
'<div class="alert ' + alertClass + ' alert-dismissible fade in" role="alert">'
|
||||
+ ' <button type="button" class="close" data-dismiss="alert" aria-label="Close">'
|
||||
+ ' <span aria-hidden="true">×</span>'
|
||||
+ ' </button>'
|
||||
+ ' <span class="fa ' + iconClass + '" aria-hidden="true"/></span>'
|
||||
+ msg
|
||||
+ '</div>';
|
||||
'<div class="alert ' +
|
||||
alertClass +
|
||||
' alert-dismissible fade show" role="alert">' +
|
||||
' <button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
|
||||
' <span aria-hidden="true">×</span>' +
|
||||
' </button>' +
|
||||
' <span class="fa ' +
|
||||
iconClass +
|
||||
'" aria-hidden="true"/></span>' +
|
||||
msg +
|
||||
'</div>';
|
||||
|
||||
if (this.options.alert) {
|
||||
$('#' + this.id + ' .alert').alert();
|
||||
}
|
||||
},
|
||||
|
||||
hide: function () {
|
||||
hide: function() {
|
||||
$('#' + this.id + ' .alert').alert('close');
|
||||
},
|
||||
|
||||
showError: function (err) {
|
||||
showError: function(err) {
|
||||
if (err == 'Error: target island detected for section 0\n') {
|
||||
err = i18next.t('warning.no-route-found');
|
||||
}
|
||||
this._show(err, 'error');
|
||||
},
|
||||
|
||||
showWarning: function (msg) {
|
||||
showWarning: function(msg) {
|
||||
this._show(msg, 'warning');
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,67 +1,58 @@
|
|||
BR.OpacitySlider = L.Control.extend({
|
||||
BR.OpacitySlider = L.Class.extend({
|
||||
options: {
|
||||
position: 'topleft',
|
||||
id: '',
|
||||
reversed: true,
|
||||
orientation: 'vertical',
|
||||
defaultValue: BR.conf.defaultOpacity,
|
||||
title: '',
|
||||
callback: function(opacity) {}
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
var container = L.DomUtil.create('div', 'leaflet-bar control-slider'),
|
||||
input = $('<input id="slider" type="text"/>'),
|
||||
item = BR.Util.localStorageAvailable() ? localStorage.opacitySliderValue : null,
|
||||
value = item ? parseInt(item) : BR.conf.defaultOpacity * 100,
|
||||
initialize: function(options) {
|
||||
L.setOptions(this, options);
|
||||
|
||||
var input = (this.input = $(
|
||||
'<input id="slider-' + this.options.id + '" type="text"/>'
|
||||
)),
|
||||
item = BR.Util.localStorageAvailable()
|
||||
? localStorage['opacitySliderValue' + this.options.id]
|
||||
: null,
|
||||
value = item ? parseInt(item) : this.options.defaultValue * 100,
|
||||
minOpacity = (BR.conf.minOpacity || 0) * 100;
|
||||
|
||||
if (value < minOpacity) {
|
||||
value = minOpacity;
|
||||
}
|
||||
|
||||
// prevent also dragging map in Chrome
|
||||
L.DomEvent.disableClickPropagation(container);
|
||||
|
||||
var stopClickAfterSlide = function(evt) {
|
||||
L.DomEvent.stop(evt);
|
||||
removeStopClickListeners();
|
||||
};
|
||||
var removeStopClickListeners = function() {
|
||||
document.removeEventListener('click', stopClickAfterSlide, true);
|
||||
document.removeEventListener('mousedown', removeStopClickListeners, true);
|
||||
};
|
||||
|
||||
$(container).html(input);
|
||||
$(container).attr('title', 'Set transparency of route track and markers');
|
||||
|
||||
input.slider({
|
||||
input
|
||||
.slider({
|
||||
id: this.options.id,
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 1,
|
||||
value: value,
|
||||
orientation: 'vertical',
|
||||
reversed : true,
|
||||
selection: 'before', // inverted, serves as track style, see css
|
||||
orientation: this.options.orientation,
|
||||
reversed: this.options.reversed,
|
||||
selection: this.options.reversed ? 'before' : 'after', // inverted, serves as track style, see css
|
||||
tooltip: 'hide'
|
||||
}).on('slideStart', function (evt) {
|
||||
// dragging beyond slider control selects zoom control +/- text in Firefox
|
||||
L.DomUtil.disableTextSelection();
|
||||
}).on('slide slideStop', { self: this }, function (evt) {
|
||||
})
|
||||
.on('slide slideStop', { self: this }, function(evt) {
|
||||
evt.data.self.options.callback(evt.value / 100);
|
||||
}).on('slideStop', function (evt) {
|
||||
})
|
||||
.on('slideStop', { self: this }, function(evt) {
|
||||
if (BR.Util.localStorageAvailable()) {
|
||||
localStorage.opacitySliderValue = evt.value;
|
||||
localStorage[
|
||||
'opacitySliderValue' + evt.data.self.options.id
|
||||
] = evt.value;
|
||||
}
|
||||
|
||||
L.DomUtil.enableTextSelection();
|
||||
|
||||
// When dragging outside slider and over map, click event after mouseup
|
||||
// adds marker when active on Chromium. So disable click (not needed)
|
||||
// once after sliding.
|
||||
document.addEventListener('click', stopClickAfterSlide, true);
|
||||
// Firefox does not fire click event in this case, so make sure stop listener
|
||||
// is always removed on next mousedown.
|
||||
document.addEventListener('mousedown', removeStopClickListeners, true);
|
||||
});
|
||||
|
||||
this.options.callback(value / 100);
|
||||
this.getElement().title = this.options.title;
|
||||
|
||||
return container;
|
||||
this.options.callback(value / 100);
|
||||
},
|
||||
|
||||
getElement: function() {
|
||||
return this.input.slider('getElement');
|
||||
}
|
||||
});
|
||||
|
|
|
|||
64
js/control/OpacitySliderControl.js
Normal file
64
js/control/OpacitySliderControl.js
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
BR.OpacitySliderControl = L.Control.extend({
|
||||
options: {
|
||||
position: 'topleft'
|
||||
},
|
||||
|
||||
onAdd: function(map) {
|
||||
var container = L.DomUtil.create('div', 'leaflet-bar control-slider');
|
||||
|
||||
// prevent also dragging map in Chrome
|
||||
L.DomEvent.disableClickPropagation(container);
|
||||
|
||||
// migrate legacy value
|
||||
if (BR.Util.localStorageAvailable()) {
|
||||
var value = localStorage.getItem('opacitySliderValue');
|
||||
if (value !== null) {
|
||||
localStorage.setItem(
|
||||
'opacitySliderValue' + this.options.id,
|
||||
value
|
||||
);
|
||||
localStorage.removeItem('opacitySliderValue');
|
||||
}
|
||||
}
|
||||
|
||||
var slider = new BR.OpacitySlider(this.options);
|
||||
container.appendChild(slider.getElement());
|
||||
|
||||
var stopClickAfterSlide = function(evt) {
|
||||
L.DomEvent.stop(evt);
|
||||
removeStopClickListeners();
|
||||
};
|
||||
|
||||
var removeStopClickListeners = function() {
|
||||
document.removeEventListener('click', stopClickAfterSlide, true);
|
||||
document.removeEventListener(
|
||||
'mousedown',
|
||||
removeStopClickListeners,
|
||||
true
|
||||
);
|
||||
};
|
||||
|
||||
slider.input
|
||||
.on('slideStart', function(evt) {
|
||||
// dragging beyond slider control selects zoom control +/- text in Firefox
|
||||
L.DomUtil.disableTextSelection();
|
||||
})
|
||||
.on('slideStop', { self: this }, function(evt) {
|
||||
L.DomUtil.enableTextSelection();
|
||||
|
||||
// When dragging outside slider and over map, click event after mouseup
|
||||
// adds marker when active on Chromium. So disable click (not needed)
|
||||
// once after sliding.
|
||||
document.addEventListener('click', stopClickAfterSlide, true);
|
||||
// Firefox does not fire click event in this case, so make sure stop listener
|
||||
// is always removed on next mousedown.
|
||||
document.addEventListener(
|
||||
'mousedown',
|
||||
removeStopClickListeners,
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
return container;
|
||||
}
|
||||
});
|
||||
|
|
@ -1,11 +1,15 @@
|
|||
BR.Profile = L.Class.extend({
|
||||
BR.Profile = L.Evented.extend({
|
||||
cache: {},
|
||||
|
||||
initialize: function () {
|
||||
initialize: function() {
|
||||
var textArea = L.DomUtil.get('profile_upload');
|
||||
this.editor = CodeMirror.fromTextArea(textArea, {
|
||||
lineNumbers: true
|
||||
});
|
||||
|
||||
L.DomUtil.get('upload').onclick = L.bind(this._upload, this);
|
||||
L.DomUtil.get('clear').onclick = L.bind(this.clear, this);
|
||||
this.ele = L.DomUtil.get('profile_upload');
|
||||
autosize(this.ele);
|
||||
|
||||
this.message = new BR.Message('profile_message', {
|
||||
alert: true
|
||||
});
|
||||
|
|
@ -15,9 +19,7 @@ BR.Profile = L.Class.extend({
|
|||
var button = evt.target || evt.srcElement;
|
||||
|
||||
evt.preventDefault();
|
||||
this.ele.value = null;
|
||||
this.ele.defaultValue = null;
|
||||
autosize.update(this.ele);
|
||||
this._setValue('');
|
||||
|
||||
this.fire('clear');
|
||||
button.blur();
|
||||
|
|
@ -26,39 +28,54 @@ BR.Profile = L.Class.extend({
|
|||
update: function(options) {
|
||||
var profileName = options.profile,
|
||||
profileUrl,
|
||||
ele = this.ele,
|
||||
dirty = ele.defaultValue !== ele.value;
|
||||
empty = !this.editor.getValue(),
|
||||
clean = this.editor.isClean();
|
||||
|
||||
this.profileName = profileName;
|
||||
if (profileName && BR.conf.profilesUrl && (!ele.value || !dirty)) {
|
||||
if (profileName && BR.conf.profilesUrl && (empty || clean)) {
|
||||
if (!(profileName in this.cache)) {
|
||||
profileUrl = BR.conf.profilesUrl + profileName + '.brf';
|
||||
BR.Util.get(profileUrl, L.bind(function(err, profileText) {
|
||||
BR.Util.get(
|
||||
profileUrl,
|
||||
L.bind(function(err, profileText) {
|
||||
if (err) {
|
||||
console.warn('Error getting profile from "' + profileUrl + '": ' + err);
|
||||
console.warn(
|
||||
'Error getting profile from "' +
|
||||
profileUrl +
|
||||
'": ' +
|
||||
err
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.cache[profileName] = profileText;
|
||||
|
||||
// don't set when option has changed while loading
|
||||
if (!this.profileName || this.profileName === profileName) {
|
||||
ele.value = profileText;
|
||||
ele.defaultValue = ele.value;
|
||||
autosize.update(this.ele);
|
||||
if (
|
||||
!this.profileName ||
|
||||
this.profileName === profileName
|
||||
) {
|
||||
this._setValue(profileText);
|
||||
}
|
||||
}, this));
|
||||
}, this)
|
||||
);
|
||||
} else {
|
||||
ele.value = this.cache[profileName];
|
||||
ele.defaultValue = ele.value;
|
||||
autosize.update(this.ele);
|
||||
this._setValue(this.cache[profileName]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
show: function() {
|
||||
this.editor.refresh();
|
||||
},
|
||||
|
||||
onResize: function() {
|
||||
this.editor.refresh();
|
||||
},
|
||||
|
||||
_upload: function(evt) {
|
||||
var button = evt.target || evt.srcElement,
|
||||
profile = this.ele.value;
|
||||
profile = this.editor.getValue();
|
||||
|
||||
this.message.hide();
|
||||
$(button).button('uploading');
|
||||
|
|
@ -66,12 +83,15 @@ BR.Profile = L.Class.extend({
|
|||
|
||||
this.fire('update', {
|
||||
profileText: profile,
|
||||
callback: function () {
|
||||
callback: function() {
|
||||
$(button).button('reset');
|
||||
$(button).blur();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_setValue: function(profileText) {
|
||||
this.editor.setValue(profileText);
|
||||
this.editor.markClean();
|
||||
}
|
||||
});
|
||||
|
||||
BR.Profile.include(L.Mixin.Events);
|
||||
|
|
|
|||
|
|
@ -1,43 +1,45 @@
|
|||
BR.RoutingOptions = BR.Control.extend({
|
||||
|
||||
onAdd: function (map) {
|
||||
$('#profile-alternative').on('changed.bs.select', this._getChangeHandler());
|
||||
BR.RoutingOptions = L.Evented.extend({
|
||||
initialize: function() {
|
||||
$('#profile-alternative').on(
|
||||
'changed.bs.select',
|
||||
this._getChangeHandler()
|
||||
);
|
||||
|
||||
// build option list from config
|
||||
var profiles = BR.conf.profiles;
|
||||
var profiles_list = L.DomUtil.get('profile');
|
||||
for (var i = 0; i < profiles.length; i++) {
|
||||
var option = document.createElement("option");
|
||||
var option = document.createElement('option');
|
||||
option.value = profiles[i];
|
||||
option.text = profiles[i];
|
||||
option.text = i18next.t('navbar.profile.' + profiles[i]);
|
||||
profiles_list.appendChild(option);
|
||||
}
|
||||
// set default value, used as indicator for empty custom profile
|
||||
profiles_list.children[0].value = 'Custom';
|
||||
// <custom> profile is empty at start, select next one
|
||||
profiles_list.children[1].selected = true;
|
||||
return BR.Control.prototype.onAdd.call(this, map);
|
||||
},
|
||||
|
||||
refreshUI: function() {
|
||||
var profile = $('#profile option:selected'),
|
||||
alternative = $('#alternative option:selected');
|
||||
|
||||
$('#stat-profile').html(profile.text() + ' (' + alternative.text() +')');
|
||||
|
||||
// we do not allow to select more than one profile and/or alternative at a time
|
||||
// so we disable the current selected items
|
||||
$('#profile-alternative').find('option:disabled').each(function(index) {
|
||||
$('#profile-alternative')
|
||||
.find('option:disabled')
|
||||
.each(function(index) {
|
||||
$(this).prop('disabled', false);
|
||||
});
|
||||
$('#profile-alternative').find('option:selected').each(function(index) {
|
||||
$('#profile-alternative')
|
||||
.find('option:selected')
|
||||
.each(function(index) {
|
||||
$(this).prop('disabled', true);
|
||||
});
|
||||
|
||||
// disable custom option if it has no value yet (default value is "Custom")
|
||||
var custom = L.DomUtil.get('profile').children[0];
|
||||
if (custom.value === "Custom") {
|
||||
if (custom.value === 'Custom') {
|
||||
custom.disabled = true;
|
||||
}
|
||||
$('.selectpicker').selectpicker('refresh')
|
||||
$('.selectpicker').selectpicker('refresh');
|
||||
},
|
||||
|
||||
getOptions: function() {
|
||||
|
|
@ -53,8 +55,12 @@ BR.RoutingOptions = BR.Control.extend({
|
|||
|
||||
setOptions: function(options) {
|
||||
var values = [
|
||||
options.profile ? options.profile : $('#profile option:selected').val(),
|
||||
options.alternative ? options.alternative : $('#alternative option:selected').val()
|
||||
options.profile
|
||||
? options.profile
|
||||
: $('#profile option:selected').val(),
|
||||
options.alternative
|
||||
? options.alternative
|
||||
: $('#alternative option:selected').val()
|
||||
];
|
||||
$('.selectpicker').selectpicker('val', values);
|
||||
this.refreshUI();
|
||||
|
|
@ -68,22 +74,28 @@ BR.RoutingOptions = BR.Control.extend({
|
|||
},
|
||||
|
||||
setCustomProfile: function(profile, noUpdate) {
|
||||
var profiles_grp,
|
||||
option;
|
||||
var profiles_grp, option;
|
||||
|
||||
profiles_grp = L.DomUtil.get('profile');
|
||||
option = profiles_grp.children[0]
|
||||
option.value = profile;
|
||||
option = profiles_grp.children[0];
|
||||
option.value = profile || 'Custom';
|
||||
option.disabled = !profile;
|
||||
|
||||
$('#profile').find('option:selected').each(function(index) {
|
||||
if (profile) {
|
||||
$('#profile')
|
||||
.find('option:selected')
|
||||
.each(function(index) {
|
||||
$(this).prop('selected', false);
|
||||
});
|
||||
} else if (option.selected) {
|
||||
// clear, select next in group when custom deselected
|
||||
profiles_grp.children[1].selected = true;
|
||||
}
|
||||
|
||||
option.selected = !!profile;
|
||||
|
||||
if (!noUpdate) {
|
||||
this.fire('update', {options: this.getOptions()});
|
||||
this.fire('update', { options: this.getOptions() });
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -92,7 +104,7 @@ BR.RoutingOptions = BR.Control.extend({
|
|||
option = profiles_grp.children[0],
|
||||
profile = null;
|
||||
|
||||
if (!option.disabled) {
|
||||
if (option.value !== 'Custom') {
|
||||
profile = option.value;
|
||||
}
|
||||
return profile;
|
||||
|
|
@ -100,9 +112,7 @@ BR.RoutingOptions = BR.Control.extend({
|
|||
|
||||
_getChangeHandler: function() {
|
||||
return L.bind(function(evt) {
|
||||
this.fire('update', {options: this.getOptions()});
|
||||
this.fire('update', { options: this.getOptions() });
|
||||
}, this);
|
||||
}
|
||||
});
|
||||
|
||||
BR.RoutingOptions.include(L.Mixin.Events);
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
BR.Tabs = BR.Control.extend({
|
||||
options: {
|
||||
divId: 'sidebar',
|
||||
// tab a.hash > instance
|
||||
tabs: {}
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
L.setOptions(this, options);
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
var tabs = this.options.tabs;
|
||||
|
||||
for (var key in tabs) {
|
||||
$('<li><a href="' + key + '" role="tab">' + tabs[key].options.heading + '</a></li>').appendTo('#tab');
|
||||
|
||||
if (tabs[key].onAdd) {
|
||||
tabs[key].onAdd(map);
|
||||
}
|
||||
}
|
||||
|
||||
$('#tab a').click(function (e) {
|
||||
e.preventDefault();
|
||||
$(this).tab('show');
|
||||
});
|
||||
|
||||
// e.target = activated tab
|
||||
// e.relatedTarget = previous tab
|
||||
$('#tab a').on('shown.bs.tab', L.bind(function (e) {
|
||||
var tab = this.options.tabs[e.target.hash],
|
||||
prevTab = e.relatedTarget ? this.options.tabs[e.relatedTarget.hash] : null;
|
||||
|
||||
if (tab && tab.show) {
|
||||
tab.show();
|
||||
}
|
||||
if (prevTab && prevTab.hide) {
|
||||
prevTab.hide();
|
||||
}
|
||||
}, this));
|
||||
|
||||
// activate first tab (instead of setting 'active' class in html)
|
||||
$('#tab li:not(.hidden) a:first').tab('show');
|
||||
|
||||
return BR.Control.prototype.onAdd.call(this, map);
|
||||
}
|
||||
});
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
BR.TrackMessages = L.Class.extend({
|
||||
|
||||
options: {
|
||||
heading: 'Segment data',
|
||||
edgeStyle: {
|
||||
color: 'yellow',
|
||||
opacity: 0.8,
|
||||
|
|
@ -13,31 +11,31 @@ BR.TrackMessages = L.Class.extend({
|
|||
active: false,
|
||||
|
||||
columnOptions: {
|
||||
'Longitude': { visible: false },
|
||||
'Latitude': { visible: false },
|
||||
'Elevation': { title: 'elev.', className: 'dt-body-right' },
|
||||
'Distance': { title: 'dist.', className: 'dt-body-right' },
|
||||
'CostPerKm': { title: '$/km', className: 'dt-body-right' },
|
||||
'ElevCost': { title: 'elev$', className: 'dt-body-right' },
|
||||
'TurnCost': { title: 'turn$', className: 'dt-body-right' },
|
||||
'NodeCost': { title: 'node$', className: 'dt-body-right' },
|
||||
'InitialCost': { title: 'initial$', className: 'dt-body-right' }
|
||||
Longitude: { visible: false },
|
||||
Latitude: { visible: false },
|
||||
Elevation: { title: 'elev.', className: 'dt-body-right' },
|
||||
Distance: { title: 'dist.', className: 'dt-body-right' },
|
||||
CostPerKm: { title: '$/km', className: 'dt-body-right' },
|
||||
ElevCost: { title: 'elev$', className: 'dt-body-right' },
|
||||
TurnCost: { title: 'turn$', className: 'dt-body-right' },
|
||||
NodeCost: { title: 'node$', className: 'dt-body-right' },
|
||||
InitialCost: { title: 'initial$', className: 'dt-body-right' }
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
initialize: function(map, options) {
|
||||
L.setOptions(this, options);
|
||||
this._map = map;
|
||||
|
||||
var table = document.getElementById('datatable');
|
||||
this.tableClassName = table.className;
|
||||
this.tableParent = table.parentElement;
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
this._map = map;
|
||||
},
|
||||
|
||||
update: function (polyline, segments) {
|
||||
var i, messages, columns, headings,
|
||||
update: function(polyline, segments) {
|
||||
var i,
|
||||
messages,
|
||||
columns,
|
||||
headings,
|
||||
data = [];
|
||||
|
||||
if (!this.active) {
|
||||
|
|
@ -67,13 +65,19 @@ BR.TrackMessages = L.Class.extend({
|
|||
paging: false,
|
||||
searching: false,
|
||||
info: false,
|
||||
// flexbox workaround: without scrollY height Firefox extends to content height
|
||||
// (^= minimum height with flexbox?)
|
||||
scrollY: 50,
|
||||
scrollX: true,
|
||||
order: []
|
||||
});
|
||||
|
||||
// highlight track segment (graph edge) on row hover
|
||||
this._setEdges(polyline, segments);
|
||||
$('#datatable tbody tr').hover(L.bind(this._handleHover, this), L.bind(this._handleHoverOut, this));
|
||||
$('#datatable tbody tr').hover(
|
||||
L.bind(this._handleHover, this),
|
||||
L.bind(this._handleHoverOut, this)
|
||||
);
|
||||
},
|
||||
|
||||
show: function() {
|
||||
|
|
@ -88,9 +92,11 @@ BR.TrackMessages = L.Class.extend({
|
|||
_destroyTable: function() {
|
||||
var ele;
|
||||
|
||||
if ($.fn.DataTable.isDataTable('#datatable') ) {
|
||||
if ($.fn.DataTable.isDataTable('#datatable')) {
|
||||
// destroy option too slow on update, really remove elements with destroy method
|
||||
$('#datatable').DataTable().destroy(true);
|
||||
$('#datatable')
|
||||
.DataTable()
|
||||
.destroy(true);
|
||||
|
||||
// recreate original table element, destroy removes all
|
||||
ele = document.createElement('table');
|
||||
|
|
@ -144,7 +150,14 @@ BR.TrackMessages = L.Class.extend({
|
|||
},
|
||||
|
||||
_setEdges: function(polyline, segments) {
|
||||
var messages, segLatLngs, length, si, mi, latLng, i, segIndex,
|
||||
var messages,
|
||||
segLatLngs,
|
||||
length,
|
||||
si,
|
||||
mi,
|
||||
latLng,
|
||||
i,
|
||||
segIndex,
|
||||
baseIndex = 0;
|
||||
|
||||
// track latLngs index for end node of edge
|
||||
|
|
@ -185,7 +198,10 @@ BR.TrackMessages = L.Class.extend({
|
|||
endIndex = this._edges[row.index()],
|
||||
edgeLatLngs = trackLatLngs.slice(startIndex, endIndex + 1);
|
||||
|
||||
this._selectedEdge = L.polyline(edgeLatLngs, this.options.edgeStyle).addTo(this._map);
|
||||
this._selectedEdge = L.polyline(
|
||||
edgeLatLngs,
|
||||
this.options.edgeStyle
|
||||
).addTo(this._map);
|
||||
},
|
||||
|
||||
_handleHoverOut: function(evt) {
|
||||
|
|
@ -193,5 +209,3 @@ BR.TrackMessages = L.Class.extend({
|
|||
this._selectedEdge = null;
|
||||
}
|
||||
});
|
||||
|
||||
BR.TrackMessages.include(L.Mixin.Events);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,61 @@
|
|||
BR.TrackStats = L.Class.extend({
|
||||
update: function (polyline, segments) {
|
||||
var stats = this.calcStats(polyline, segments),
|
||||
length1 = L.Util.formatNum(stats.trackLength/1000,1),
|
||||
length3 = L.Util.formatNum(stats.trackLength/1000,3),
|
||||
meanCostFactor = stats.trackLength ? L.Util.formatNum(stats.cost / stats.trackLength, 2) : ''
|
||||
update: function(polyline, segments) {
|
||||
if (segments.length == 0) {
|
||||
$('#distance').html('-');
|
||||
$('#distance').attr('title', '');
|
||||
$('#ascend').html('-');
|
||||
$('#plainascend').html('-');
|
||||
$('#cost').html('-');
|
||||
$('#meancostfactor').html('-');
|
||||
$('#totaltime').html('-');
|
||||
$('#totalenergy').html('-');
|
||||
$('#meanenergy').html('-');
|
||||
return;
|
||||
}
|
||||
|
||||
$('#distance').html(length1 + ' <abbr title="kilometer">km</abbr>');
|
||||
$('#ascend').html(stats.filteredAscend + ' (' + stats.plainAscend +')' + ' <abbr title="meter">m</abbr>');
|
||||
$('#cost').html(stats.cost + ' (' + meanCostFactor + ')');
|
||||
var stats = this.calcStats(polyline, segments),
|
||||
length1 = L.Util.formatNum(
|
||||
stats.trackLength / 1000,
|
||||
1
|
||||
).toLocaleString(),
|
||||
length3 = L.Util.formatNum(
|
||||
stats.trackLength / 1000,
|
||||
3
|
||||
).toLocaleString(),
|
||||
formattedAscend = stats.filteredAscend.toLocaleString(),
|
||||
formattedPlainAscend = stats.plainAscend.toLocaleString(),
|
||||
formattedCost = stats.cost.toLocaleString(),
|
||||
meanCostFactor = stats.trackLength
|
||||
? L.Util.formatNum(
|
||||
stats.cost / stats.trackLength,
|
||||
2
|
||||
).toLocaleString()
|
||||
: '0',
|
||||
formattedTime =
|
||||
Math.trunc(stats.totalTime / 3600) +
|
||||
':' +
|
||||
('0' + Math.trunc((stats.totalTime % 3600) / 60)).slice(-2),
|
||||
formattedEnergy = L.Util.formatNum(
|
||||
stats.totalEnergy / 3600000,
|
||||
2
|
||||
).toLocaleString(),
|
||||
meanEnergy = stats.trackLength
|
||||
? L.Util.formatNum(
|
||||
stats.totalEnergy / 36 / stats.trackLength,
|
||||
2
|
||||
).toLocaleString()
|
||||
: '0';
|
||||
|
||||
$('#distance').html(length1);
|
||||
// alternative 3-digit format down to meters as tooltip
|
||||
$('#distance').attr('title', length3 + ' km');
|
||||
$('#ascend').html(formattedAscend);
|
||||
$('#plainascend').html(formattedPlainAscend);
|
||||
$('#cost').html(formattedCost);
|
||||
$('#meancostfactor').html(meanCostFactor);
|
||||
$('#totaltime').html(formattedTime);
|
||||
$('#totalenergy').html(formattedEnergy);
|
||||
$('#meanenergy').html(meanEnergy);
|
||||
},
|
||||
|
||||
calcStats: function(polyline, segments) {
|
||||
|
|
@ -15,6 +63,8 @@ BR.TrackStats = L.Class.extend({
|
|||
trackLength: 0,
|
||||
filteredAscend: 0,
|
||||
plainAscend: 0,
|
||||
totalTime: 0,
|
||||
totalEnergy: 0,
|
||||
cost: 0
|
||||
};
|
||||
var i, props;
|
||||
|
|
@ -24,6 +74,8 @@ BR.TrackStats = L.Class.extend({
|
|||
stats.trackLength += +props['track-length'];
|
||||
stats.filteredAscend += +props['filtered ascend'];
|
||||
stats.plainAscend += +props['plain-ascend'];
|
||||
stats.totalTime += +props['total-time'];
|
||||
stats.totalEnergy += +props['total-energy'];
|
||||
stats.cost += +props['cost'];
|
||||
}
|
||||
|
||||
|
|
|
|||
352
js/index.js
352
js/index.js
|
|
@ -5,21 +5,26 @@
|
|||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
var mapContext;
|
||||
|
||||
function verifyTouchStyle(mapContext) {
|
||||
// revert touch style (large icons) when touch screen detection is available and negative
|
||||
// see https://github.com/nrenner/brouter-web/issues/69
|
||||
if (L.Browser.touch && BR.Browser.touchScreenDetectable && !BR.Browser.touchScreen) {
|
||||
L.DomUtil.removeClass(mapContext.map.getContainer(), 'leaflet-touch');
|
||||
if (
|
||||
L.Browser.touch &&
|
||||
BR.Browser.touchScreenDetectable &&
|
||||
!BR.Browser.touchScreen
|
||||
) {
|
||||
L.DomUtil.removeClass(
|
||||
mapContext.map.getContainer(),
|
||||
'leaflet-touch'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function initApp(mapContext) {
|
||||
var map = mapContext.map,
|
||||
layersControl = mapContext.layersControl,
|
||||
mapLayers = mapContext.layers,
|
||||
search,
|
||||
router,
|
||||
routing,
|
||||
|
|
@ -28,20 +33,23 @@
|
|||
stats,
|
||||
itinerary,
|
||||
elevation,
|
||||
download,
|
||||
tabs,
|
||||
exportRoute,
|
||||
profile,
|
||||
trackMessages,
|
||||
sidebar,
|
||||
drawButton,
|
||||
deleteButton,
|
||||
deleteRouteButton,
|
||||
drawToolbar,
|
||||
urlHash,
|
||||
reverseRoute,
|
||||
saveWarningShown = false;
|
||||
|
||||
// By default bootstrap-select use glyphicons
|
||||
$('.selectpicker').selectpicker({
|
||||
iconBase: 'fa',
|
||||
tickIcon: 'fa-check'
|
||||
tickIcon: 'fa-check',
|
||||
// don't overlap with footer
|
||||
windowPadding: [0, 0, 40, 0]
|
||||
});
|
||||
|
||||
search = new BR.Search();
|
||||
|
|
@ -50,45 +58,75 @@
|
|||
router = L.bRouter(); //brouterCgi dummyRouter
|
||||
|
||||
drawButton = L.easyButton({
|
||||
states: [{
|
||||
states: [
|
||||
{
|
||||
stateName: 'deactivate-draw',
|
||||
icon: 'fa-pencil active',
|
||||
onClick: function (control) {
|
||||
onClick: function(control) {
|
||||
routing.draw(false);
|
||||
control.state('activate-draw');
|
||||
},
|
||||
title: 'Stop drawing route (ESC key)'
|
||||
}, {
|
||||
title: i18next.t('map.draw-route-stop')
|
||||
},
|
||||
{
|
||||
stateName: 'activate-draw',
|
||||
icon: 'fa-pencil',
|
||||
onClick: function (control) {
|
||||
onClick: function(control) {
|
||||
routing.draw(true);
|
||||
control.state('deactivate-draw');
|
||||
},
|
||||
title: 'Draw route (D key)'
|
||||
}]
|
||||
title: i18next.t('map.draw-route-start')
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
deleteButton = L.easyButton(
|
||||
reverseRouteButton = L.easyButton(
|
||||
'fa-random',
|
||||
function() {
|
||||
routing.reverse();
|
||||
},
|
||||
i18next.t('map.reverse-route')
|
||||
);
|
||||
|
||||
deletePointButton = L.easyButton(
|
||||
'<span><i class="fa fa-caret-left"></i><i class="fa fa-map-marker" style="margin-left: 1px; color: gray;"></i></span>',
|
||||
function() {
|
||||
routing.removeWaypoint(routing.getLast(), function(
|
||||
err,
|
||||
data
|
||||
) {});
|
||||
},
|
||||
i18next.t('map.delete-last-point')
|
||||
);
|
||||
|
||||
deleteRouteButton = L.easyButton(
|
||||
'fa-trash-o',
|
||||
function () {
|
||||
bootbox.confirm({
|
||||
function() {
|
||||
bootbox.prompt({
|
||||
size: 'small',
|
||||
message: "Delete route?",
|
||||
title: i18next.t('map.delete-route'),
|
||||
inputType: 'checkbox',
|
||||
inputOptions: [
|
||||
{
|
||||
text: i18next.t('map.delete-nogo-areas'),
|
||||
value: 'nogo'
|
||||
}
|
||||
],
|
||||
callback: function(result) {
|
||||
if (result) {
|
||||
if (result !== null) {
|
||||
routing.clear();
|
||||
if (result.length > 0 && result[0] === 'nogo') {
|
||||
nogos.clear();
|
||||
}
|
||||
onUpdate();
|
||||
urlHash.onMapMove();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
'Clear route'
|
||||
i18next.t('map.clear-route')
|
||||
);
|
||||
|
||||
drawToolbar = L.easyBar([drawButton, deleteButton]).addTo(map);
|
||||
|
||||
function updateRoute(evt) {
|
||||
router.setOptions(evt.options);
|
||||
|
||||
|
|
@ -112,6 +150,11 @@
|
|||
profile.update(evt.options);
|
||||
});
|
||||
|
||||
BR.NogoAreas.MSG_BUTTON = i18next.t('map.nogo.draw');
|
||||
BR.NogoAreas.MSG_BUTTON_CANCEL = i18next.t('map.nogo.cancel');
|
||||
BR.NogoAreas.MSG_CREATE = i18next.t('map.nogo.click-drag');
|
||||
BR.NogoAreas.MSG_DISABLED = i18next.t('map.nogo.edit');
|
||||
BR.NogoAreas.MSG_ENABLED = i18next.t('map.nogo.help');
|
||||
nogos = new BR.NogoAreas();
|
||||
nogos.on('update', updateRoute);
|
||||
|
||||
|
|
@ -121,22 +164,26 @@
|
|||
} else {
|
||||
stats = new BR.TrackStats();
|
||||
}
|
||||
download = new BR.Download();
|
||||
exportRoute = new BR.Export(router);
|
||||
elevation = new BR.Elevation();
|
||||
|
||||
profile = new BR.Profile();
|
||||
profile.on('update', function(evt) {
|
||||
BR.message.hide();
|
||||
var profileId = routingOptions.getCustomProfile();
|
||||
router.uploadProfile(profileId, evt.profileText, function(err, profileId) {
|
||||
router.uploadProfile(profileId, evt.profileText, function(
|
||||
err,
|
||||
profileId
|
||||
) {
|
||||
if (!err) {
|
||||
routingOptions.setCustomProfile(profileId, true);
|
||||
updateRoute({
|
||||
options: routingOptions.getOptions()
|
||||
});
|
||||
if (!saveWarningShown) {
|
||||
profile.message.showWarning('<strong>Note:</strong> Uploaded custom profiles are only cached temporarily on the server.'
|
||||
+ '<br/>Please save your edits to your local PC.');
|
||||
profile.message.showWarning(
|
||||
i18next.t('warning.temporary-profile')
|
||||
);
|
||||
saveWarningShown = true;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -156,7 +203,7 @@
|
|||
profile.message.hide();
|
||||
routingOptions.setCustomProfile(null);
|
||||
});
|
||||
trackMessages = new BR.TrackMessages({
|
||||
trackMessages = new BR.TrackMessages(map, {
|
||||
requestUpdate: requestUpdate
|
||||
});
|
||||
|
||||
|
|
@ -167,7 +214,9 @@
|
|||
styles: BR.conf.routingStyles
|
||||
});
|
||||
|
||||
routing.on('routing:routeWaypointEnd routing:setWaypointsEnd', function(evt) {
|
||||
routing.on('routing:routeWaypointEnd routing:setWaypointsEnd', function(
|
||||
evt
|
||||
) {
|
||||
search.clear();
|
||||
onUpdate(evt && evt.err);
|
||||
});
|
||||
|
|
@ -191,8 +240,7 @@
|
|||
var track = routing.toPolyline(),
|
||||
segments = routing.getSegments(),
|
||||
latLngs = routing.getWaypoints(),
|
||||
segmentsLayer = routing._segments,
|
||||
urls = {};
|
||||
segmentsLayer = routing._segments;
|
||||
|
||||
elevation.update(track, segmentsLayer);
|
||||
if (BR.conf.transit) {
|
||||
|
|
@ -202,54 +250,62 @@
|
|||
}
|
||||
trackMessages.update(track, segments);
|
||||
|
||||
if (latLngs.length > 1) {
|
||||
urls.gpx = router.getUrl(latLngs, 'gpx');
|
||||
urls.kml = router.getUrl(latLngs, 'kml');
|
||||
urls.geojson = router.getUrl(latLngs, 'geojson');
|
||||
urls.csv = router.getUrl(latLngs, 'csv');
|
||||
exportRoute.update(latLngs);
|
||||
}
|
||||
|
||||
download.update(urls);
|
||||
};
|
||||
|
||||
routingOptions.addTo(map);
|
||||
|
||||
routing.addTo(map);
|
||||
elevation.addBelow(map);
|
||||
|
||||
tabs = new BR.Tabs({
|
||||
tabs: {
|
||||
'#tab_itinerary': itinerary,
|
||||
'#tab_data': trackMessages
|
||||
sidebar = BR.sidebar({
|
||||
defaultTabId: BR.conf.transit ? 'tab_itinerary' : 'tab_profile',
|
||||
listeningTabs: {
|
||||
tab_profile: profile,
|
||||
tab_data: trackMessages
|
||||
}
|
||||
});
|
||||
if (!BR.conf.transit) {
|
||||
delete tabs.options.tabs['#tab_itinerary'];
|
||||
}).addTo(map);
|
||||
if (BR.conf.transit) {
|
||||
sidebar.showPanel('tab_itinerary');
|
||||
}
|
||||
map.addControl(tabs);
|
||||
|
||||
var sidebar = L.control.sidebar('sidebar', {
|
||||
position: 'left'
|
||||
});
|
||||
sidebar.id = 'sidebar-control'; //required for persistence in local storage
|
||||
map.addControl(sidebar);
|
||||
|
||||
nogos.addTo(map);
|
||||
map.addControl(new BR.OpacitySlider({
|
||||
drawToolbar = L.easyBar([
|
||||
drawButton,
|
||||
reverseRouteButton,
|
||||
nogos.getButton(),
|
||||
deletePointButton,
|
||||
deleteRouteButton
|
||||
]).addTo(map);
|
||||
nogos.preventRoutePointOnCreate(routing);
|
||||
|
||||
if (BR.keys.strava) {
|
||||
BR.stravaSegments(map, layersControl);
|
||||
}
|
||||
|
||||
map.addControl(
|
||||
new BR.OpacitySliderControl({
|
||||
id: 'route',
|
||||
title: i18next.t('map.opacity-slider'),
|
||||
callback: L.bind(routing.setOpacity, routing)
|
||||
}));
|
||||
})
|
||||
);
|
||||
|
||||
// initial option settings (after controls are added and initialized with onAdd)
|
||||
router.setOptions(nogos.getOptions());
|
||||
router.setOptions(routingOptions.getOptions());
|
||||
profile.update(routingOptions.getOptions());
|
||||
|
||||
// restore active layers from local storage when called without hash
|
||||
// (check before hash plugin init)
|
||||
if (!location.hash) {
|
||||
layersControl.loadActiveLayers();
|
||||
}
|
||||
|
||||
var onHashChangeCb = function(url) {
|
||||
var url2params = function (s) {
|
||||
var url2params = function(s) {
|
||||
s = s.replace(/;/g, '|');
|
||||
var p = {};
|
||||
var sep = '&';
|
||||
if (s.search('&') !== -1)
|
||||
sep = '&';
|
||||
if (s.search('&') !== -1) sep = '&';
|
||||
var params = s.split(sep);
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var tmp = params[i].split('=');
|
||||
|
|
@ -257,7 +313,7 @@
|
|||
p[tmp[0]] = decodeURIComponent(tmp[1]);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
};
|
||||
if (url == null) return;
|
||||
var opts = router.parseUrlParams(url2params(url));
|
||||
router.setOptions(opts);
|
||||
|
|
@ -283,35 +339,48 @@
|
|||
// do not initialize immediately
|
||||
urlHash = new L.Hash(null, null);
|
||||
urlHash.additionalCb = function() {
|
||||
var url = router.getUrl(routing.getWaypoints(), null).substr('brouter?'.length+1);
|
||||
var url = router
|
||||
.getUrl(routing.getWaypoints(), null)
|
||||
.substr('brouter?'.length + 1);
|
||||
url = url.replace(/\|/g, ';');
|
||||
return url.length > 0 ? '&' + url : null;
|
||||
};
|
||||
urlHash.onHashChangeCb = onHashChangeCb;
|
||||
urlHash.onInvalidHashChangeCb = onInvalidHashChangeCb;
|
||||
urlHash.layers = mapLayers;
|
||||
urlHash.map = map;
|
||||
urlHash.init(map, mapLayers);
|
||||
urlHash.init(map, {
|
||||
layersControl: layersControl
|
||||
});
|
||||
|
||||
// activate configured default base layer or first if no hash,
|
||||
// only after hash init, by using the same delay
|
||||
setTimeout(function() {
|
||||
layersControl.activateDefaultBaseLayer();
|
||||
}, urlHash.changeDefer);
|
||||
|
||||
routingOptions.on('update', urlHash.onMapMove, urlHash);
|
||||
nogos.on('update', urlHash.onMapMove, urlHash);
|
||||
// waypoint add, move, delete (but last)
|
||||
routing.on('routing:routeWaypointEnd', urlHash.onMapMove, urlHash);
|
||||
// delete last waypoint
|
||||
routing.on('waypoint:click', function (evt) {
|
||||
routing.on(
|
||||
'waypoint:click',
|
||||
function(evt) {
|
||||
var r = evt.marker._routing;
|
||||
if (!r.prevMarker && !r.nextMarker) {
|
||||
urlHash.onMapMove();
|
||||
}
|
||||
}, urlHash);
|
||||
},
|
||||
urlHash
|
||||
);
|
||||
|
||||
$(window).resize(function () {
|
||||
$(window).resize(function() {
|
||||
elevation.addBelow(map);
|
||||
});
|
||||
|
||||
$('#elevation-chart').on('show.bs.collapse', function () {
|
||||
$('#elevation-chart').on('show.bs.collapse', function() {
|
||||
$('#elevation-btn').addClass('active');
|
||||
});
|
||||
$('#elevation-chart').on('hidden.bs.collapse', function () {
|
||||
$('#elevation-chart').on('hidden.bs.collapse', function() {
|
||||
$('#elevation-btn').removeClass('active');
|
||||
// we must fetch tiles that are located behind elevation-chart
|
||||
map._onResize();
|
||||
|
|
@ -319,36 +388,149 @@
|
|||
|
||||
var onHide = function() {
|
||||
if (this.id && BR.Util.localStorageAvailable()) {
|
||||
localStorage[this.id] = 'true';
|
||||
localStorage.removeItem(this.id);
|
||||
}
|
||||
};
|
||||
var onShow = function() {
|
||||
if (this.id && BR.Util.localStorageAvailable()) {
|
||||
localStorage.removeItem(this.id);
|
||||
localStorage[this.id] = 'true';
|
||||
}
|
||||
};
|
||||
var toggleSidebar = function (event) {
|
||||
sidebar.toggle();
|
||||
$('#sidebar-btn').toggleClass('active');
|
||||
};
|
||||
$('#sidebar-btn').on('click', toggleSidebar);
|
||||
sidebar.on('shown', onShow);
|
||||
sidebar.on('hidden', onHide);
|
||||
// on page load, we want to restore collapsible elements from previous usage
|
||||
$('.collapse').on('hidden.bs.collapse', onHide)
|
||||
$('.collapse')
|
||||
.on('hidden.bs.collapse', onHide)
|
||||
.on('shown.bs.collapse', onShow)
|
||||
.each(function() {
|
||||
if (!(this.id && BR.Util.localStorageAvailable() && localStorage[this.id] === 'true' )) {
|
||||
$(this).collapse('hide');
|
||||
if (
|
||||
this.id &&
|
||||
BR.Util.localStorageAvailable() &&
|
||||
localStorage[this.id] === 'true'
|
||||
) {
|
||||
$(this).collapse('show');
|
||||
}
|
||||
});
|
||||
if (BR.Util.localStorageAvailable() && localStorage[sidebar.id] !== 'true') {
|
||||
toggleSidebar();
|
||||
|
||||
$('#submitNogos').on('click', function() {
|
||||
var geoJSONPromise;
|
||||
var nogoURL = $('#nogoURL').val();
|
||||
var nogoFile = $('#nogoFile')[0].files[0];
|
||||
if (nogoURL) {
|
||||
// TODO: Handle {{bbox}}
|
||||
geoJSONPromise = fetch(nogoURL).then(function(response) {
|
||||
response.json();
|
||||
});
|
||||
} else if (nogoFile) {
|
||||
geoJSONPromise = new Promise(function(resolve, reject) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function() {
|
||||
resolve(reader.result);
|
||||
};
|
||||
reader.readAsText(nogoFile);
|
||||
}).then(function(response) {
|
||||
return JSON.parse(response);
|
||||
});
|
||||
} else {
|
||||
$('#nogoError').text('Error: Missing file or URL.');
|
||||
$('#nogoError').css('display', 'block');
|
||||
return false;
|
||||
}
|
||||
var nogoWeight = parseFloat($('#nogoWeight').val());
|
||||
if (isNaN(nogoWeight)) {
|
||||
$('#nogoError').text('Error: Missing default nogo weight.');
|
||||
$('#nogoError').css('display', 'block');
|
||||
return false;
|
||||
}
|
||||
var nogoRadius = parseFloat($('#nogoRadius').val());
|
||||
if (isNaN(nogoRadius) || nogoRadius < 0) {
|
||||
$('#nogoError').text('Error: Invalid default nogo radius.');
|
||||
$('#nogoError').css('display', 'block');
|
||||
return false;
|
||||
}
|
||||
var nogoBuffer = parseFloat($('#nogoBuffer').val());
|
||||
if (isNaN(nogoBuffer)) {
|
||||
$('#nogoError').text('Error: Invalid nogo buffering radius.');
|
||||
$('#nogoError').css('display', 'block');
|
||||
return false;
|
||||
}
|
||||
|
||||
geoJSONPromise.then(function(response) {
|
||||
// Iterate on features in order to discard features without geometry
|
||||
var cleanedGeoJSONFeatures = [];
|
||||
turf.featureEach(response, function(feature) {
|
||||
if (turf.getGeom(feature)) {
|
||||
var maybeBufferedFeature = feature;
|
||||
// Eventually buffer GeoJSON
|
||||
if (nogoBuffer != 0) {
|
||||
maybeBufferedFeature = turf.buffer(
|
||||
maybeBufferedFeature,
|
||||
nogoBuffer,
|
||||
{ units: 'meters' }
|
||||
);
|
||||
}
|
||||
cleanedGeoJSONFeatures.push(maybeBufferedFeature);
|
||||
}
|
||||
});
|
||||
|
||||
var geoJSON = L.geoJson(
|
||||
turf.featureCollection(cleanedGeoJSONFeatures),
|
||||
{
|
||||
onEachFeature: function(feature, layer) {
|
||||
layer.options.nogoWeight =
|
||||
feature.properties.nogoWeight || nogoWeight;
|
||||
}
|
||||
}
|
||||
);
|
||||
var nogosPoints = geoJSON.getLayers().filter(function(e) {
|
||||
return e.feature.geometry.type === 'Point';
|
||||
});
|
||||
nogosPoints = nogosPoints.map(function(item) {
|
||||
var radius = item.feature.properties.radius || nogoRadius;
|
||||
if (radius > 0) {
|
||||
return L.circle(item.getLatLng(), { radius: radius });
|
||||
}
|
||||
return null;
|
||||
});
|
||||
nogosPoints = nogosPoints.filter(function(e) {
|
||||
return e;
|
||||
});
|
||||
nogos.setOptions({
|
||||
nogos: nogosPoints,
|
||||
polygons: geoJSON.getLayers().filter(function(e) {
|
||||
return e.feature.geometry.type === 'Polygon';
|
||||
}),
|
||||
polylines: geoJSON.getLayers().filter(function(e) {
|
||||
return e.feature.geometry.type === 'LineString';
|
||||
})
|
||||
});
|
||||
updateRoute({
|
||||
options: nogos.getOptions()
|
||||
});
|
||||
urlHash.onMapMove();
|
||||
$('#nogoError').text('');
|
||||
$('#nogoError').css('display', 'none');
|
||||
$('#loadNogos').modal('hide');
|
||||
});
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
i18next
|
||||
.use(window.i18nextXHRBackend)
|
||||
.use(window.i18nextBrowserLanguageDetector)
|
||||
.init(
|
||||
{
|
||||
fallbackLng: 'en',
|
||||
backend: {
|
||||
loadPath: 'dist/locales/{{lng}}.json'
|
||||
}
|
||||
},
|
||||
function(err, t) {
|
||||
jqueryI18next.init(i18next, $);
|
||||
$('html').localize();
|
||||
|
||||
mapContext = BR.Map.initMap();
|
||||
verifyTouchStyle(mapContext);
|
||||
initApp(mapContext);
|
||||
|
||||
}
|
||||
);
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -1,17 +1,19 @@
|
|||
BR.BingLayer = L.BingLayer.extend({
|
||||
options: {
|
||||
maxZoom: 19,
|
||||
attribution: '<a target="_blank" href="https://www.bing.com/maps/">Bing Maps</a>'
|
||||
+ ' (<a target="_blank" href="https://go.microsoft.com/?linkid=9710837">TOU</a>)'
|
||||
attribution:
|
||||
'<a target="_blank" href="https://www.bing.com/maps/">Bing Maps</a>' +
|
||||
' (<a target="_blank" href="https://go.microsoft.com/?linkid=9710837">TOU</a>)'
|
||||
},
|
||||
|
||||
initialize: function(key, options) {
|
||||
L.BingLayer.prototype.initialize.call(this, key, options);
|
||||
|
||||
this._logo = L.control({position: 'bottomleft'});
|
||||
this._logo.onAdd = function (map) {
|
||||
this._logo = L.control({ position: 'bottomleft' });
|
||||
this._logo.onAdd = function(map) {
|
||||
this._div = L.DomUtil.create('div', 'bing-logo');
|
||||
this._div.innerHTML = '<img src="https://www.microsoft.com/maps/images/branding/Bing%20logo%20white_50px-19px.png">';
|
||||
this._div.innerHTML =
|
||||
'<img src="https://www.microsoft.com/maps/images/branding/Bing%20logo%20white_50px-19px.png">';
|
||||
return this._div;
|
||||
};
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,33 +1,47 @@
|
|||
BR.Elevation = L.Control.Elevation.extend({
|
||||
options: {
|
||||
width:$('#map').outerWidth(),
|
||||
width: $('#map').outerWidth(),
|
||||
margins: {
|
||||
top: 20,
|
||||
right: 30,
|
||||
bottom: 30,
|
||||
left: 60
|
||||
},
|
||||
theme: "steelblue-theme"
|
||||
theme: 'steelblue-theme'
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
onAdd: function(map) {
|
||||
var container = L.Control.Elevation.prototype.onAdd.call(this, map);
|
||||
|
||||
// revert registering touch events when touch screen detection is available and negative
|
||||
// see https://github.com/MrMufflon/Leaflet.Elevation/issues/67
|
||||
if (L.Browser.touch && BR.Browser.touchScreenDetectable && !BR.Browser.touchScreen) {
|
||||
|
||||
this._background.on("touchmove.drag", null).
|
||||
on("touchstart.drag", null).
|
||||
on("touchstart.focus", null);
|
||||
L.DomEvent.off(this._container, 'touchend', this._dragEndHandler, this);
|
||||
|
||||
this._background.on("mousemove.focus", this._mousemoveHandler.bind(this)).
|
||||
on("mouseout.focus", this._mouseoutHandler.bind(this)).
|
||||
on("mousedown.drag", this._dragStartHandler.bind(this)).
|
||||
on("mousemove.drag", this._dragHandler.bind(this));
|
||||
L.DomEvent.on(this._container, 'mouseup', this._dragEndHandler, this);
|
||||
if (
|
||||
L.Browser.touch &&
|
||||
BR.Browser.touchScreenDetectable &&
|
||||
!BR.Browser.touchScreen
|
||||
) {
|
||||
this._background
|
||||
.on('touchmove.drag', null)
|
||||
.on('touchstart.drag', null)
|
||||
.on('touchstart.focus', null);
|
||||
L.DomEvent.off(
|
||||
this._container,
|
||||
'touchend',
|
||||
this._dragEndHandler,
|
||||
this
|
||||
);
|
||||
|
||||
this._background
|
||||
.on('mousemove.focus', this._mousemoveHandler.bind(this))
|
||||
.on('mouseout.focus', this._mouseoutHandler.bind(this))
|
||||
.on('mousedown.drag', this._dragStartHandler.bind(this))
|
||||
.on('mousemove.drag', this._dragHandler.bind(this));
|
||||
L.DomEvent.on(
|
||||
this._container,
|
||||
'mouseup',
|
||||
this._dragEndHandler,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
return container;
|
||||
|
|
@ -36,7 +50,7 @@ BR.Elevation = L.Control.Elevation.extend({
|
|||
addBelow: function(map) {
|
||||
// waiting for https://github.com/MrMufflon/Leaflet.Elevation/pull/66
|
||||
// this.width($('#map').outerWidth());
|
||||
this.options.width = $('#map').outerWidth();
|
||||
this.options.width = $('#content').outerWidth();
|
||||
|
||||
if (this.getContainer() != null) {
|
||||
this.remove(map);
|
||||
|
|
@ -47,7 +61,10 @@ BR.Elevation = L.Control.Elevation.extend({
|
|||
}
|
||||
this.addTo(map);
|
||||
// move elevation graph outside of the map
|
||||
setParent(this.getContainer(), document.getElementById('elevation-chart'));
|
||||
setParent(
|
||||
this.getContainer(),
|
||||
document.getElementById('elevation-chart')
|
||||
);
|
||||
},
|
||||
|
||||
update: function(track, layer) {
|
||||
|
|
@ -62,7 +79,7 @@ BR.Elevation = L.Control.Elevation.extend({
|
|||
if (track && track.getLatLngs().length > 0) {
|
||||
this.addData(track.toGeoJSON(), layer);
|
||||
|
||||
layer.on("mouseout", this._hidePositionMarker.bind(this));
|
||||
layer.on('mouseout', this._hidePositionMarker.bind(this));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,76 +1,504 @@
|
|||
L.drawLocal.draw.toolbar.buttons.circle = 'Draw no-go area (circle)';
|
||||
L.drawLocal.edit.toolbar.buttons.edit = 'Edit no-go areas';
|
||||
L.drawLocal.edit.toolbar.buttons.remove = 'Delete no-go areas';
|
||||
|
||||
BR.NogoAreas = L.Control.Draw.extend({
|
||||
initialize: function () {
|
||||
this.drawnItems = new L.FeatureGroup();
|
||||
|
||||
L.Control.Draw.prototype.initialize.call(this, {
|
||||
draw: {
|
||||
position: 'topleft',
|
||||
polyline: false,
|
||||
polygon: false,
|
||||
circle: true,
|
||||
rectangle: false,
|
||||
marker: false
|
||||
BR.NogoAreas = L.Control.extend({
|
||||
statics: {
|
||||
MSG_BUTTON: 'Draw no-go area (circle)',
|
||||
MSG_BUTTON_CANCEL: 'Cancel drawing no-go area',
|
||||
MSG_CREATE: 'Click and drag to draw circle',
|
||||
MSG_DISABLED: 'Click to edit',
|
||||
MSG_ENABLED:
|
||||
'□ = move / resize, <span class="fa fa-trash-o"></span> = delete,<br>click nogo to quit editing',
|
||||
STATE_CREATE: 'no-go-create',
|
||||
STATE_CANCEL: 'cancel-no-go-create'
|
||||
},
|
||||
edit: {
|
||||
featureGroup: this.drawnItems,
|
||||
//edit: false,
|
||||
edit: {
|
||||
selectedPathOptions: {
|
||||
//opacity: 0.8
|
||||
}
|
||||
|
||||
style: {
|
||||
color: '#f06eaa',
|
||||
weight: 4,
|
||||
opacity: 0.5,
|
||||
fillColor: null, //same as color by default
|
||||
fillOpacity: 0.2,
|
||||
dashArray: null
|
||||
},
|
||||
remove: true
|
||||
}
|
||||
|
||||
editStyle: {
|
||||
color: '#fe57a1',
|
||||
opacity: 0.6,
|
||||
dashArray: '10, 10',
|
||||
fillOpacity: 0.1
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
this._wasRouteDrawing = false;
|
||||
},
|
||||
|
||||
onAdd: function(map) {
|
||||
var self = this;
|
||||
|
||||
this.drawnItems = new L.FeatureGroup().addTo(map);
|
||||
this.drawnItems.on('click', function(e) {
|
||||
L.DomEvent.stop(e);
|
||||
e.layer.toggleEdit();
|
||||
});
|
||||
|
||||
var editTools = (this.editTools = map.editTools = new L.Editable(map, {
|
||||
circleEditorClass: BR.DeletableCircleEditor,
|
||||
// FeatureGroup instead of LayerGroup to propagate events to members
|
||||
editLayer: new L.FeatureGroup().addTo(map),
|
||||
featuresLayer: this.drawnItems
|
||||
}));
|
||||
|
||||
this.button = L.easyButton({
|
||||
states: [
|
||||
{
|
||||
stateName: BR.NogoAreas.STATE_CREATE,
|
||||
icon: 'fa-ban',
|
||||
title: BR.NogoAreas.MSG_BUTTON,
|
||||
onClick: function(control) {
|
||||
// initial radius of 0 to detect click, see DeletableCircleEditor.onDrawingMouseUp
|
||||
var opts = L.extend({ radius: 0 }, self.style);
|
||||
editTools.startCircle(null, opts);
|
||||
|
||||
control.state('cancel-no-go-create');
|
||||
}
|
||||
},
|
||||
{
|
||||
stateName: BR.NogoAreas.STATE_CANCEL,
|
||||
icon: 'fa-ban active',
|
||||
title: BR.NogoAreas.MSG_BUTTON_CANCEL,
|
||||
onClick: function(control) {
|
||||
editTools.stopDrawing();
|
||||
control.state('no-go-create');
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
this.editTools.on(
|
||||
'editable:drawing:end',
|
||||
function(e) {
|
||||
self.button.state(BR.NogoAreas.STATE_CREATE);
|
||||
|
||||
setTimeout(
|
||||
L.bind(function() {
|
||||
// turn editing off after create; async to still fire 'editable:vertex:dragend'
|
||||
e.layer.disableEdit();
|
||||
}, this),
|
||||
0
|
||||
);
|
||||
},
|
||||
this
|
||||
);
|
||||
|
||||
this.editTools.on(
|
||||
'editable:vertex:dragend editable:deleted',
|
||||
function(e) {
|
||||
this._fireUpdate();
|
||||
},
|
||||
this
|
||||
);
|
||||
|
||||
this.editTools.on(
|
||||
'editable:enable',
|
||||
function(e) {
|
||||
e.layer.setStyle(this.editStyle);
|
||||
},
|
||||
this
|
||||
);
|
||||
this.editTools.on(
|
||||
'editable:disable',
|
||||
function(e) {
|
||||
e.layer.setStyle(this.style);
|
||||
},
|
||||
this
|
||||
);
|
||||
|
||||
this.tooltip = new BR.EditingTooltip(map, editTools, this.button);
|
||||
this.tooltip.enable();
|
||||
|
||||
// dummy, no own representation, delegating to EasyButton
|
||||
return L.DomUtil.create('div');
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
map.addLayer(this.drawnItems);
|
||||
// prevent route waypoint added after circle create (map click after up)
|
||||
preventRoutePointOnCreate: function(routing) {
|
||||
this.editTools.on(
|
||||
'editable:drawing:start',
|
||||
function(e) {
|
||||
this._wasRouteDrawing = routing.isDrawing();
|
||||
routing.draw(false);
|
||||
},
|
||||
this
|
||||
);
|
||||
|
||||
map.on('draw:created', function (e) {
|
||||
var layer = e.layer;
|
||||
this.drawnItems.addLayer(layer);
|
||||
this._fireUpdate();
|
||||
}, this);
|
||||
|
||||
map.on('draw:editstart', function (e) {
|
||||
this.drawnItems.eachLayer(function (layer) {
|
||||
layer.on('edit', function(e) {
|
||||
this._fireUpdate();
|
||||
}, this);
|
||||
}, this);
|
||||
}, this);
|
||||
|
||||
map.on('draw:deleted', function (e) {
|
||||
this._fireUpdate();
|
||||
}, this);
|
||||
|
||||
return L.Control.Draw.prototype.onAdd.call(this, map);
|
||||
// after create
|
||||
this.editTools.on(
|
||||
'editable:drawing:end',
|
||||
function(e) {
|
||||
if (this._wasRouteDrawing) {
|
||||
setTimeout(function() {
|
||||
routing.draw(true);
|
||||
}, 0);
|
||||
}
|
||||
},
|
||||
this
|
||||
);
|
||||
},
|
||||
|
||||
getOptions: function() {
|
||||
return {
|
||||
nogos: this.drawnItems.getLayers()
|
||||
nogos: this.drawnItems.getLayers().filter(function(e) {
|
||||
return e instanceof L.Circle;
|
||||
}),
|
||||
polygons: this.drawnItems.getLayers().filter(function(e) {
|
||||
return e instanceof L.Polygon;
|
||||
}),
|
||||
polylines: this.drawnItems.getLayers().filter(function(e) {
|
||||
return e instanceof L.Polyline && !(e instanceof L.Polygon);
|
||||
})
|
||||
};
|
||||
},
|
||||
|
||||
setOptions: function(options) {
|
||||
var nogos = options.nogos;
|
||||
this.drawnItems.clearLayers();
|
||||
var polylines = options.polylines;
|
||||
var polygons = options.polygons;
|
||||
this._clear();
|
||||
if (nogos) {
|
||||
for (var i = 0; i < nogos.length; i++) {
|
||||
nogos[i].setStyle(this.style);
|
||||
this.drawnItems.addLayer(nogos[i]);
|
||||
}
|
||||
}
|
||||
if (polylines) {
|
||||
for (var i = 0; i < polylines.length; i++) {
|
||||
polylines[i].setStyle(this.style);
|
||||
this.drawnItems.addLayer(polylines[i]);
|
||||
}
|
||||
}
|
||||
if (polygons) {
|
||||
for (var i = 0; i < polygons.length; i++) {
|
||||
polygons[i].setStyle(this.style);
|
||||
this.drawnItems.addLayer(polygons[i]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_fireUpdate: function () {
|
||||
this.fire('update', {options: this.getOptions()});
|
||||
_clear: function() {
|
||||
this.drawnItems.clearLayers();
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
this._clear();
|
||||
this._fireUpdate();
|
||||
},
|
||||
|
||||
_fireUpdate: function() {
|
||||
this.fire('update', { options: this.getOptions() });
|
||||
},
|
||||
|
||||
getFeatureGroup: function() {
|
||||
return this.drawnItems;
|
||||
},
|
||||
|
||||
getEditGroup: function() {
|
||||
return this.editTools.editLayer;
|
||||
},
|
||||
|
||||
getButton: function() {
|
||||
return this.button;
|
||||
}
|
||||
});
|
||||
|
||||
BR.NogoAreas.include(L.Mixin.Events);
|
||||
BR.NogoAreas.include(L.Evented.prototype);
|
||||
|
||||
L.Editable.prototype.createVertexIcon = function(options) {
|
||||
return BR.Browser.touch
|
||||
? new L.Editable.TouchVertexIcon(options)
|
||||
: new L.Editable.VertexIcon(options);
|
||||
};
|
||||
|
||||
BR.EditingTooltip = L.Handler.extend({
|
||||
options: {
|
||||
closeTimeout: 2000
|
||||
},
|
||||
|
||||
initialize: function(map, editTools, button) {
|
||||
this.map = map;
|
||||
this.editTools = editTools;
|
||||
this.button = button;
|
||||
},
|
||||
|
||||
addHooks: function() {
|
||||
// hack: listen to EasyButton click (instead of editable:drawing:start),
|
||||
// to get mouse position from event for initial tooltip location
|
||||
L.DomEvent.addListener(
|
||||
this.button.button,
|
||||
'click',
|
||||
this._addCreate,
|
||||
this
|
||||
);
|
||||
|
||||
this.editTools.featuresLayer.on('layeradd', this._bind, this);
|
||||
|
||||
this.editTools.on('editable:drawing:end', this._postCreate, this);
|
||||
this.editTools.on('editable:enable', this._enable, this);
|
||||
this.editTools.on('editable:disable', this._disable, this);
|
||||
},
|
||||
|
||||
removeHooks: function() {
|
||||
L.DomEvent.removeListener(
|
||||
this.button.button,
|
||||
'click',
|
||||
this._addCreate,
|
||||
this
|
||||
);
|
||||
|
||||
this.editTools.featuresLayer.off('layeradd', this._bind, this);
|
||||
|
||||
this.editTools.off('editable:drawing:end', this._postCreate, this);
|
||||
this.editTools.off('editable:enable', this._enable, this);
|
||||
this.editTools.off('editable:disable', this._disable, this);
|
||||
},
|
||||
|
||||
_bind: function(e) {
|
||||
// Position tooltip at bottom of circle, less distracting than
|
||||
// sticky with cursor or at center.
|
||||
|
||||
var layer = e.layer;
|
||||
layer.bindTooltip(BR.NogoAreas.MSG_DISABLED, {
|
||||
direction: 'bottom',
|
||||
className: 'editing-tooltip'
|
||||
});
|
||||
|
||||
// Override to set position to south instead of center (circle latlng);
|
||||
// works better with zooming than updating offset to match radius
|
||||
layer.openTooltip = function(layer, latlng) {
|
||||
if (!latlng && layer instanceof L.Layer) {
|
||||
latlng = L.latLng(
|
||||
layer.getBounds().getSouth(),
|
||||
0.5 *
|
||||
(layer.getBounds().getWest() +
|
||||
layer.getBounds().getEast())
|
||||
);
|
||||
}
|
||||
L.Layer.prototype.openTooltip.call(this, layer, latlng);
|
||||
};
|
||||
},
|
||||
|
||||
_addCreate: function(e) {
|
||||
// button cancel
|
||||
if (!this.editTools.drawing()) return;
|
||||
|
||||
var initialLatLng = this.map.mouseEventToLatLng(e);
|
||||
var tooltip = L.tooltip({
|
||||
// no effect with map tooltip
|
||||
sticky: true,
|
||||
// offset wrong with 'auto' when switching direction
|
||||
direction: 'right',
|
||||
offset: L.point(5, 28),
|
||||
className: 'editing-tooltip-create'
|
||||
});
|
||||
|
||||
// self-reference hack for _moveTooltip, as tooltip is not bound to layer
|
||||
tooltip._tooltip = tooltip;
|
||||
|
||||
// simulate sticky feature (follow mouse) for map tooltip without layer
|
||||
var onOffMove = function(e) {
|
||||
var onOff = e.type === 'tooltipclose' ? 'off' : 'on';
|
||||
this._map[onOff]('mousemove', this._moveTooltip, this);
|
||||
};
|
||||
this.map.on('tooltipopen', onOffMove, tooltip);
|
||||
this.map.on('tooltipclose', onOffMove, tooltip);
|
||||
|
||||
var onTooltipRemove = function(e) {
|
||||
this.map.off('tooltipopen', onOffMove, e.tooltip);
|
||||
this.map.off('tooltipclose', onOffMove, e.tooltip);
|
||||
this.map.off('tooltipclose', onTooltipRemove, this);
|
||||
e.tooltip._tooltip = null;
|
||||
};
|
||||
this.map.on('tooltipclose', onTooltipRemove, this);
|
||||
|
||||
tooltip.setTooltipContent(BR.NogoAreas.MSG_CREATE);
|
||||
this.map.openTooltip(tooltip, initialLatLng);
|
||||
|
||||
var closeTooltip = function() {
|
||||
this.map.closeTooltip(tooltip);
|
||||
};
|
||||
this.editTools.once(
|
||||
'editable:editing editable:drawing:cancel',
|
||||
closeTooltip,
|
||||
this
|
||||
);
|
||||
|
||||
if (BR.Browser.touch) {
|
||||
// can't move with cursor on touch devices, so show at start pos for a few seconds
|
||||
setTimeout(L.bind(closeTooltip, this), this.options.closeTimeout);
|
||||
}
|
||||
},
|
||||
|
||||
_setCloseTimeout: function(layer) {
|
||||
var timeoutId = setTimeout(function() {
|
||||
layer.closeTooltip();
|
||||
}, this.options.closeTimeout);
|
||||
|
||||
// prevent timer to close tooltip that changed in the meantime
|
||||
layer.once('tooltipopen', function(e) {
|
||||
clearTimeout(timeoutId);
|
||||
});
|
||||
},
|
||||
|
||||
_postCreate: function() {
|
||||
// editing is disabled by another handler, tooltip won't stay open before
|
||||
this.editTools.once(
|
||||
'editable:disable',
|
||||
function(e) {
|
||||
// show for a few seconds, as mouse often not hovering circle after create
|
||||
e.layer.openTooltip(e.layer);
|
||||
this._setCloseTimeout(e.layer);
|
||||
},
|
||||
this
|
||||
);
|
||||
},
|
||||
|
||||
_enable: function(e) {
|
||||
e.layer.setTooltipContent(BR.NogoAreas.MSG_ENABLED);
|
||||
|
||||
this.editTools.once(
|
||||
'editable:editing',
|
||||
function(e) {
|
||||
e.layer.closeTooltip();
|
||||
},
|
||||
this
|
||||
);
|
||||
},
|
||||
|
||||
_disable: function(e) {
|
||||
e.layer.setTooltipContent(BR.NogoAreas.MSG_DISABLED);
|
||||
this._setCloseTimeout(e.layer);
|
||||
}
|
||||
});
|
||||
|
||||
BR.DeletableCircleEditor = L.Editable.CircleEditor.extend({
|
||||
_computeDeleteLatLng: function() {
|
||||
// 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),
|
||||
point = this.map.project(this.feature._latlng);
|
||||
return this.map.unproject([point.x - delta, point.y - delta]);
|
||||
},
|
||||
|
||||
_updateDeleteLatLng: function() {
|
||||
this._deleteLatLng.update(this._computeDeleteLatLng());
|
||||
this._deleteLatLng.__vertex.update();
|
||||
},
|
||||
|
||||
_addDeleteMarker: function() {
|
||||
if (!this.enabled()) return;
|
||||
this._deleteLatLng = this._computeDeleteLatLng();
|
||||
return new BR.DeleteMarker(this._deleteLatLng, this);
|
||||
},
|
||||
|
||||
_delete: function() {
|
||||
this.disable();
|
||||
this.tools.featuresLayer.removeLayer(this.feature);
|
||||
},
|
||||
|
||||
delete: function() {
|
||||
this._delete();
|
||||
this.fireAndForward('editable:deleted');
|
||||
},
|
||||
|
||||
initialize: function(map, feature, options) {
|
||||
L.Editable.CircleEditor.prototype.initialize.call(
|
||||
this,
|
||||
map,
|
||||
feature,
|
||||
options
|
||||
);
|
||||
this._deleteLatLng = this._computeDeleteLatLng();
|
||||
|
||||
// FeatureGroup instead of LayerGroup to propagate events to members
|
||||
this.editLayer = new L.FeatureGroup();
|
||||
},
|
||||
|
||||
addHooks: function() {
|
||||
L.Editable.CircleEditor.prototype.addHooks.call(this);
|
||||
if (this.feature) {
|
||||
this._addDeleteMarker();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
L.Editable.CircleEditor.prototype.reset.call(this);
|
||||
this._addDeleteMarker();
|
||||
},
|
||||
|
||||
onDrawingMouseDown: function(e) {
|
||||
this._deleteLatLng.update(e.latlng);
|
||||
L.Editable.CircleEditor.prototype.onDrawingMouseDown.call(this, e);
|
||||
},
|
||||
|
||||
// override to cancel/remove created circle when added by click instead of drag, because:
|
||||
// - without resize, edit handles stacked on top of each other
|
||||
// - makes event handling more complicated (editable:vertex:dragend not called)
|
||||
onDrawingMouseUp: function(e) {
|
||||
if (this.feature.getRadius() > 0) {
|
||||
this.commitDrawing(e);
|
||||
} else {
|
||||
this.cancelDrawing(e);
|
||||
this._delete();
|
||||
}
|
||||
e.originalEvent._simulated = false;
|
||||
L.Editable.PathEditor.prototype.onDrawingMouseUp.call(this, e);
|
||||
},
|
||||
|
||||
onVertexMarkerDrag: function(e) {
|
||||
this._updateDeleteLatLng();
|
||||
L.Editable.CircleEditor.prototype.onVertexMarkerDrag.call(this, e);
|
||||
}
|
||||
});
|
||||
|
||||
BR.DeleteMarker = L.Marker.extend({
|
||||
options: {
|
||||
draggable: false,
|
||||
icon: L.divIcon({
|
||||
iconSize: BR.Browser.touch
|
||||
? new L.Point(24, 24)
|
||||
: new L.Point(16, 16),
|
||||
className: 'leaflet-div-icon fa fa-trash-o nogo-delete-marker'
|
||||
})
|
||||
},
|
||||
|
||||
initialize: function(latlng, editor, options) {
|
||||
// derived from L.Editable.VertexMarker.initialize
|
||||
|
||||
// We don't use this._latlng, because on drag Leaflet replace it while
|
||||
// we want to keep reference.
|
||||
this.latlng = latlng;
|
||||
this.editor = editor;
|
||||
L.Marker.prototype.initialize.call(this, latlng, options);
|
||||
|
||||
this.latlng.__vertex = this;
|
||||
this.editor.editLayer.addLayer(this);
|
||||
|
||||
// to keep small circles editable, make sure delete button is below drag handle
|
||||
// (not using "+ 1" to place at bottom of other vertex markers)
|
||||
this.setZIndexOffset(editor.tools._lastZIndex);
|
||||
},
|
||||
|
||||
onAdd: function(map) {
|
||||
L.Marker.prototype.onAdd.call(this, map);
|
||||
this.on('click', this.onClick);
|
||||
},
|
||||
|
||||
onRemove: function(map) {
|
||||
delete this.latlng.__vertex;
|
||||
this.off('click', this.onClick);
|
||||
L.Marker.prototype.onRemove.call(this, map);
|
||||
},
|
||||
|
||||
onClick: function(e) {
|
||||
this.editor.delete();
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
L.Routing.Draw.prototype._hideTrailer = function() {
|
||||
if (this._trailer.options.opacity !== 0.0) {
|
||||
this._trailer.setStyle({opacity: 0.0});
|
||||
this._trailer.setStyle({ opacity: 0.0 });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ BR.Routing = L.Routing.extend({
|
|||
zIndexOffset: -2000
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
onAdd: function(map) {
|
||||
this._segmentsCasing = new L.FeatureGroup().addTo(map);
|
||||
|
||||
var container = L.Routing.prototype.onAdd.call(this, map);
|
||||
|
|
@ -31,35 +31,50 @@ BR.Routing = L.Routing.extend({
|
|||
this._waypoints.on('layeradd', this._setMarkerOpacity, this);
|
||||
|
||||
// turn line mouse marker off while over waypoint marker
|
||||
this.on('waypoint:mouseover', function(e) {
|
||||
this.on(
|
||||
'waypoint:mouseover',
|
||||
function(e) {
|
||||
// L.Routing.Edit._segmentOnMouseout without firing 'segment:mouseout' (enables draw)
|
||||
if (this._dragging) { return; }
|
||||
if (this._dragging) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._mouseMarker.setOpacity(0.0);
|
||||
this._map.off('mousemove', this._segmentOnMousemove, this);
|
||||
this._suspended = true;
|
||||
}, this._edit);
|
||||
},
|
||||
this._edit
|
||||
);
|
||||
|
||||
this.on('waypoint:mouseout', function(e) {
|
||||
this.on(
|
||||
'waypoint:mouseout',
|
||||
function(e) {
|
||||
this._segmentOnMouseover(e);
|
||||
this._suspended = false;
|
||||
}, this._edit);
|
||||
},
|
||||
this._edit
|
||||
);
|
||||
|
||||
this._edit._mouseMarker.setIcon(L.divIcon({
|
||||
className: 'line-mouse-marker'
|
||||
,iconAnchor: [8, 8] // size/2 + border/2
|
||||
,iconSize: [16, 16]
|
||||
}));
|
||||
this._edit._mouseMarker.setIcon(
|
||||
L.divIcon({
|
||||
className: 'line-mouse-marker',
|
||||
iconAnchor: [8, 8], // size/2 + border/2
|
||||
iconSize: [16, 16]
|
||||
})
|
||||
);
|
||||
|
||||
// Forward mousemove event to snapped feature (for Leaflet.Elevation to
|
||||
// update indicator), see also L.Routing.Edit._segmentOnMousemove
|
||||
this._edit._mouseMarker.on('move', L.bind(function(e) {
|
||||
this._edit._mouseMarker.on(
|
||||
'move',
|
||||
L.bind(function(e) {
|
||||
var latLng = e.latlng;
|
||||
if (latLng._feature) {
|
||||
this._mouseMarker._feature = latLng._feature;
|
||||
latLng._feature.fire('mousemove', e, true);
|
||||
}
|
||||
}, this._edit));
|
||||
}, this._edit)
|
||||
);
|
||||
var mouseoutHandler = function(e) {
|
||||
if (this._mouseMarker._feature) {
|
||||
this._mouseMarker._feature.fire('mouseout', e, true);
|
||||
|
|
@ -79,12 +94,20 @@ BR.Routing = L.Routing.extend({
|
|||
|
||||
// intercept listener: only re-show draw trailer after marker hover
|
||||
// when edit is not active (i.e. wasn't also supended)
|
||||
this._parent.off('waypoint:mouseout' , this._catchWaypointEvent, this);
|
||||
this.on('waypoint:mouseout' , function(e) {
|
||||
this._parent.off(
|
||||
'waypoint:mouseout',
|
||||
this._catchWaypointEvent,
|
||||
this
|
||||
);
|
||||
this.on(
|
||||
'waypoint:mouseout',
|
||||
function(e) {
|
||||
if (!this._parent._edit._suspended) {
|
||||
this._catchWaypointEvent(e);
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
this
|
||||
);
|
||||
});
|
||||
this._draw.on('disabled', function() {
|
||||
L.DomUtil.removeClass(map.getContainer(), 'routing-draw-enabled');
|
||||
|
|
@ -111,7 +134,12 @@ BR.Routing = L.Routing.extend({
|
|||
this._map.off('mouseout', hide, this);
|
||||
this._map.off('mouseover', show, this);
|
||||
L.DomEvent.off(this._map._controlContainer, 'mouseout', show, this);
|
||||
L.DomEvent.off(this._map._controlContainer, 'mouseover', hide, this);
|
||||
L.DomEvent.off(
|
||||
this._map._controlContainer,
|
||||
'mouseover',
|
||||
hide,
|
||||
this
|
||||
);
|
||||
});
|
||||
|
||||
// Call show after deleting last waypoint, but hide trailer.
|
||||
|
|
@ -119,35 +147,46 @@ BR.Routing = L.Routing.extend({
|
|||
// mouseout to show again never fires when deleted. Click handler
|
||||
// _onMouseClick aborts when hidden, so no waypoint can be added
|
||||
// although enabled.
|
||||
this.on('waypoint:click', function() {
|
||||
this.on(
|
||||
'waypoint:click',
|
||||
function() {
|
||||
if (this._hidden && !this._parent._waypoints._first) {
|
||||
this._show();
|
||||
this._hideTrailer();
|
||||
}
|
||||
}, this._draw);
|
||||
},
|
||||
this._draw
|
||||
);
|
||||
|
||||
// keys not working when map container does not have focus, use document instead
|
||||
L.DomEvent.removeListener(this._container, 'keyup', this._keyupListener);
|
||||
L.DomEvent.removeListener(
|
||||
this._container,
|
||||
'keyup',
|
||||
this._keyupListener
|
||||
);
|
||||
L.DomEvent.addListener(document, 'keyup', this._keyupListener, this);
|
||||
|
||||
// enable drawing mode
|
||||
this.draw(true);
|
||||
|
||||
return container;
|
||||
}
|
||||
},
|
||||
|
||||
,_addSegmentCasing: function(e) {
|
||||
var casing = L.polyline(e.layer.getLatLngs(), this.options.styles.trackCasing);
|
||||
_addSegmentCasing: function(e) {
|
||||
var casing = L.polyline(
|
||||
e.layer.getLatLngs(),
|
||||
this.options.styles.trackCasing
|
||||
);
|
||||
this._segmentsCasing.addLayer(casing);
|
||||
e.layer._casing = casing;
|
||||
this._segments.bringToFront();
|
||||
}
|
||||
},
|
||||
|
||||
,_removeSegmentCasing: function(e) {
|
||||
_removeSegmentCasing: function(e) {
|
||||
this._segmentsCasing.removeLayer(e.layer._casing);
|
||||
}
|
||||
},
|
||||
|
||||
,setOpacity: function(opacity) {
|
||||
setOpacity: function(opacity) {
|
||||
// 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
|
||||
// inverted formula is used to get the same result as with a single layer.
|
||||
|
|
@ -168,34 +207,36 @@ BR.Routing = L.Routing.extend({
|
|||
this._waypoints.eachLayer(function(marker) {
|
||||
marker.setOpacity(opacity);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
,_setMarkerOpacity: function(e) {
|
||||
_setMarkerOpacity: function(e) {
|
||||
e.layer.setOpacity(this.options.icons.opacity);
|
||||
}
|
||||
},
|
||||
|
||||
,_removeMarkerEvents: function(marker) {
|
||||
_removeMarkerEvents: function(marker) {
|
||||
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('dragend' , this._fireWaypointEvent, this);
|
||||
marker.off('drag' , this._fireWaypointEvent, this);
|
||||
marker.off('click' , this._fireWaypointEvent, this);
|
||||
}
|
||||
marker.off('dragend', this._fireWaypointEvent, this);
|
||||
marker.off('drag', this._fireWaypointEvent, this);
|
||||
marker.off('click', this._fireWaypointEvent, this);
|
||||
},
|
||||
|
||||
,clear: function() {
|
||||
clear: function() {
|
||||
var drawEnabled = this._draw._enabled;
|
||||
var current = this._waypoints._first;
|
||||
|
||||
this.draw(false);
|
||||
|
||||
if (current === null) { return; }
|
||||
if (current === null) {
|
||||
return;
|
||||
}
|
||||
this._removeMarkerEvents(current);
|
||||
while (current._routing.nextMarker) {
|
||||
var marker = current._routing.nextMarker;
|
||||
this._removeMarkerEvents(marker);
|
||||
current = marker;
|
||||
};
|
||||
}
|
||||
|
||||
this._waypoints._first = null;
|
||||
this._waypoints._last = null;
|
||||
|
|
@ -205,9 +246,9 @@ BR.Routing = L.Routing.extend({
|
|||
if (drawEnabled) {
|
||||
this.draw(true);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
,setWaypoints: function(latLngs, cb) {
|
||||
setWaypoints: function(latLngs, cb) {
|
||||
var i;
|
||||
var callbackCount = 0;
|
||||
var firstErr;
|
||||
|
|
@ -228,11 +269,11 @@ BR.Routing = L.Routing.extend({
|
|||
for (i = 0; latLngs && i < latLngs.length; i++) {
|
||||
this.addWaypoint(latLngs[i], this._waypoints._last, null, callback);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// patch to fix error when line is null or error line
|
||||
// (when called while still segments to calculate, e.g. permalink or fast drawing)
|
||||
,toPolyline: function() {
|
||||
toPolyline: function() {
|
||||
var latLngs = [];
|
||||
|
||||
this._eachSegment(function(m1, m2, line) {
|
||||
|
|
@ -244,14 +285,14 @@ BR.Routing = L.Routing.extend({
|
|||
});
|
||||
|
||||
return L.polyline(latLngs);
|
||||
}
|
||||
},
|
||||
|
||||
,_routeSegment: function(m1, m2, cb) {
|
||||
_routeSegment: function(m1, m2, cb) {
|
||||
var loadingTrailer;
|
||||
|
||||
// change segment color before request to indicate recalculation (mark old)
|
||||
if (m1 && m1._routing.nextLine !== null) {
|
||||
m1._routing.nextLine.setStyle({color: 'dimgray' });
|
||||
m1._routing.nextLine.setStyle({ color: 'dimgray' });
|
||||
}
|
||||
|
||||
// animate dashed trailer as loading indicator
|
||||
|
|
@ -265,15 +306,20 @@ BR.Routing = L.Routing.extend({
|
|||
loadingTrailer.addTo(this._map);
|
||||
}
|
||||
|
||||
L.Routing.prototype._routeSegment.call(this, m1, m2, L.bind(function(err, data) {
|
||||
L.Routing.prototype._routeSegment.call(
|
||||
this,
|
||||
m1,
|
||||
m2,
|
||||
L.bind(function(err, data) {
|
||||
if (loadingTrailer) {
|
||||
this._map.removeLayer(loadingTrailer);
|
||||
}
|
||||
cb(err, data);
|
||||
}, this));
|
||||
}
|
||||
}, this)
|
||||
);
|
||||
},
|
||||
|
||||
,getSegments: function() {
|
||||
getSegments: function() {
|
||||
var segments = [];
|
||||
|
||||
this._eachSegment(function(m1, m2, line) {
|
||||
|
|
@ -285,14 +331,32 @@ BR.Routing = L.Routing.extend({
|
|||
});
|
||||
|
||||
return segments;
|
||||
}
|
||||
},
|
||||
|
||||
_keyupListener: function(e) {
|
||||
// Suppress shortcut handling when a text input field is focussed
|
||||
if (
|
||||
document.activeElement.type == 'text' ||
|
||||
document.activeElement.type == 'textarea'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
// add 'esc' to disable drawing
|
||||
,_keyupListener: function (e) {
|
||||
if (e.keyCode === 27) {
|
||||
this._draw.disable();
|
||||
} else {
|
||||
L.Routing.prototype._keyupListener.call(this, e);
|
||||
}
|
||||
},
|
||||
|
||||
isDrawing: function() {
|
||||
return this._draw._enabled;
|
||||
},
|
||||
|
||||
reverse: function() {
|
||||
var waypoints = this.getWaypoints();
|
||||
waypoints.reverse();
|
||||
this.clear();
|
||||
this.setWaypoints(waypoints);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,18 +1,14 @@
|
|||
BR.Search = L.Control.Geocoder.extend({
|
||||
options: {
|
||||
geocoder: new L.Control.Geocoder.Nominatim({
|
||||
geocoder: new L.Control.Geocoder.LatLng({
|
||||
next: new L.Control.Geocoder.Nominatim({
|
||||
serviceUrl: 'https://nominatim.openstreetmap.org/'
|
||||
}),
|
||||
sizeInMeters: 800
|
||||
}),
|
||||
position: 'topleft'
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
map.attributionControl.addAttribution(
|
||||
'search by <a href="https://wiki.openstreetmap.org/wiki/Nominatim" target="_blank">Nominatim</a>');
|
||||
|
||||
return L.Control.Geocoder.prototype.onAdd.call(this, map);
|
||||
},
|
||||
|
||||
markGeocode: function(result) {
|
||||
this._map.fitBounds(result.geocode.bbox, {
|
||||
maxZoom: 17
|
||||
|
|
|
|||
115
js/plugin/Sidebar.js
Normal file
115
js/plugin/Sidebar.js
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
BR.Sidebar = L.Control.Sidebar.extend({
|
||||
storageId: 'sidebar-control',
|
||||
|
||||
options: {
|
||||
position: 'right',
|
||||
container: 'sidebar',
|
||||
tabContainer: 'sidebarTabs',
|
||||
autopan: false,
|
||||
defaultTabId: '',
|
||||
|
||||
// Tabs to be notified when shown or hidden
|
||||
// (tab div id -> object implementing show/hide methods)
|
||||
listeningTabs: {}
|
||||
},
|
||||
|
||||
initialize: function(id, options) {
|
||||
L.Control.Sidebar.prototype.initialize.call(this, id, options);
|
||||
|
||||
this.oldTab = null;
|
||||
},
|
||||
|
||||
addTo: function(map) {
|
||||
L.Control.Sidebar.prototype.addTo.call(this, map);
|
||||
|
||||
this.on('content', this._notifyOnContent, this);
|
||||
this.on('closing', this._notifyOnClose, this);
|
||||
this.on('toggleExpand', this._notifyOnResize, this);
|
||||
|
||||
this.on(
|
||||
'closing',
|
||||
function() {
|
||||
this._map.getContainer().focus();
|
||||
},
|
||||
this
|
||||
);
|
||||
|
||||
this._rememberTabState();
|
||||
|
||||
if (
|
||||
L.Browser.touch &&
|
||||
BR.Browser.touchScreenDetectable &&
|
||||
!BR.Browser.touchScreen
|
||||
) {
|
||||
L.DomUtil.removeClass(this._container, 'leaflet-touch');
|
||||
L.DomUtil.removeClass(this._tabContainer, 'leaflet-touch');
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
showPanel: function(id) {
|
||||
var tab = this._getTab(id);
|
||||
tab.hidden = false;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_rememberTabState: function() {
|
||||
if (BR.Util.localStorageAvailable()) {
|
||||
this.on('content closing', this._storeActiveTab, this);
|
||||
|
||||
var tabId = localStorage.getItem(this.storageId);
|
||||
|
||||
// 'true': legacy value for toggling old sidebar
|
||||
if (tabId === 'true') {
|
||||
tabId = this.options.defaultTabId;
|
||||
} else if (tabId === null) {
|
||||
// not set: closed by default for new users
|
||||
tabId = '';
|
||||
}
|
||||
if (tabId !== '') {
|
||||
this.open(tabId);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_notifyShow: function(tab) {
|
||||
if (tab && tab.show) {
|
||||
tab.show();
|
||||
}
|
||||
},
|
||||
|
||||
_notifyHide: function(tab) {
|
||||
if (tab && tab.hide) {
|
||||
tab.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_notifyOnContent: function(e) {
|
||||
var tab = this.options.listeningTabs[e.id];
|
||||
this._notifyHide(this.oldTab);
|
||||
this._notifyShow(tab);
|
||||
this.oldTab = tab;
|
||||
},
|
||||
|
||||
_notifyOnClose: function(e) {
|
||||
this._notifyHide(this.oldTab);
|
||||
this.oldTab = null;
|
||||
},
|
||||
|
||||
_notifyOnResize: function(e) {
|
||||
var tab = this.oldTab;
|
||||
if (tab && tab.onResize) {
|
||||
tab.onResize();
|
||||
}
|
||||
},
|
||||
|
||||
_storeActiveTab: function(e) {
|
||||
localStorage.setItem(this.storageId, e.id || '');
|
||||
}
|
||||
});
|
||||
|
||||
BR.sidebar = function(divId, options) {
|
||||
return new BR.Sidebar(divId, options);
|
||||
};
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
(function(window) {
|
||||
var HAS_HASHCHANGE = (function() {
|
||||
var doc_mode = window.documentMode;
|
||||
return ('onhashchange' in window) &&
|
||||
(doc_mode === undefined || doc_mode > 7);
|
||||
return (
|
||||
'onhashchange' in window && (doc_mode === undefined || doc_mode > 7)
|
||||
);
|
||||
})();
|
||||
|
||||
L.Hash = function(map, options) {
|
||||
|
|
@ -14,16 +15,16 @@
|
|||
};
|
||||
|
||||
L.Hash.parseHash = function(hash) {
|
||||
if(hash.indexOf('#map=') === 0) {
|
||||
if (hash.indexOf('#map=') === 0) {
|
||||
hash = hash.substr(5);
|
||||
}
|
||||
var args = hash.split(/\&(.+)/);
|
||||
var mapsArgs = args[0].split("/");
|
||||
var mapsArgs = args[0].split('/');
|
||||
if (mapsArgs.length == 4) {
|
||||
var zoom = parseInt(mapsArgs[0], 10),
|
||||
lat = parseFloat(mapsArgs[1]),
|
||||
lon = parseFloat(mapsArgs[2]),
|
||||
layers = decodeURIComponent(mapsArgs[3]).split('-'),
|
||||
layers = this.parseLayers(mapsArgs[3]),
|
||||
additional = args[1];
|
||||
if (isNaN(zoom) || isNaN(lat) || isNaN(lon)) {
|
||||
return false;
|
||||
|
|
@ -40,32 +41,19 @@
|
|||
}
|
||||
};
|
||||
|
||||
L.Hash.formatHash = function(map) {
|
||||
(L.Hash.formatHash = function(map) {
|
||||
var center = map.getCenter(),
|
||||
zoom = map.getZoom(),
|
||||
precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)),
|
||||
layers = [];
|
||||
layers = this.formatLayers();
|
||||
|
||||
//console.log(this.options);
|
||||
var options = this.options;
|
||||
//Check active layers
|
||||
for(var key in options) {
|
||||
if (options.hasOwnProperty(key)) {
|
||||
if (map.hasLayer(options[key])) {
|
||||
layers.push(key);
|
||||
};
|
||||
};
|
||||
};
|
||||
if (layers.length == 0) {
|
||||
layers.push(Object.keys(options)[0]);
|
||||
}
|
||||
var params = [
|
||||
zoom,
|
||||
center.lat.toFixed(precision),
|
||||
center.lng.toFixed(precision),
|
||||
encodeURIComponent(layers.join("-"))
|
||||
layers
|
||||
];
|
||||
url = "#map=" + params.join("/");
|
||||
url = '#map=' + params.join('/');
|
||||
if (this.additionalCb != null) {
|
||||
var additional = this.additionalCb();
|
||||
if (additional != null) {
|
||||
|
|
@ -73,9 +61,11 @@
|
|||
}
|
||||
}
|
||||
return url;
|
||||
}),
|
||||
(L.Hash.prototype = {
|
||||
options: {
|
||||
layerSeparator: ','
|
||||
},
|
||||
|
||||
L.Hash.prototype = {
|
||||
map: null,
|
||||
lastHash: null,
|
||||
|
||||
|
|
@ -95,6 +85,88 @@
|
|||
}
|
||||
},
|
||||
|
||||
_parseLayers: function(layersParam, layerSeparator) {
|
||||
var layers = layersParam.split(layerSeparator).map(
|
||||
L.bind(function(layerEncoded) {
|
||||
var obj = null;
|
||||
var layerString = decodeURIComponent(layerEncoded);
|
||||
|
||||
if (layerString) {
|
||||
obj = this.options.layersControl.getLayerFromString(
|
||||
layerString
|
||||
);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}, this)
|
||||
);
|
||||
|
||||
return layers;
|
||||
},
|
||||
|
||||
parseLayers: function(layersParam) {
|
||||
var countFoundLayers = function(count, obj) {
|
||||
if (obj) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
};
|
||||
|
||||
var layers = this._parseLayers(
|
||||
layersParam,
|
||||
this.options.layerSeparator
|
||||
);
|
||||
var found = layers.reduce(countFoundLayers, 0);
|
||||
|
||||
if (found < layers.length) {
|
||||
// legacy support for name instead of id and '-' layer separator
|
||||
var layersLegacy = this._parseLayers(layersParam, '-');
|
||||
var foundLegacy = layersLegacy.reduce(countFoundLayers, 0);
|
||||
|
||||
if (foundLegacy > found) {
|
||||
layers = layersLegacy;
|
||||
}
|
||||
}
|
||||
|
||||
return layers;
|
||||
},
|
||||
|
||||
activateLayers: function(layers) {
|
||||
var layersControl = this.options.layersControl;
|
||||
var added = false;
|
||||
|
||||
layersControl.removeActiveLayers();
|
||||
|
||||
layers.forEach(
|
||||
L.bind(function(obj, index, array) {
|
||||
if (obj) {
|
||||
layersControl.activateLayer(obj);
|
||||
if (obj && !obj.overlay) {
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
}, this)
|
||||
);
|
||||
|
||||
if (!added) {
|
||||
// if we couldn't add layers (removed or invalid name), add the default one
|
||||
layersControl.activateDefaultBaseLayer();
|
||||
}
|
||||
},
|
||||
|
||||
formatLayers: function() {
|
||||
var objList = this.options.layersControl.getActiveLayers();
|
||||
var layerList = objList.map(
|
||||
L.bind(function(obj) {
|
||||
return encodeURIComponent(
|
||||
this.options.layersControl.toLayerString(obj)
|
||||
);
|
||||
}, this)
|
||||
);
|
||||
|
||||
return layerList.join(this.options.layerSeparator);
|
||||
},
|
||||
|
||||
removeFrom: function(map) {
|
||||
if (this.changeTimeout) {
|
||||
clearTimeout(this.changeTimeout);
|
||||
|
|
@ -143,29 +215,8 @@
|
|||
this.movingMap = true;
|
||||
|
||||
this.map.setView(parsed.center, parsed.zoom);
|
||||
var layers = parsed.layers,
|
||||
options = this.options,
|
||||
that = this;
|
||||
//Add/remove layer
|
||||
this.map.eachLayer(function(layer) {
|
||||
for (alayer in that.layers) {
|
||||
if (that.layers[alayer] == layer) {
|
||||
that.map.removeLayer(layer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
var added = false;
|
||||
layers.forEach(function(element, index, array) {
|
||||
if (element in options) {
|
||||
added = true;
|
||||
that.map.addLayer(options[element]);
|
||||
}
|
||||
});
|
||||
if (!added) {
|
||||
// if we couldn't add layers (custom ones or invalid name), add the default one
|
||||
this.map.addLayer(options[Object.keys(options)[0]]);
|
||||
}
|
||||
|
||||
this.activateLayers(parsed.layers);
|
||||
|
||||
if (this.onHashChangeCb != null) {
|
||||
this.onHashChangeCb(parsed.additional);
|
||||
|
|
@ -195,22 +246,41 @@
|
|||
isListening: false,
|
||||
hashChangeInterval: null,
|
||||
startListening: function() {
|
||||
this.map.on("moveend layeradd layerremove", this.onMapMove, this);
|
||||
this.map.on(
|
||||
'moveend layeradd layerremove',
|
||||
this.onMapMove,
|
||||
this
|
||||
);
|
||||
|
||||
if (HAS_HASHCHANGE) {
|
||||
L.DomEvent.addListener(window, "hashchange", this.onHashChange);
|
||||
L.DomEvent.addListener(
|
||||
window,
|
||||
'hashchange',
|
||||
this.onHashChange
|
||||
);
|
||||
} else {
|
||||
clearInterval(this.hashChangeInterval);
|
||||
this.hashChangeInterval = setInterval(this.onHashChange, 50);
|
||||
this.hashChangeInterval = setInterval(
|
||||
this.onHashChange,
|
||||
50
|
||||
);
|
||||
}
|
||||
this.isListening = true;
|
||||
},
|
||||
|
||||
stopListening: function() {
|
||||
this.map.off("moveend layeradd layerremove", this.onMapMove, this);
|
||||
this.map.off(
|
||||
'moveend layeradd layerremove',
|
||||
this.onMapMove,
|
||||
this
|
||||
);
|
||||
|
||||
if (HAS_HASHCHANGE) {
|
||||
L.DomEvent.removeListener(window, "hashchange", this.onHashChange);
|
||||
L.DomEvent.removeListener(
|
||||
window,
|
||||
'hashchange',
|
||||
this.onHashChange
|
||||
);
|
||||
} else {
|
||||
clearInterval(this.hashChangeInterval);
|
||||
}
|
||||
|
|
@ -218,15 +288,17 @@
|
|||
},
|
||||
|
||||
_keyByValue: function(obj, value) {
|
||||
for(var key in obj) {
|
||||
for (var key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
if (obj[key] === value) {
|
||||
return key;
|
||||
} else { return null; };
|
||||
};
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
L.hash = function(map, options) {
|
||||
return new L.Hash(map, options);
|
||||
};
|
||||
|
|
|
|||
31
js/plugin/stravaSegments.js
Normal file
31
js/plugin/stravaSegments.js
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
BR.stravaSegments = function(map, layersControl) {
|
||||
const stravaControl = L.control
|
||||
.stravaSegments({
|
||||
runningTitle: i18next.t('map.strava-running'),
|
||||
bikingTitle: i18next.t('map.strava-biking'),
|
||||
loadingTitle: i18next.t('map.loading'),
|
||||
stravaToken: BR.keys.strava
|
||||
})
|
||||
.addTo(map);
|
||||
layersControl.addOverlay(
|
||||
stravaControl.stravaLayer,
|
||||
i18next.t('map.layer.strava-segments')
|
||||
);
|
||||
stravaControl.onError = function(err) {
|
||||
BR.message.showError(
|
||||
i18next.t('warning.strava-error', {
|
||||
error: err && err.message ? err.message : err
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
// hide strava buttons when layer is inactive
|
||||
var toggleStravaControl = function() {
|
||||
var stravaBar = stravaControl.runningButton.button.parentElement;
|
||||
stravaBar.hidden = !stravaBar.hidden;
|
||||
};
|
||||
toggleStravaControl();
|
||||
stravaControl.stravaLayer.on('add remove', toggleStravaControl);
|
||||
|
||||
return stravaControl;
|
||||
};
|
||||
|
|
@ -2,7 +2,8 @@ L.BRouter = L.Class.extend({
|
|||
statics: {
|
||||
// NOTE: the routing API used here is not public!
|
||||
// /brouter?lonlats=1.1,1.2|2.1,2.2|3.1,3.2|4.1,4.2&nogos=-1.1,-1.2,1|-2.1,-2.2,2&profile=shortest&alternativeidx=1&format=kml
|
||||
URL_TEMPLATE: '/brouter?lonlats={lonlats}&nogos={nogos}&profile={profile}&alternativeidx={alternativeidx}&format={format}',
|
||||
URL_TEMPLATE:
|
||||
'/brouter?lonlats={lonlats}&nogos={nogos}&polylines={polylines}&polygons={polygons}&profile={profile}&alternativeidx={alternativeidx}&format={format}',
|
||||
URL_PROFILE_UPLOAD: BR.conf.host + '/brouter/profile',
|
||||
PRECISION: 6,
|
||||
NUMBER_SEPARATOR: ',',
|
||||
|
|
@ -10,18 +11,20 @@ L.BRouter = L.Class.extend({
|
|||
ABORTED_ERROR: 'aborted'
|
||||
},
|
||||
|
||||
options: {
|
||||
},
|
||||
options: {},
|
||||
|
||||
initialize: function (options) {
|
||||
initialize: function(options) {
|
||||
L.setOptions(this, options);
|
||||
|
||||
this.queue = async.queue(L.bind(function (task, callback) {
|
||||
this.queue = async.queue(
|
||||
L.bind(function(task, callback) {
|
||||
this.getRoute(task.segment, callback);
|
||||
}, this), 1);
|
||||
}, this),
|
||||
1
|
||||
);
|
||||
|
||||
// patch to call callbacks on kill for cleanup (loadingTrailer)
|
||||
this.queue.kill = function () {
|
||||
this.queue.kill = function() {
|
||||
var aborted = this.tasks;
|
||||
this.drain = null;
|
||||
this.tasks = [];
|
||||
|
|
@ -37,15 +40,32 @@ L.BRouter = L.Class.extend({
|
|||
|
||||
getUrlParams: function(latLngs, format) {
|
||||
params = {};
|
||||
|
||||
if (this._getLonLatsString(latLngs) != null)
|
||||
params.lonlats = this._getLonLatsString(latLngs);
|
||||
|
||||
if (this._getNogosString(this.options.nogos).length > 0)
|
||||
if (
|
||||
this.options.nogos &&
|
||||
this._getNogosString(this.options.nogos).length > 0
|
||||
)
|
||||
params.nogos = this._getNogosString(this.options.nogos);
|
||||
|
||||
if (this.options.profile != null)
|
||||
params.profile = this.options.profile;
|
||||
if (
|
||||
this.options.polylines &&
|
||||
this._getNogosPolylinesString(this.options.polylines).length > 0
|
||||
)
|
||||
params.polylines = this._getNogosPolylinesString(
|
||||
this.options.polylines
|
||||
);
|
||||
|
||||
if (
|
||||
this.options.polygons &&
|
||||
this._getNogosPolygonsString(this.options.polygons).length > 0
|
||||
)
|
||||
params.polygons = this._getNogosPolygonsString(
|
||||
this.options.polygons
|
||||
);
|
||||
|
||||
if (this.options.profile != null) params.profile = this.options.profile;
|
||||
|
||||
params.alternativeidx = this.options.alternative;
|
||||
|
||||
|
|
@ -53,10 +73,16 @@ L.BRouter = L.Class.extend({
|
|||
params.format = format;
|
||||
} else {
|
||||
// do not put values in URL if this is the default value (format===null)
|
||||
if (params.profile === BR.conf.profiles[0])
|
||||
if (params.profile === BR.conf.profiles[0]) delete params.profile;
|
||||
if (params.alternativeidx == 0) delete params.alternativeidx;
|
||||
|
||||
// don't add custom profile, as these are only stored temporarily
|
||||
if (
|
||||
params.profile &&
|
||||
params.profile.substring(0, 7) === 'custom_'
|
||||
) {
|
||||
delete params.profile;
|
||||
if (params.alternativeidx == 0)
|
||||
delete params.alternativeidx;
|
||||
}
|
||||
}
|
||||
|
||||
return params;
|
||||
|
|
@ -70,6 +96,12 @@ L.BRouter = L.Class.extend({
|
|||
if (params.nogos) {
|
||||
opts.nogos = this._parseNogos(params.nogos);
|
||||
}
|
||||
if (params.polylines) {
|
||||
opts.polylines = this._parseNogosPolylines(params.polylines);
|
||||
}
|
||||
if (params.polygons) {
|
||||
opts.polygons = this._parseNogosPolygons(params.polygons);
|
||||
}
|
||||
if (params.alternativeidx) {
|
||||
opts.alternative = params.alternativeidx;
|
||||
}
|
||||
|
|
@ -79,24 +111,39 @@ L.BRouter = L.Class.extend({
|
|||
return opts;
|
||||
},
|
||||
|
||||
getUrl: function(latLngs, format) {
|
||||
getUrl: function(latLngs, format, trackname, exportWaypoints) {
|
||||
var urlParams = this.getUrlParams(latLngs, format);
|
||||
|
||||
var args = []
|
||||
var args = [];
|
||||
if (urlParams.lonlats != null && urlParams.lonlats.length > 0)
|
||||
args.push(L.Util.template('lonlats={lonlats}', urlParams));
|
||||
if (urlParams.nogos != null)
|
||||
args.push(L.Util.template('nogos={nogos}', urlParams));
|
||||
if (urlParams.polylines != null)
|
||||
args.push(L.Util.template('polylines={polylines}', urlParams));
|
||||
if (urlParams.polygons != null)
|
||||
args.push(L.Util.template('polygons={polygons}', urlParams));
|
||||
if (urlParams.profile != null)
|
||||
args.push(L.Util.template('profile={profile}', urlParams));
|
||||
if (urlParams.alternativeidx != null)
|
||||
args.push(L.Util.template('alternativeidx={alternativeidx}', urlParams));
|
||||
args.push(
|
||||
L.Util.template('alternativeidx={alternativeidx}', urlParams)
|
||||
);
|
||||
if (urlParams.format != null)
|
||||
args.push(L.Util.template('format={format}', urlParams));
|
||||
if (trackname)
|
||||
args.push(
|
||||
L.Util.template('trackname={trackname}', {
|
||||
trackname: trackname
|
||||
})
|
||||
);
|
||||
if (exportWaypoints) args.push('exportWaypoints=1');
|
||||
|
||||
var prepend_host = (format != null);
|
||||
var prepend_host = format != null;
|
||||
|
||||
return (prepend_host ? BR.conf.host : '') + '/brouter?' + args.join('&');
|
||||
return (
|
||||
(prepend_host ? BR.conf.host : '') + '/brouter?' + args.join('&')
|
||||
);
|
||||
},
|
||||
|
||||
getRoute: function(latLngs, cb) {
|
||||
|
|
@ -104,26 +151,32 @@ L.BRouter = L.Class.extend({
|
|||
xhr = new XMLHttpRequest();
|
||||
|
||||
if (!url) {
|
||||
return cb(new Error('Error getting route URL'));
|
||||
return cb(new Error(i18next.t('warning.cannot-get-route')));
|
||||
}
|
||||
|
||||
xhr.open('GET', url, true);
|
||||
xhr.onload = L.bind(this._handleRouteResponse, this, xhr, cb);
|
||||
xhr.onerror = L.bind(function(xhr, cb) {
|
||||
xhr.onerror = L.bind(
|
||||
function(xhr, cb) {
|
||||
cb(BR.Util.getError(xhr));
|
||||
}, this, xhr, cb);
|
||||
},
|
||||
this,
|
||||
xhr,
|
||||
cb
|
||||
);
|
||||
xhr.send();
|
||||
},
|
||||
|
||||
_handleRouteResponse: function(xhr, cb) {
|
||||
var layer,
|
||||
geojson;
|
||||
var layer, geojson;
|
||||
|
||||
if (xhr.status === 200
|
||||
&& xhr.responseText
|
||||
if (
|
||||
xhr.status === 200 &&
|
||||
xhr.responseText &&
|
||||
// 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/vnd.geo+json'
|
||||
) {
|
||||
// leaflet.spin
|
||||
//gpxLayer.fire('data:loaded');
|
||||
|
||||
|
|
@ -132,7 +185,7 @@ L.BRouter = L.Class.extend({
|
|||
layer = L.geoJSON(geojson).getLayers()[0];
|
||||
|
||||
return cb(null, layer);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
console.error(e, xhr.responseText);
|
||||
return cb(e);
|
||||
}
|
||||
|
|
@ -158,7 +211,7 @@ L.BRouter = L.Class.extend({
|
|||
xhr.onload = L.bind(this._handleProfileResponse, this, xhr, cb);
|
||||
xhr.onerror = function(evt) {
|
||||
var xhr = this;
|
||||
cb('Upload error: ' + xhr.statusText);
|
||||
cb(i18next.t('warning.upload-error', { error: xhr.statusText }));
|
||||
};
|
||||
|
||||
// send profile text only, as text/plain;charset=UTF-8
|
||||
|
|
@ -168,11 +221,15 @@ L.BRouter = L.Class.extend({
|
|||
_handleProfileResponse: function(xhr, cb) {
|
||||
var response;
|
||||
|
||||
if (xhr.status === 200 && xhr.responseText && xhr.responseText.length > 0) {
|
||||
if (
|
||||
xhr.status === 200 &&
|
||||
xhr.responseText &&
|
||||
xhr.responseText.length > 0
|
||||
) {
|
||||
response = JSON.parse(xhr.responseText);
|
||||
cb(response.error, response.profileid);
|
||||
} else {
|
||||
cb('Profile error: no or empty response from server');
|
||||
cb(i18next.t('warning.profile-error'));
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -180,7 +237,7 @@ L.BRouter = L.Class.extend({
|
|||
var s = '';
|
||||
for (var i = 0; i < latLngs.length; i++) {
|
||||
s += this._formatLatLng(latLngs[i]);
|
||||
if (i < (latLngs.length - 1)) {
|
||||
if (i < latLngs.length - 1) {
|
||||
s += L.BRouter.GROUP_SEPARATOR;
|
||||
}
|
||||
}
|
||||
|
|
@ -213,7 +270,16 @@ L.BRouter = L.Class.extend({
|
|||
s += this._formatLatLng(circle.getLatLng());
|
||||
s += L.BRouter.NUMBER_SEPARATOR;
|
||||
s += Math.round(circle.getRadius());
|
||||
if (i < (nogos.length - 1)) {
|
||||
// -1 is default nogo exclusion, it should not be passed as a URL parameter.
|
||||
if (
|
||||
circle.options.nogoWeight !== undefined &&
|
||||
circle.options.nogoWeight !== null &&
|
||||
circle.options.nogoWeight !== -1
|
||||
) {
|
||||
s += L.BRouter.NUMBER_SEPARATOR;
|
||||
s += circle.options.nogoWeight;
|
||||
}
|
||||
if (i < nogos.length - 1) {
|
||||
s += L.BRouter.GROUP_SEPARATOR;
|
||||
}
|
||||
}
|
||||
|
|
@ -231,26 +297,137 @@ L.BRouter = L.Class.extend({
|
|||
|
||||
groups = s.split(L.BRouter.GROUP_SEPARATOR);
|
||||
for (var i = 0; i < groups.length; i++) {
|
||||
// lng,lat,radius
|
||||
// lng,lat,radius(,weight)
|
||||
numbers = groups[i].split(L.BRouter.NUMBER_SEPARATOR);
|
||||
// TODO refactor: pass simple obj, create circle in NogoAreas; use shapeOptions of instance
|
||||
// [lat,lng],radius
|
||||
nogos.push(L.circle([numbers[1], numbers[0]], {radius: numbers[2]}));
|
||||
// Parse as a nogo circle
|
||||
var nogoOptions = { radius: numbers[2] };
|
||||
if (numbers.length > 3) {
|
||||
nogoOptions.nogoWeight = numbers[3];
|
||||
}
|
||||
nogos.push(L.circle([numbers[1], numbers[0]], nogoOptions));
|
||||
}
|
||||
|
||||
return nogos;
|
||||
},
|
||||
|
||||
_getNogosPolylinesString: function(nogos) {
|
||||
var s = '';
|
||||
for (var i = 0, polyline, vertices; i < nogos.length; i++) {
|
||||
polyline = nogos[i];
|
||||
vertices = polyline.getLatLngs();
|
||||
for (var j = 0; j < vertices.length; j++) {
|
||||
if (j > 0) {
|
||||
s += L.BRouter.NUMBER_SEPARATOR;
|
||||
}
|
||||
s += this._formatLatLng(vertices[j]);
|
||||
}
|
||||
// -1 is default nogo exclusion, it should not be passed as a URL parameter.
|
||||
if (
|
||||
polyline.options.nogoWeight !== undefined &&
|
||||
polyline.options.nogoWeight !== null &&
|
||||
polyline.options.nogoWeight !== -1
|
||||
) {
|
||||
s += L.BRouter.NUMBER_SEPARATOR;
|
||||
s += polyline.options.nogoWeight;
|
||||
}
|
||||
if (i < nogos.length - 1) {
|
||||
s += L.BRouter.GROUP_SEPARATOR;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
},
|
||||
|
||||
_parseNogosPolylines: function(s) {
|
||||
var groups,
|
||||
numbers,
|
||||
latlngs,
|
||||
nogos = [];
|
||||
|
||||
groups = s.split(L.BRouter.GROUP_SEPARATOR);
|
||||
for (var i = 0; i < groups.length; i++) {
|
||||
numbers = groups[i].split(L.BRouter.NUMBER_SEPARATOR);
|
||||
if (numbers.length > 1) {
|
||||
latlngs = [];
|
||||
for (var j = 0; j < numbers.length - 1; ) {
|
||||
var lng = Number.parseFloat(numbers[j++]);
|
||||
var lat = Number.parseFloat(numbers[j++]);
|
||||
latlngs.push([lat, lng]);
|
||||
}
|
||||
var nogoWeight;
|
||||
if (j < numbers.length) {
|
||||
nogoWeight = Number.parseFloat(numbers[j++]);
|
||||
}
|
||||
nogos.push(L.polyline(latlngs, { nogoWeight: nogoWeight }));
|
||||
}
|
||||
}
|
||||
return nogos;
|
||||
},
|
||||
|
||||
_getNogosPolygonsString: function(nogos) {
|
||||
var s = '';
|
||||
for (var i = 0, polygon, vertices; i < nogos.length; i++) {
|
||||
polygon = nogos[i];
|
||||
vertices = polygon.getLatLngs()[0];
|
||||
for (var j = 0; j < vertices.length; j++) {
|
||||
if (j > 0) {
|
||||
s += L.BRouter.NUMBER_SEPARATOR;
|
||||
}
|
||||
s += this._formatLatLng(vertices[j]);
|
||||
}
|
||||
// -1 is default nogo exclusion, it should not be passed as a URL parameter.
|
||||
if (
|
||||
polygon.options.nogoWeight !== undefined &&
|
||||
polygon.options.nogoWeight !== null &&
|
||||
polygon.options.nogoWeight !== -1
|
||||
) {
|
||||
s += L.BRouter.NUMBER_SEPARATOR;
|
||||
s += polygon.options.nogoWeight;
|
||||
}
|
||||
if (i < nogos.length - 1) {
|
||||
s += L.BRouter.GROUP_SEPARATOR;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
},
|
||||
|
||||
_parseNogosPolygons: function(s) {
|
||||
var groups,
|
||||
numbers,
|
||||
latlngs,
|
||||
nogos = [];
|
||||
|
||||
groups = s.split(L.BRouter.GROUP_SEPARATOR);
|
||||
for (var i = 0; i < groups.length; i++) {
|
||||
numbers = groups[i].split(L.BRouter.NUMBER_SEPARATOR);
|
||||
if (numbers.length > 1) {
|
||||
latlngs = [];
|
||||
for (var j = 0; j < numbers.length - 1; ) {
|
||||
var lng = Number.parseFloat(numbers[j++]);
|
||||
var lat = Number.parseFloat(numbers[j++]);
|
||||
latlngs.push([lat, lng]);
|
||||
}
|
||||
var nogoWeight;
|
||||
if (j < numbers.length) {
|
||||
nogoWeight = Number.parseFloat(numbers[j++]);
|
||||
}
|
||||
nogos.push(L.polygon(latlngs, { nogoWeight: nogoWeight }));
|
||||
}
|
||||
}
|
||||
return nogos;
|
||||
},
|
||||
|
||||
// formats L.LatLng object as lng,lat string
|
||||
_formatLatLng: function(latLng) {
|
||||
var s = '';
|
||||
s += L.Util.formatNum(latLng.lng, L.BRouter.PRECISION);
|
||||
s += L.Util.formatNum(latLng.lng || latLng[1], L.BRouter.PRECISION);
|
||||
s += L.BRouter.NUMBER_SEPARATOR;
|
||||
s += L.Util.formatNum(latLng.lat, L.BRouter.PRECISION);
|
||||
s += L.Util.formatNum(latLng.lat || latLng[0], L.BRouter.PRECISION);
|
||||
return s;
|
||||
}
|
||||
});
|
||||
|
||||
L.bRouter = function (options) {
|
||||
L.bRouter = function(options) {
|
||||
return new L.BRouter(options);
|
||||
};
|
||||
|
|
@ -24,6 +24,5 @@ var brouterCgi = (function() {
|
|||
|
||||
return {
|
||||
getUrl: getUrl
|
||||
}
|
||||
|
||||
};
|
||||
})();
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
(function() {
|
||||
|
||||
// COPYING: Please get your own API keys from the sites listed below
|
||||
|
||||
BR.keys = {
|
||||
|
|
@ -10,7 +9,12 @@
|
|||
digitalGlobe: '',
|
||||
|
||||
// Thunderforest, https://thunderforest.com/pricing/
|
||||
thunderforest: ''
|
||||
};
|
||||
thunderforest: '',
|
||||
|
||||
// Strava API token in case you want to display Strava segments
|
||||
strava: '',
|
||||
|
||||
// OpenMapSurfer (OpenRouteService API), https://openrouteservice.org/plans/
|
||||
openrouteservice: ''
|
||||
};
|
||||
})();
|
||||
|
|
|
|||
20
layers/collection/1010.geojson
Normal file
20
layers/collection/1010.geojson
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"name": "OpenStreetMap.se",
|
||||
"maxZoom": 18,
|
||||
"attribution": "Map data: © <a href=\"http://www.openstreetmap.org/copyright\" target=\"_blank\">OpenStreetMap</a> contributors, under ODbL | Tiles: © <a href=\"http://openstreetmap.se/\" target=\"_blank\">OpenStreetMap Sweden</a>",
|
||||
"id": "1010",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
"d",
|
||||
"e",
|
||||
"f"
|
||||
],
|
||||
"url": "http://{s}.tile.openstreetmap.se/hydda/full/{z}/{x}/{y}.png",
|
||||
"dataSource": "LayersCollection"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
12
layers/collection/1016.geojson
Normal file
12
layers/collection/1016.geojson
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"name": "4UMaps",
|
||||
"maxZoom": 15,
|
||||
"attribution": "Map data: © <a href=\"http://www.openstreetmap.org/copyright\" target=\"_blank\">OpenStreetMap</a> contributors, under ODbL | Tiles: © <a href=\"http://www.4umaps.eu/\">4UMaps</a>",
|
||||
"id": "1016",
|
||||
"url": "http://4umaps.eu/{z}/{x}/{y}.png",
|
||||
"dataSource": "LayersCollection"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
14
layers/collection/1017.geojson
Normal file
14
layers/collection/1017.geojson
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"name": "Osmapa.pl",
|
||||
"maxZoom": 20,
|
||||
"attribution": "Map data: © <a href=\"http://www.openstreetmap.org/copyright\" target=\"_blank\">OpenStreetMap</a> contributors, under ODbL | Tiles: © <a href=\"http://osmapa.pl/\" target=\"_blank\">Osmapa.pl</a>",
|
||||
"id": "1017",
|
||||
"threed": "true",
|
||||
"language": "pl",
|
||||
"url": "http://{s}.tile.openstreetmap.pl/osmapa.pl/{z}/{x}/{y}.png",
|
||||
"dataSource": "LayersCollection"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
14
layers/collection/1021.geojson
Normal file
14
layers/collection/1021.geojson
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"name": "Спутник",
|
||||
"maxZoom": 19,
|
||||
"attribution": "Map data: © <a href=\"http://www.openstreetmap.org/copyright\" target=\"_blank\">OpenStreetMap</a> contributors, under ODbL | Tiles: © <a href=\"http://maps.sputnik.ru/\" target=\"_blank\">Спутник</a>",
|
||||
"id": "1021",
|
||||
"threed": "true",
|
||||
"language": "ru",
|
||||
"url": "http://{s}.tiles.maps.sputnik.ru/{z}/{x}/{y}.png",
|
||||
"dataSource": "LayersCollection"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
19
layers/collection/1023.geojson
Normal file
19
layers/collection/1023.geojson
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"name": "Космоснимки",
|
||||
"maxZoom": 18,
|
||||
"attribution": "Map data: © <a href=\"http://www.openstreetmap.org/copyright\" target=\"_blank\">OpenStreetMap</a> contributors, under ODbL | Tiles: © <a href=\"http://osm.kosmosnimki.ru/\" target=\"_blank\">ScanEx</a>",
|
||||
"id": "1023",
|
||||
"subdomains": [
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
"d"
|
||||
],
|
||||
"language": "ru",
|
||||
"url": "http://{s}.tile.osm.kosmosnimki.ru/kosmo/{z}/{x}/{y}.png",
|
||||
"dataSource": "LayersCollection"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
12
layers/collection/1059.geojson
Normal file
12
layers/collection/1059.geojson
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"name": "ÖPNV Karte",
|
||||
"maxZoom": 18,
|
||||
"attribution": "Map data: © <a href=\"http://www.openstreetmap.org/copyright\" target=\"_blank\">OpenStreetMap</a> contributors, under ODbL | Tiles: © <a href=\"http://öpnvkarte.de/\" target=\"_blank\">ÖPNV Karte</a>",
|
||||
"id": "1059",
|
||||
"url": "http://tileserver.memomaps.de/tilegen/{z}/{x}/{y}.png",
|
||||
"dataSource": "LayersCollection"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
12
layers/collection/1061.geojson
Normal file
12
layers/collection/1061.geojson
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"name": "Thunderforest Outdoors",
|
||||
"maxZoom": 22,
|
||||
"attribution": "Map data: © <a href=\"http://www.openstreetmap.org/copyright\" target=\"_blank\">OpenStreetMap</a> contributors, under ODbL | Tiles: © <a href=\"http://www.thunderforest.com/\" target=\"_blank\">Andy Allan</a>",
|
||||
"id": "1061",
|
||||
"url": "http://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png",
|
||||
"dataSource": "LayersCollection"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
12
layers/collection/1065.geojson
Normal file
12
layers/collection/1065.geojson
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"name": "Hike & Bike",
|
||||
"maxZoom": 19,
|
||||
"attribution": "Map data: © <a href=\"http://www.openstreetmap.org/copyright\" target=\"_blank\">OpenStreetMap</a> contributors, under ODbL | Tiles: © <a href=\"http://hikebikemap.de/\" target=\"_blank\">Colin Marquardt</a>",
|
||||
"id": "1065",
|
||||
"url": "http://toolserver.org/tiles/hikebike/{z}/{x}/{y}.png",
|
||||
"dataSource": "LayersCollection"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
13
layers/collection/1069.geojson
Normal file
13
layers/collection/1069.geojson
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"name": "Refuges.info hiking",
|
||||
"maxZoom": 18,
|
||||
"attribution": "Map data: © <a href=\"http://www.openstreetmap.org/copyright\" target=\"_blank\">OpenStreetMap</a> contributors, under ODbL | Tiles: © <a href=\"http://maps.refuges.info/\" target=\"_blank\">sly</a>",
|
||||
"id": "1069",
|
||||
"old": "true",
|
||||
"url": "http://maps.refuges.info/hiking/{z}/{x}/{y}.png",
|
||||
"dataSource": "LayersCollection"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
53
layers/collection/extract.js
Normal file
53
layers/collection/extract.js
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const fetch = require('node-fetch');
|
||||
|
||||
const outDir = __dirname;
|
||||
|
||||
var includeList = [
|
||||
"1016", // 4UMaps
|
||||
"1065", // Hike & Bike Map
|
||||
"1061", // Thunderforest Outdoors
|
||||
"1021", // kosmosnimki.ru
|
||||
"1017", // sputnik.ru
|
||||
"1023", // Osmapa.pl - Mapa OpenStreetMap Polska
|
||||
"1010", // OpenStreetMap.se (Hydda.Full)
|
||||
"1069", // MRI (maps.refuges.info),
|
||||
"1059" // ÖPNV Karte
|
||||
];
|
||||
|
||||
function extract(constantsJs) {
|
||||
eval(constantsJs);
|
||||
|
||||
for (let i = 0; i < includeList.length; i++) {
|
||||
let id = includeList[i];
|
||||
|
||||
let layer = getLayerDataByID(id);
|
||||
if (!layer) {
|
||||
console.warn('Layer not found: ' + id);
|
||||
continue;
|
||||
}
|
||||
//console.log(`${layer.id}, ${layer.name}, ${layer.address}`);
|
||||
|
||||
layer.url = layer.address;
|
||||
delete layer.address;
|
||||
|
||||
let geoJson = {
|
||||
geometry: null,
|
||||
properties: layer,
|
||||
type: "Feature"
|
||||
};
|
||||
geoJson.properties.dataSource = 'LayersCollection';
|
||||
|
||||
const outFileName = path.join(outDir, layer.id + '.geojson');
|
||||
const data = JSON.stringify(geoJson, null, 2);
|
||||
fs.writeFileSync(outFileName, data);
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/Edward17/LayersCollection/blob/gh-pages/constants.js
|
||||
fetch('http://edward17.github.io/LayersCollection/constants.js')
|
||||
.then(res => res.text())
|
||||
.then(text => extract(text))
|
||||
.catch(err => console.error(err));
|
||||
38
layers/config/config.js
Normal file
38
layers/config/config.js
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
BR.confLayers = {};
|
||||
|
||||
BR.confLayers.defaultBaseLayers = [
|
||||
'standard',
|
||||
'OpenTopoMap',
|
||||
'Stamen.Terrain',
|
||||
'Esri.WorldImagery'
|
||||
];
|
||||
|
||||
// worldwide monolingual layers to add as default when browser language matches
|
||||
BR.confLayers.languageDefaultLayers = [
|
||||
'osm-mapnik-german_style',
|
||||
'osmfr',
|
||||
'1021' // sputnik.ru
|
||||
];
|
||||
|
||||
BR.confLayers.defaultOverlays = [
|
||||
'HikeBike.HillShading',
|
||||
'Waymarked_Trails-Cycling',
|
||||
'Waymarked_Trails-Hiking'
|
||||
];
|
||||
|
||||
BR.confLayers.legacyNameToIdMap = {
|
||||
'OpenStreetMap': 'standard',
|
||||
'OpenStreetMap.de': 'osm-mapnik-german_style',
|
||||
'OpenTopoMap': 'OpenTopoMap',
|
||||
'Esri World Imagery': 'Esri.WorldImagery',
|
||||
'Cycling (Waymarked Trails)': 'Waymarked_Trails-Cycling',
|
||||
'Hiking (Waymarked Trails)': 'Waymarked_Trails-Hiking'
|
||||
};
|
||||
|
||||
BR.confLayers.leafletProvidersIncludeList = [
|
||||
'Stamen.Terrain',
|
||||
'MtbMap',
|
||||
'OpenStreetMap.CH',
|
||||
'HikeBike.HillShading',
|
||||
'Esri.WorldImagery'
|
||||
];
|
||||
1475
layers/config/geometry.js
Normal file
1475
layers/config/geometry.js
Normal file
File diff suppressed because it is too large
Load diff
232
layers/config/overrides.js
Normal file
232
layers/config/overrides.js
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
BR.confLayers.getPropertyOverrides = function() {
|
||||
return {
|
||||
'standard': {
|
||||
'name': i18next.t('map.layer.osm'),
|
||||
'attribution': {
|
||||
'html': '© <a target="_blank" href="https://www.openstreetmap.org/copyright">openstreetmap.org</a>, <a target="_blank" href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA 2.0</a>'
|
||||
},
|
||||
'mapUrl': 'https://www.openstreetmap.org/#map={zoom}/{lat}/{lon}'
|
||||
},
|
||||
'OpenTopoMap': {
|
||||
'name': i18next.t('map.layer.topo'),
|
||||
'attribution': {
|
||||
'html': '© <a target="_blank" href="https://opentopomap.org/about#verwendung">OpenTopoMap</a>, <a target="_blank" href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA 3.0</a>; <a target="_blank" href="http://viewfinderpanoramas.org">SRTM</a>'
|
||||
},
|
||||
'mapUrl': 'https://opentopomap.org/#map={zoom}/{lat}/{lon}'
|
||||
},
|
||||
'Stamen.Terrain': {
|
||||
'name': i18next.t('map.layer.stamen-terrain'),
|
||||
'attribution': '© <a href="http://stamen.com">Stamen Design</a>, <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>',
|
||||
'mapUrl': 'http://maps.stamen.com/#terrain/{zoom}/{lat}/{lon}'
|
||||
},
|
||||
'Esri.WorldImagery': {
|
||||
'name': i18next.t('map.layer.esri'),
|
||||
'nameShort': i18next.t('credits.esri-tiles'),
|
||||
'attribution': i18next.t('credits.esri-license'),
|
||||
'mapUrl': 'http://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9'
|
||||
},
|
||||
'wikimedia-map': {
|
||||
'mapUrl': 'https://maps.wikimedia.org/#{zoom}/{lat}/{lon}'
|
||||
},
|
||||
'HDM_HOT': {
|
||||
'nameShort': 'HOT',
|
||||
'mapUrl': 'http://map.hotosm.org/#{zoom}/{lat}/{lon}'
|
||||
},
|
||||
// OpenStreetMap.se (Hydda.Full)
|
||||
'1010': {
|
||||
'mapUrl': 'https://maps.openstreetmap.se/#{zoom}/{lat}/{lon}'
|
||||
},
|
||||
'opencylemap': {
|
||||
'name': i18next.t('map.layer.cycle'),
|
||||
'nameShort': 'OpenCycleMap',
|
||||
// add Thunderforest API key variable
|
||||
'url': 'https://{switch:a,b,c}.tile.thunderforest.com/cycle/{zoom}/{x}/{y}.png?apikey={keys_thunderforest}',
|
||||
'mapUrl': 'https://www.opencyclemap.org/?zoom={zoom}&lat={lat}&lon={lon}&layers=B0000'
|
||||
},
|
||||
'1061': {
|
||||
'name': i18next.t('map.layer.outdoors'),
|
||||
'nameShort': 'Outdoors',
|
||||
'url': 'http://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png?apikey={keys_thunderforest}',
|
||||
'mapUrl': 'https://www.opencyclemap.org/?zoom={zoom}&lat={lat}&lon={lon}&layers=000B0'
|
||||
},
|
||||
// Hike & Bike Map
|
||||
'1065': {
|
||||
'mapUrl': 'http://hikebikemap.org/?zoom={zoom}&lat={lat}&lon={lon}&layer=HikeBikeMap'
|
||||
},
|
||||
// 4UMaps
|
||||
'1016': {
|
||||
'mapUrl': 'https://www.4umaps.com/map.htm?zoom={zoom}&lat={lat}&lon={lon}&layers=B00'
|
||||
},
|
||||
'openmapsurfer': {
|
||||
'mapUrl': 'https://maps.openrouteservice.org/directions?n1={lat}&n2={lon}&n3={zoom}&b=0&c=0&k1=en-US&k2=km'
|
||||
},
|
||||
// ÖPNV Karte
|
||||
'1059': {
|
||||
'name': 'Public transport (ÖPNVKarte)',
|
||||
'nameShort': 'ÖPNVKarte',
|
||||
'mapUrl': 'http://öpnvkarte.de/#{lon};{lat};{zoom}'
|
||||
},
|
||||
'osm-mapnik-german_style': {
|
||||
'name': i18next.t('map.layer.osmde'),
|
||||
'language_code': 'de',
|
||||
'attribution': {
|
||||
'html': '© <a target="_blank" href="https://openstreetmap.de/karte.html">openstreetmap.de</a>'
|
||||
},
|
||||
'mapUrl': 'https://www.openstreetmap.de/karte.html?zoom={zoom}&lat={lat}&lon={lon}&layers=B000TF'
|
||||
},
|
||||
'osmfr': {
|
||||
'language_code': 'fr',
|
||||
'nameShort': 'OSM French',
|
||||
'mapUrl': 'http://tile.openstreetmap.fr/?layers=B00000000FFFFFF&zoom={zoom}&lat={lat}&lon={lon}'
|
||||
},
|
||||
// kosmosnimki.ru
|
||||
'1023': {
|
||||
'language_code': 'ru',
|
||||
'mapUrl': 'http://kosmosnimki.ru/'
|
||||
},
|
||||
// sputnik.ru
|
||||
'1021': {
|
||||
'language_code': 'ru',
|
||||
'mapUrl': 'http://maps.sputnik.ru/?lat={lat}&lng={lon}&zoom={zoom}'
|
||||
},
|
||||
'MtbMap': {
|
||||
'mapUrl': 'http://mtbmap.cz/#zoom={zoom}&lat={lat}&lon={lon}',
|
||||
'worldTiles': true // -z12
|
||||
},
|
||||
// MRI (maps.refuges.info)
|
||||
'1069': {
|
||||
'nameShort': 'Refuges.info',
|
||||
'mapUrl': 'http://maps.refuges.info/?zoom={zoom}&lat={lat}&lon={lon}&layers=B',
|
||||
'worldTiles': true
|
||||
},
|
||||
'osmfr-basque': {
|
||||
'language_code': 'eu',
|
||||
'nameShort': 'OSM Basque',
|
||||
'mapUrl': 'http://tile.openstreetmap.fr/?layers=00000000BFFFFFF&zoom={zoom}&lat={lat}&lon={lon}',
|
||||
'worldTiles': true
|
||||
},
|
||||
'osmfr-breton': {
|
||||
'language_code': 'br',
|
||||
'nameShort': 'OSM Breton',
|
||||
'mapUrl': 'https://kartenn.openstreetmap.bzh/#map={zoom}/{lat}/{lon}',
|
||||
'worldTiles': true
|
||||
},
|
||||
'osmfr-occitan': {
|
||||
'language_code': 'oc',
|
||||
'nameShort': 'OSM Occitan',
|
||||
'mapUrl': 'http://tile.openstreetmap.fr/?layers=0000000B0FFFFFF&zoom={zoom}&lat={lat}&lon={lon}',
|
||||
'worldTiles': true
|
||||
},
|
||||
'osmbe': {
|
||||
'nameShort': 'OSM Belgium',
|
||||
'mapUrl': 'https://tile.osm.be/#map={zoom}/{lat}/{lon}',
|
||||
'worldTiles': true // -z7
|
||||
},
|
||||
'osmbe-fr': {
|
||||
'nameShort': 'OSM Belgium (fr)',
|
||||
'mapUrl': 'https://tile.osm.be/#map={zoom}/{lat}/{lon}',
|
||||
'worldTiles': true // -z7
|
||||
},
|
||||
'osmbe-nl': {
|
||||
'nameShort': 'OSM Belgium (nl)',
|
||||
'mapUrl': 'https://tile.osm.be/#map={zoom}/{lat}/{lon}',
|
||||
'worldTiles': true // -z7
|
||||
},
|
||||
'OpenStreetMap.CH': {
|
||||
'country_code': 'CH',
|
||||
'mapUrl': 'https://osm.ch/#{zoom}/{lat}/{lon}',
|
||||
'worldTiles': true
|
||||
},
|
||||
'topplus-open': {
|
||||
'country_code': 'DE',
|
||||
'mapUrl': 'http://www.geodatenzentrum.de/geodaten/gdz_rahmen.gdz_div?gdz_spr=deu&gdz_user_id=0&gdz_akt_zeile=5&gdz_anz_zeile=1&gdz_unt_zeile=41',
|
||||
'worldTiles': true // World -z9, Europe -z14
|
||||
},
|
||||
|
||||
'OpenStreetMap-turistautak': {
|
||||
'nameShort': 'OSM Turistautak',
|
||||
'mapUrl': 'https://turistautak.openstreetmap.hu/?zoom={zoom}&lat={lat}&lon={lon}&layers=0B00F'
|
||||
},
|
||||
'Israel_Hiking': {
|
||||
'mapUrl': 'https://israelhiking.osm.org.il/map/{zoom}/{lat}/{lon}'
|
||||
},
|
||||
'Israel_MTB': {
|
||||
'mapUrl': 'https://israelhiking.osm.org.il/map/{zoom}/{lat}/{lon}'
|
||||
},
|
||||
'mtbmap-no': {
|
||||
'mapUrl': 'https://mtbmap.no/#{zoom}/{lat}/{lon}'
|
||||
},
|
||||
// Osmapa.pl - Mapa OpenStreetMap Polska
|
||||
'1017': {
|
||||
"country_code": "PL",
|
||||
'language_code': 'pl',
|
||||
'mapUrl': 'http://osmapa.pl/#lat={lat}&lon={lon}&z={zoom}&m=os',
|
||||
'worldTiles': true // -z13
|
||||
},
|
||||
'Freemap.sk-Car': {
|
||||
'mapUrl': 'https://www.freemap.sk/?map={zoom}/{lat}/{lon}&layers=A'
|
||||
},
|
||||
'Freemap.sk-Hiking': {
|
||||
'mapUrl': 'https://www.freemap.sk/?map={zoom}/{lat}/{lon}&layers=T'
|
||||
},
|
||||
'Freemap.sk-Cyclo': {
|
||||
'mapUrl': 'https://www.freemap.sk/?map={zoom}/{lat}/{lon}&layers=C'
|
||||
},
|
||||
'osm-cambodia_laos_thailand_vietnam-bilingual': {
|
||||
'country_code': 'TH+',
|
||||
'nameShort': 'Thaimap',
|
||||
'mapUrl': 'http://thaimap.osm-tools.org/?zoom={zoom}&lat={lat}&lon={lon}&layers=BT',
|
||||
'worldTiles': true
|
||||
},
|
||||
'HikeBike.HillShading': {
|
||||
'name': i18next.t('map.layer.hikebike-hillshading'),
|
||||
'nameShort': i18next.t('map.hikebike-hillshading'),
|
||||
'attribution': '© <a target="_blank" href="http://hikebikemap.org">hikebikemap.org</a>; SRTM3 v2 (<a target="_blank" href="http://www2.jpl.nasa.gov/srtm/">NASA</a>)',
|
||||
'mapUrl': 'http://hikebikemap.org/?zoom={zoom}&lat={lat}&lon={lon}&layer=HikeBikeMap',
|
||||
'overlay': true
|
||||
},
|
||||
'Waymarked_Trails-Cycling': {
|
||||
'name': i18next.t('map.layer.cycling'),
|
||||
'nameShort': i18next.t('map.cycling'),
|
||||
'attribution': {
|
||||
'html': '© <a target="_blank" href="https://cycling.waymarkedtrails.org/en/help/legal">waymarkedtrails.org</a>, <a target="_blank" href="https://creativecommons.org/licenses/by-sa/3.0/de/deed.en">CC-BY-SA 3.0 DE</a>'
|
||||
},
|
||||
'mapUrl': 'http://cycling.waymarkedtrails.org/#?map={zoom}!{lat}!{lon}'
|
||||
},
|
||||
'Waymarked_Trails-Hiking': {
|
||||
'name': i18next.t('map.layer.hiking'),
|
||||
'nameShort': i18next.t('map.hiking'),
|
||||
'attribution': {
|
||||
'html': '© <a target="_blank" href="https://hiking.waymarkedtrails.org/en/help/legal">waymarkedtrails.org</a>, <a target="_blank" href="https://creativecommons.org/licenses/by-sa/3.0/de/deed.en">CC-BY-SA 3.0 DE</a>'
|
||||
},
|
||||
'mapUrl': 'http://hiking.waymarkedtrails.org/#?map={zoom}!{lat}!{lon}'
|
||||
},
|
||||
'Waymarked_Trails-MTB': {
|
||||
'nameShort': 'MTB',
|
||||
'mapUrl': 'http://mtb.waymarkedtrails.org/#?map={zoom}!{lat}!{lon}'
|
||||
},
|
||||
'mapillary-coverage-raster': {
|
||||
'nameShort': 'Mapillary',
|
||||
'mapUrl': 'https://www.mapillary.com/app/?lat={lat}&lng={lon}&z={zoom}&menu=false'
|
||||
},
|
||||
'openpt_map': {
|
||||
'nameShort': 'openptmap',
|
||||
'mapUrl': 'http://openptmap.org/?zoom={zoom}&lat={lat}&lon={lon}&layers=B0000TFT'
|
||||
},
|
||||
'historic-place-contours': {
|
||||
'mapUrl': 'http://gk.historic.place/historische_objekte/?zoom={zoom}&lat={lat}&lon={lon}&pid=GhHaSaHe'
|
||||
},
|
||||
'hu-hillshade': {
|
||||
'nameShort': 'Hillshade HU',
|
||||
'mapUrl': 'http://map.turistautak.hu/?zoom={zoom}&lat={lat}&lon={lon}&layers=0B000FTF'
|
||||
},
|
||||
'mapaszlakow-cycle': {
|
||||
'nameShort': 'Cycleways PL',
|
||||
'mapUrl': 'http://mapaszlakow.eu/#{zoom}/{lat}/{lon}'
|
||||
},
|
||||
'mapaszlakow-routes': {
|
||||
'nameShort': 'Routes PL',
|
||||
'mapUrl': 'http://mapaszlakow.eu/#{zoom}/{lat}/{lon}'
|
||||
}
|
||||
};
|
||||
};
|
||||
82
layers/config/tree.js
Normal file
82
layers/config/tree.js
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
BR.confLayers.tree = {
|
||||
'base-layers': {
|
||||
'worldwide-international': [
|
||||
'standard',
|
||||
'OpenTopoMap',
|
||||
'Stamen.Terrain',
|
||||
'Esri.WorldImagery',
|
||||
'wikimedia-map',
|
||||
'HDM_HOT',
|
||||
'1010', // OpenStreetMap.se (Hydda.Full)
|
||||
'opencylemap',
|
||||
'1061', // Thunderforest Outdoors
|
||||
'1065', // Hike & Bike Map
|
||||
'1016', // 4UMaps,
|
||||
'openmapsurfer',
|
||||
'1059' // ÖPNV Karte
|
||||
],
|
||||
'worldwide-monolingual': [
|
||||
'osm-mapnik-german_style',
|
||||
'osmfr',
|
||||
'1023', // kosmosnimki.ru
|
||||
'1021' // sputnik.ru
|
||||
],
|
||||
'europe': [
|
||||
'MtbMap',
|
||||
'1069' // MRI (maps.refuges.info)
|
||||
],
|
||||
'europe-monolingual': [
|
||||
'osmfr-basque',
|
||||
'osmfr-breton',
|
||||
'osmfr-occitan'
|
||||
],
|
||||
'country': [
|
||||
{
|
||||
'BE': [
|
||||
'osmbe',
|
||||
'osmbe-fr',
|
||||
'osmbe-nl',
|
||||
]
|
||||
},
|
||||
'OpenStreetMap.CH',
|
||||
'topplus-open',
|
||||
'OpenStreetMap-turistautak',
|
||||
{
|
||||
'IL': [
|
||||
'Israel_Hiking',
|
||||
'Israel_MTB',
|
||||
]
|
||||
},
|
||||
'mtbmap-no',
|
||||
'1017', // Osmapa.pl - Mapa OpenStreetMap Polska
|
||||
{
|
||||
'SK': [
|
||||
'Freemap.sk-Car',
|
||||
'Freemap.sk-Hiking',
|
||||
'Freemap.sk-Cyclo',
|
||||
]
|
||||
},
|
||||
'osm-cambodia_laos_thailand_vietnam-bilingual'
|
||||
]
|
||||
},
|
||||
'overlays': {
|
||||
'worldwide': [
|
||||
'HikeBike.HillShading',
|
||||
'Waymarked_Trails-Cycling',
|
||||
'Waymarked_Trails-Hiking',
|
||||
'Waymarked_Trails-MTB',
|
||||
'mapillary-coverage-raster',
|
||||
'openpt_map'
|
||||
],
|
||||
'country': [
|
||||
'historic-place-contours',
|
||||
'hu-hillshade',
|
||||
{
|
||||
'PL': [
|
||||
'mapaszlakow-cycle',
|
||||
'mapaszlakow-routes'
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
45
layers/extra/historic-place-contours.geojson
Normal file
45
layers/extra/historic-place-contours.geojson
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
5.45,
|
||||
45
|
||||
],
|
||||
[
|
||||
17,
|
||||
45
|
||||
],
|
||||
[
|
||||
17,
|
||||
56.27
|
||||
],
|
||||
[
|
||||
5.45,
|
||||
56.27
|
||||
],
|
||||
[
|
||||
5.45,
|
||||
45
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
},
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"html": "<a href=\"https://www.eea.europa.eu/data-and-maps/data/eu-dem\" target=\"_blank\" rel=\"noopener\">Produced using Copernicus data and information funded by the European Union - EU-DEM layers</a>, download from <a href=\"http://opendem.info/index.html\" target=\"_blank\">OpenDEM</a>, Data sources <a href=\"https://www2.jpl.nasa.gov/srtm/\" target=\"_blank\">SRTM</a>, <a href=\"https://asterweb.jpl.nasa.gov/gdem.asp\" target=\"_blank\">ASTER GDEM</a>, Tiles from <a href=\"http://www.historic.place/\" target=\"_blank\" rel=\"noopener\">Historic.Place</a>"
|
||||
},
|
||||
"country_code": "DACH",
|
||||
"id": "historic-place-contours",
|
||||
"min_zoom": 12,
|
||||
"max_zoom": 15,
|
||||
"name": "Contours DACH",
|
||||
"overlay": true,
|
||||
"type": "tms",
|
||||
"url": "http://tiles.historic.place/ele/de/{zoom}/{x}/{y}.png",
|
||||
"valid-georeference": true
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
412
layers/extra/mapaszlakow/mapaszlakow-cycle.geojson
Normal file
412
layers/extra/mapaszlakow/mapaszlakow-cycle.geojson
Normal file
|
|
@ -0,0 +1,412 @@
|
|||
{
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
15.9751041,
|
||||
54.3709213
|
||||
],
|
||||
[
|
||||
16.311164,
|
||||
54.5561775
|
||||
],
|
||||
[
|
||||
17.1391878,
|
||||
54.7845723
|
||||
],
|
||||
[
|
||||
18.3448458,
|
||||
54.9022727
|
||||
],
|
||||
[
|
||||
19.6613689,
|
||||
54.4737213
|
||||
],
|
||||
[
|
||||
20.2815206,
|
||||
54.4213456
|
||||
],
|
||||
[
|
||||
21.4663914,
|
||||
54.3406369
|
||||
],
|
||||
[
|
||||
22.7759855,
|
||||
54.3769755
|
||||
],
|
||||
[
|
||||
22.8625989,
|
||||
54.4233613
|
||||
],
|
||||
[
|
||||
23.2956657,
|
||||
54.2678633
|
||||
],
|
||||
[
|
||||
23.5347186,
|
||||
54.0955258
|
||||
],
|
||||
[
|
||||
23.5208604,
|
||||
53.9775182
|
||||
],
|
||||
[
|
||||
23.7183389,
|
||||
53.4629603
|
||||
],
|
||||
[
|
||||
23.9296755,
|
||||
53.1856735
|
||||
],
|
||||
[
|
||||
23.9296755,
|
||||
52.6887269
|
||||
],
|
||||
[
|
||||
23.732197,
|
||||
52.6067497
|
||||
],
|
||||
[
|
||||
23.5658994,
|
||||
52.5878101
|
||||
],
|
||||
[
|
||||
23.2090523,
|
||||
52.3302642
|
||||
],
|
||||
[
|
||||
23.1951942,
|
||||
52.2370089
|
||||
],
|
||||
[
|
||||
23.5035377,
|
||||
52.1860596
|
||||
],
|
||||
[
|
||||
23.6906226,
|
||||
52.0030113
|
||||
],
|
||||
[
|
||||
23.5970802,
|
||||
51.739903
|
||||
],
|
||||
[
|
||||
23.6629063,
|
||||
51.3888562
|
||||
],
|
||||
[
|
||||
23.9366046,
|
||||
50.9827781
|
||||
],
|
||||
[
|
||||
24.1687284,
|
||||
50.8604752
|
||||
],
|
||||
[
|
||||
24.0197534,
|
||||
50.8035823
|
||||
],
|
||||
[
|
||||
24.1098313,
|
||||
50.6610467
|
||||
],
|
||||
[
|
||||
24.0578633,
|
||||
50.4188439
|
||||
],
|
||||
[
|
||||
23.6178674,
|
||||
50.3083403
|
||||
],
|
||||
[
|
||||
22.6824431,
|
||||
49.5163532
|
||||
],
|
||||
[
|
||||
22.7378756,
|
||||
49.2094935
|
||||
],
|
||||
[
|
||||
22.9041733,
|
||||
49.0780441
|
||||
],
|
||||
[
|
||||
22.8625989,
|
||||
48.9940062
|
||||
],
|
||||
[
|
||||
22.6096878,
|
||||
49.0371785
|
||||
],
|
||||
[
|
||||
22.0761495,
|
||||
49.2004392
|
||||
],
|
||||
[
|
||||
21.8474902,
|
||||
49.3721872
|
||||
],
|
||||
[
|
||||
21.3763135,
|
||||
49.4488281
|
||||
],
|
||||
[
|
||||
21.1026153,
|
||||
49.3721872
|
||||
],
|
||||
[
|
||||
20.9120659,
|
||||
49.3022043
|
||||
],
|
||||
[
|
||||
20.6452967,
|
||||
49.3902311
|
||||
],
|
||||
[
|
||||
20.1845136,
|
||||
49.3315641
|
||||
],
|
||||
[
|
||||
20.1186875,
|
||||
49.2004392
|
||||
],
|
||||
[
|
||||
19.9419962,
|
||||
49.1302123
|
||||
],
|
||||
[
|
||||
19.765305,
|
||||
49.2117568
|
||||
],
|
||||
[
|
||||
19.7479823,
|
||||
49.3992506
|
||||
],
|
||||
[
|
||||
19.6024718,
|
||||
49.4150307
|
||||
],
|
||||
[
|
||||
19.5089294,
|
||||
49.5815389
|
||||
],
|
||||
[
|
||||
19.4292451,
|
||||
49.5905232
|
||||
],
|
||||
[
|
||||
19.2317666,
|
||||
49.4150307
|
||||
],
|
||||
[
|
||||
18.9961783,
|
||||
49.387976
|
||||
],
|
||||
[
|
||||
18.9338167,
|
||||
49.4916048
|
||||
],
|
||||
[
|
||||
18.8368097,
|
||||
49.4938552
|
||||
],
|
||||
[
|
||||
18.8021643,
|
||||
49.6623381
|
||||
],
|
||||
[
|
||||
18.6427958,
|
||||
49.7094091
|
||||
],
|
||||
[
|
||||
18.521537,
|
||||
49.8994693
|
||||
],
|
||||
[
|
||||
18.0815412,
|
||||
50.0109209
|
||||
],
|
||||
[
|
||||
17.8875272,
|
||||
49.9886512
|
||||
],
|
||||
[
|
||||
17.7385522,
|
||||
50.0687739
|
||||
],
|
||||
[
|
||||
17.6068999,
|
||||
50.1709584
|
||||
],
|
||||
[
|
||||
17.7454813,
|
||||
50.2153184
|
||||
],
|
||||
[
|
||||
17.710836,
|
||||
50.3017019
|
||||
],
|
||||
[
|
||||
17.4163505,
|
||||
50.2640668
|
||||
],
|
||||
[
|
||||
16.9486384,
|
||||
50.4453265
|
||||
],
|
||||
[
|
||||
16.8932058,
|
||||
50.4033889
|
||||
],
|
||||
[
|
||||
17.0006064,
|
||||
50.3105529
|
||||
],
|
||||
[
|
||||
17.017929,
|
||||
50.2241854
|
||||
],
|
||||
[
|
||||
16.8135215,
|
||||
50.186489
|
||||
],
|
||||
[
|
||||
16.6402948,
|
||||
50.0976742
|
||||
],
|
||||
[
|
||||
16.4324227,
|
||||
50.2862087
|
||||
],
|
||||
[
|
||||
16.1968344,
|
||||
50.4276731
|
||||
],
|
||||
[
|
||||
16.4220291,
|
||||
50.5885165
|
||||
],
|
||||
[
|
||||
16.3388803,
|
||||
50.6632429
|
||||
],
|
||||
[
|
||||
16.2280152,
|
||||
50.6368824
|
||||
],
|
||||
[
|
||||
16.0547884,
|
||||
50.6127057
|
||||
],
|
||||
[
|
||||
15.5732181,
|
||||
50.7641544
|
||||
],
|
||||
[
|
||||
15.2683391,
|
||||
50.8976368
|
||||
],
|
||||
[
|
||||
15.2440873,
|
||||
50.980597
|
||||
],
|
||||
[
|
||||
15.0292862,
|
||||
51.0133036
|
||||
],
|
||||
[
|
||||
15.0015699,
|
||||
50.8582883
|
||||
],
|
||||
[
|
||||
14.8110205,
|
||||
50.8735944
|
||||
],
|
||||
[
|
||||
14.956531,
|
||||
51.0721176
|
||||
],
|
||||
[
|
||||
15.0188926,
|
||||
51.2914636
|
||||
],
|
||||
[
|
||||
14.9392083,
|
||||
51.4601459
|
||||
],
|
||||
[
|
||||
14.7209426,
|
||||
51.5571799
|
||||
],
|
||||
[
|
||||
14.7521234,
|
||||
51.6260562
|
||||
],
|
||||
[
|
||||
14.5996839,
|
||||
51.8427626
|
||||
],
|
||||
[
|
||||
14.70362,
|
||||
52.0733396
|
||||
],
|
||||
[
|
||||
14.5581095,
|
||||
52.2497371
|
||||
],
|
||||
[
|
||||
14.5165351,
|
||||
52.425436
|
||||
],
|
||||
[
|
||||
14.6031485,
|
||||
52.5878101
|
||||
],
|
||||
[
|
||||
14.1146491,
|
||||
52.8208272
|
||||
],
|
||||
[
|
||||
14.152759,
|
||||
52.9733951
|
||||
],
|
||||
[
|
||||
14.3502374,
|
||||
53.0734212
|
||||
],
|
||||
[
|
||||
14.4229927,
|
||||
53.2665624
|
||||
],
|
||||
[
|
||||
14.1977979,
|
||||
53.8734759
|
||||
],
|
||||
[
|
||||
14.2220497,
|
||||
53.9958517
|
||||
],
|
||||
[
|
||||
15.9751041,
|
||||
54.3709213
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
},
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"text": "Tiles © OSM Mapa Szlaków",
|
||||
"url": "http://mapaszlakow.eu/"
|
||||
},
|
||||
"country_code": "PL",
|
||||
"id": "mapaszlakow-cycle",
|
||||
"max_zoom": 16,
|
||||
"min_zoom": 6,
|
||||
"name": "Cycleways (Mapa Szlaków)",
|
||||
"overlay": true,
|
||||
"type": "tms",
|
||||
"url": "http://mapaszlakow.eu/c{zoom}/{zoom}/{x}/{y}.png"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
412
layers/extra/mapaszlakow/mapaszlakow-routes.geojson
Normal file
412
layers/extra/mapaszlakow/mapaszlakow-routes.geojson
Normal file
|
|
@ -0,0 +1,412 @@
|
|||
{
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
15.9751041,
|
||||
54.3709213
|
||||
],
|
||||
[
|
||||
16.311164,
|
||||
54.5561775
|
||||
],
|
||||
[
|
||||
17.1391878,
|
||||
54.7845723
|
||||
],
|
||||
[
|
||||
18.3448458,
|
||||
54.9022727
|
||||
],
|
||||
[
|
||||
19.6613689,
|
||||
54.4737213
|
||||
],
|
||||
[
|
||||
20.2815206,
|
||||
54.4213456
|
||||
],
|
||||
[
|
||||
21.4663914,
|
||||
54.3406369
|
||||
],
|
||||
[
|
||||
22.7759855,
|
||||
54.3769755
|
||||
],
|
||||
[
|
||||
22.8625989,
|
||||
54.4233613
|
||||
],
|
||||
[
|
||||
23.2956657,
|
||||
54.2678633
|
||||
],
|
||||
[
|
||||
23.5347186,
|
||||
54.0955258
|
||||
],
|
||||
[
|
||||
23.5208604,
|
||||
53.9775182
|
||||
],
|
||||
[
|
||||
23.7183389,
|
||||
53.4629603
|
||||
],
|
||||
[
|
||||
23.9296755,
|
||||
53.1856735
|
||||
],
|
||||
[
|
||||
23.9296755,
|
||||
52.6887269
|
||||
],
|
||||
[
|
||||
23.732197,
|
||||
52.6067497
|
||||
],
|
||||
[
|
||||
23.5658994,
|
||||
52.5878101
|
||||
],
|
||||
[
|
||||
23.2090523,
|
||||
52.3302642
|
||||
],
|
||||
[
|
||||
23.1951942,
|
||||
52.2370089
|
||||
],
|
||||
[
|
||||
23.5035377,
|
||||
52.1860596
|
||||
],
|
||||
[
|
||||
23.6906226,
|
||||
52.0030113
|
||||
],
|
||||
[
|
||||
23.5970802,
|
||||
51.739903
|
||||
],
|
||||
[
|
||||
23.6629063,
|
||||
51.3888562
|
||||
],
|
||||
[
|
||||
23.9366046,
|
||||
50.9827781
|
||||
],
|
||||
[
|
||||
24.1687284,
|
||||
50.8604752
|
||||
],
|
||||
[
|
||||
24.0197534,
|
||||
50.8035823
|
||||
],
|
||||
[
|
||||
24.1098313,
|
||||
50.6610467
|
||||
],
|
||||
[
|
||||
24.0578633,
|
||||
50.4188439
|
||||
],
|
||||
[
|
||||
23.6178674,
|
||||
50.3083403
|
||||
],
|
||||
[
|
||||
22.6824431,
|
||||
49.5163532
|
||||
],
|
||||
[
|
||||
22.7378756,
|
||||
49.2094935
|
||||
],
|
||||
[
|
||||
22.9041733,
|
||||
49.0780441
|
||||
],
|
||||
[
|
||||
22.8625989,
|
||||
48.9940062
|
||||
],
|
||||
[
|
||||
22.6096878,
|
||||
49.0371785
|
||||
],
|
||||
[
|
||||
22.0761495,
|
||||
49.2004392
|
||||
],
|
||||
[
|
||||
21.8474902,
|
||||
49.3721872
|
||||
],
|
||||
[
|
||||
21.3763135,
|
||||
49.4488281
|
||||
],
|
||||
[
|
||||
21.1026153,
|
||||
49.3721872
|
||||
],
|
||||
[
|
||||
20.9120659,
|
||||
49.3022043
|
||||
],
|
||||
[
|
||||
20.6452967,
|
||||
49.3902311
|
||||
],
|
||||
[
|
||||
20.1845136,
|
||||
49.3315641
|
||||
],
|
||||
[
|
||||
20.1186875,
|
||||
49.2004392
|
||||
],
|
||||
[
|
||||
19.9419962,
|
||||
49.1302123
|
||||
],
|
||||
[
|
||||
19.765305,
|
||||
49.2117568
|
||||
],
|
||||
[
|
||||
19.7479823,
|
||||
49.3992506
|
||||
],
|
||||
[
|
||||
19.6024718,
|
||||
49.4150307
|
||||
],
|
||||
[
|
||||
19.5089294,
|
||||
49.5815389
|
||||
],
|
||||
[
|
||||
19.4292451,
|
||||
49.5905232
|
||||
],
|
||||
[
|
||||
19.2317666,
|
||||
49.4150307
|
||||
],
|
||||
[
|
||||
18.9961783,
|
||||
49.387976
|
||||
],
|
||||
[
|
||||
18.9338167,
|
||||
49.4916048
|
||||
],
|
||||
[
|
||||
18.8368097,
|
||||
49.4938552
|
||||
],
|
||||
[
|
||||
18.8021643,
|
||||
49.6623381
|
||||
],
|
||||
[
|
||||
18.6427958,
|
||||
49.7094091
|
||||
],
|
||||
[
|
||||
18.521537,
|
||||
49.8994693
|
||||
],
|
||||
[
|
||||
18.0815412,
|
||||
50.0109209
|
||||
],
|
||||
[
|
||||
17.8875272,
|
||||
49.9886512
|
||||
],
|
||||
[
|
||||
17.7385522,
|
||||
50.0687739
|
||||
],
|
||||
[
|
||||
17.6068999,
|
||||
50.1709584
|
||||
],
|
||||
[
|
||||
17.7454813,
|
||||
50.2153184
|
||||
],
|
||||
[
|
||||
17.710836,
|
||||
50.3017019
|
||||
],
|
||||
[
|
||||
17.4163505,
|
||||
50.2640668
|
||||
],
|
||||
[
|
||||
16.9486384,
|
||||
50.4453265
|
||||
],
|
||||
[
|
||||
16.8932058,
|
||||
50.4033889
|
||||
],
|
||||
[
|
||||
17.0006064,
|
||||
50.3105529
|
||||
],
|
||||
[
|
||||
17.017929,
|
||||
50.2241854
|
||||
],
|
||||
[
|
||||
16.8135215,
|
||||
50.186489
|
||||
],
|
||||
[
|
||||
16.6402948,
|
||||
50.0976742
|
||||
],
|
||||
[
|
||||
16.4324227,
|
||||
50.2862087
|
||||
],
|
||||
[
|
||||
16.1968344,
|
||||
50.4276731
|
||||
],
|
||||
[
|
||||
16.4220291,
|
||||
50.5885165
|
||||
],
|
||||
[
|
||||
16.3388803,
|
||||
50.6632429
|
||||
],
|
||||
[
|
||||
16.2280152,
|
||||
50.6368824
|
||||
],
|
||||
[
|
||||
16.0547884,
|
||||
50.6127057
|
||||
],
|
||||
[
|
||||
15.5732181,
|
||||
50.7641544
|
||||
],
|
||||
[
|
||||
15.2683391,
|
||||
50.8976368
|
||||
],
|
||||
[
|
||||
15.2440873,
|
||||
50.980597
|
||||
],
|
||||
[
|
||||
15.0292862,
|
||||
51.0133036
|
||||
],
|
||||
[
|
||||
15.0015699,
|
||||
50.8582883
|
||||
],
|
||||
[
|
||||
14.8110205,
|
||||
50.8735944
|
||||
],
|
||||
[
|
||||
14.956531,
|
||||
51.0721176
|
||||
],
|
||||
[
|
||||
15.0188926,
|
||||
51.2914636
|
||||
],
|
||||
[
|
||||
14.9392083,
|
||||
51.4601459
|
||||
],
|
||||
[
|
||||
14.7209426,
|
||||
51.5571799
|
||||
],
|
||||
[
|
||||
14.7521234,
|
||||
51.6260562
|
||||
],
|
||||
[
|
||||
14.5996839,
|
||||
51.8427626
|
||||
],
|
||||
[
|
||||
14.70362,
|
||||
52.0733396
|
||||
],
|
||||
[
|
||||
14.5581095,
|
||||
52.2497371
|
||||
],
|
||||
[
|
||||
14.5165351,
|
||||
52.425436
|
||||
],
|
||||
[
|
||||
14.6031485,
|
||||
52.5878101
|
||||
],
|
||||
[
|
||||
14.1146491,
|
||||
52.8208272
|
||||
],
|
||||
[
|
||||
14.152759,
|
||||
52.9733951
|
||||
],
|
||||
[
|
||||
14.3502374,
|
||||
53.0734212
|
||||
],
|
||||
[
|
||||
14.4229927,
|
||||
53.2665624
|
||||
],
|
||||
[
|
||||
14.1977979,
|
||||
53.8734759
|
||||
],
|
||||
[
|
||||
14.2220497,
|
||||
53.9958517
|
||||
],
|
||||
[
|
||||
15.9751041,
|
||||
54.3709213
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
},
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"text": "Tiles © OSM Mapa Szlaków",
|
||||
"url": "http://mapaszlakow.eu/"
|
||||
},
|
||||
"country_code": "PL",
|
||||
"id": "mapaszlakow-routes",
|
||||
"max_zoom": 16,
|
||||
"min_zoom": 6,
|
||||
"name": "Routes (Mapa Szlaków)",
|
||||
"overlay": true,
|
||||
"type": "tms",
|
||||
"url": "http://mapaszlakow.eu/b{zoom}/{zoom}/{x}/{y}.png"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
17
layers/extra/mapillary-coverage-raster.geojson
Normal file
17
layers/extra/mapillary-coverage-raster.geojson
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"text": "Mapillary, CC BY",
|
||||
"url": "https://www.mapillary.com"
|
||||
},
|
||||
"id": "mapillary-coverage-raster",
|
||||
"max_zoom": 17,
|
||||
"name": "Mapillary Coverage",
|
||||
"overlay": true,
|
||||
"type": "tms",
|
||||
"url": "https://d6a1v2w10ny40.cloudfront.net/v0.1/{z}/{x}/{y}.png"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
|
||||
15
layers/extra/openmapsurfer.geojson
Normal file
15
layers/extra/openmapsurfer.geojson
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"html": "<a href=\"https://giscience.uni-hd.de\" target=\"_blank\" rel=\"noopener\">GIScience Research Group</a> @ University of Heidelberg (<a href=\"https://openrouteservice.org/\" target=\"_blank\" rel=\"noopener\">info</a>)"
|
||||
},
|
||||
"id": "openmapsurfer",
|
||||
"max_zoom": 19,
|
||||
"name": "OpenMapSurfer",
|
||||
"type": "tms",
|
||||
"url": "https://api.openrouteservice.org/mapsurfer/{zoom}/{x}/{y}.png?api_key={keys_openrouteservice}"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
|
||||
42
layers/extra/topplus-open.geojson
Normal file
42
layers/extra/topplus-open.geojson
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
4.219,
|
||||
46.317
|
||||
],
|
||||
[
|
||||
16.875,
|
||||
46.317
|
||||
],
|
||||
[
|
||||
16.875,
|
||||
55.776
|
||||
],
|
||||
[
|
||||
4.219,
|
||||
55.776
|
||||
],
|
||||
[
|
||||
4.219,
|
||||
46.317
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
},
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"html": "© <a href=\"http://www.bkg.bund.de\" target=\"_blank\" rel=\"noopener\">Bundesamt für Kartographie und Geodäsie</a> 2018, <a href=\"http://sg.geodatenzentrum.de/web_public/Datenquellen_TopPlus_Open.pdf\" target=\"_blank\" rel=\"noopener\">Datenquellen</a>"
|
||||
},
|
||||
"id": "topplus-open",
|
||||
"name": "TopPlusOpen",
|
||||
"type": "wms",
|
||||
"url": "http://sgx.geodatenzentrum.de/wms_topplus_web_open",
|
||||
"layers": "web",
|
||||
"format": "image/png"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
|
||||
210
layers/josm/Freemap.sk-Car.geojson
Normal file
210
layers/josm/Freemap.sk-Car.geojson
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
{
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
19.83682,
|
||||
49.25529
|
||||
],
|
||||
[
|
||||
19.80075,
|
||||
49.42385
|
||||
],
|
||||
[
|
||||
19.60437,
|
||||
49.48058
|
||||
],
|
||||
[
|
||||
19.49179,
|
||||
49.63961
|
||||
],
|
||||
[
|
||||
19.21831,
|
||||
49.52604
|
||||
],
|
||||
[
|
||||
19.16778,
|
||||
49.42521
|
||||
],
|
||||
[
|
||||
19.00308,
|
||||
49.42236
|
||||
],
|
||||
[
|
||||
18.97611,
|
||||
49.5308
|
||||
],
|
||||
[
|
||||
18.54685,
|
||||
49.51425
|
||||
],
|
||||
[
|
||||
18.31432,
|
||||
49.33818
|
||||
],
|
||||
[
|
||||
18.15913,
|
||||
49.2961
|
||||
],
|
||||
[
|
||||
18.05564,
|
||||
49.11134
|
||||
],
|
||||
[
|
||||
17.56396,
|
||||
48.84938
|
||||
],
|
||||
[
|
||||
17.17929,
|
||||
48.88816
|
||||
],
|
||||
[
|
||||
17.058,
|
||||
48.81105
|
||||
],
|
||||
[
|
||||
16.90426,
|
||||
48.61947
|
||||
],
|
||||
[
|
||||
16.79685,
|
||||
48.38561
|
||||
],
|
||||
[
|
||||
17.06762,
|
||||
48.01116
|
||||
],
|
||||
[
|
||||
17.32787,
|
||||
47.97749
|
||||
],
|
||||
[
|
||||
17.51699,
|
||||
47.82535
|
||||
],
|
||||
[
|
||||
17.74776,
|
||||
47.73093
|
||||
],
|
||||
[
|
||||
18.29515,
|
||||
47.72075
|
||||
],
|
||||
[
|
||||
18.67959,
|
||||
47.75541
|
||||
],
|
||||
[
|
||||
18.89755,
|
||||
47.81203
|
||||
],
|
||||
[
|
||||
18.79463,
|
||||
47.88245
|
||||
],
|
||||
[
|
||||
18.84318,
|
||||
48.04046
|
||||
],
|
||||
[
|
||||
19.46212,
|
||||
48.05333
|
||||
],
|
||||
[
|
||||
19.62064,
|
||||
48.22938
|
||||
],
|
||||
[
|
||||
19.89585,
|
||||
48.09387
|
||||
],
|
||||
[
|
||||
20.33766,
|
||||
48.2643
|
||||
],
|
||||
[
|
||||
20.55395,
|
||||
48.52358
|
||||
],
|
||||
[
|
||||
20.82335,
|
||||
48.55714
|
||||
],
|
||||
[
|
||||
21.10271,
|
||||
48.47096
|
||||
],
|
||||
[
|
||||
21.45863,
|
||||
48.55513
|
||||
],
|
||||
[
|
||||
21.74536,
|
||||
48.31435
|
||||
],
|
||||
[
|
||||
22.15293,
|
||||
48.37179
|
||||
],
|
||||
[
|
||||
22.61255,
|
||||
49.08914
|
||||
],
|
||||
[
|
||||
22.09997,
|
||||
49.23814
|
||||
],
|
||||
[
|
||||
21.9686,
|
||||
49.36363
|
||||
],
|
||||
[
|
||||
21.6244,
|
||||
49.46989
|
||||
],
|
||||
[
|
||||
21.06873,
|
||||
49.46402
|
||||
],
|
||||
[
|
||||
20.94336,
|
||||
49.31088
|
||||
],
|
||||
[
|
||||
20.73052,
|
||||
49.44006
|
||||
],
|
||||
[
|
||||
20.22804,
|
||||
49.41714
|
||||
],
|
||||
[
|
||||
20.05234,
|
||||
49.23052
|
||||
],
|
||||
[
|
||||
19.83682,
|
||||
49.25529
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
},
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"logo-image": "https://raw.githubusercontent.com/FreemapSlovakia/freemap-v3-react/master/src/images/freemap-logo-small.png",
|
||||
"required": true,
|
||||
"text": "Copyright ©2007-2012 Freemap Slovakia (www.freemap.sk). Some rights reserved."
|
||||
},
|
||||
"country_code": "SK",
|
||||
"icon": "https://raw.githubusercontent.com/FreemapSlovakia/freemap-v3-react/master/src/images/freemap-logo-small.png",
|
||||
"id": "Freemap.sk-Car",
|
||||
"max_zoom": 16,
|
||||
"min_zoom": 8,
|
||||
"name": "Freemap.sk Car",
|
||||
"type": "tms",
|
||||
"url": "https://{switch:a,b,c,d}.freemap.sk/A/{zoom}/{x}/{y}.jpeg",
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
210
layers/josm/Freemap.sk-Cyclo.geojson
Normal file
210
layers/josm/Freemap.sk-Cyclo.geojson
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
{
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
19.83682,
|
||||
49.25529
|
||||
],
|
||||
[
|
||||
19.80075,
|
||||
49.42385
|
||||
],
|
||||
[
|
||||
19.60437,
|
||||
49.48058
|
||||
],
|
||||
[
|
||||
19.49179,
|
||||
49.63961
|
||||
],
|
||||
[
|
||||
19.21831,
|
||||
49.52604
|
||||
],
|
||||
[
|
||||
19.16778,
|
||||
49.42521
|
||||
],
|
||||
[
|
||||
19.00308,
|
||||
49.42236
|
||||
],
|
||||
[
|
||||
18.97611,
|
||||
49.5308
|
||||
],
|
||||
[
|
||||
18.54685,
|
||||
49.51425
|
||||
],
|
||||
[
|
||||
18.31432,
|
||||
49.33818
|
||||
],
|
||||
[
|
||||
18.15913,
|
||||
49.2961
|
||||
],
|
||||
[
|
||||
18.05564,
|
||||
49.11134
|
||||
],
|
||||
[
|
||||
17.56396,
|
||||
48.84938
|
||||
],
|
||||
[
|
||||
17.17929,
|
||||
48.88816
|
||||
],
|
||||
[
|
||||
17.058,
|
||||
48.81105
|
||||
],
|
||||
[
|
||||
16.90426,
|
||||
48.61947
|
||||
],
|
||||
[
|
||||
16.79685,
|
||||
48.38561
|
||||
],
|
||||
[
|
||||
17.06762,
|
||||
48.01116
|
||||
],
|
||||
[
|
||||
17.32787,
|
||||
47.97749
|
||||
],
|
||||
[
|
||||
17.51699,
|
||||
47.82535
|
||||
],
|
||||
[
|
||||
17.74776,
|
||||
47.73093
|
||||
],
|
||||
[
|
||||
18.29515,
|
||||
47.72075
|
||||
],
|
||||
[
|
||||
18.67959,
|
||||
47.75541
|
||||
],
|
||||
[
|
||||
18.89755,
|
||||
47.81203
|
||||
],
|
||||
[
|
||||
18.79463,
|
||||
47.88245
|
||||
],
|
||||
[
|
||||
18.84318,
|
||||
48.04046
|
||||
],
|
||||
[
|
||||
19.46212,
|
||||
48.05333
|
||||
],
|
||||
[
|
||||
19.62064,
|
||||
48.22938
|
||||
],
|
||||
[
|
||||
19.89585,
|
||||
48.09387
|
||||
],
|
||||
[
|
||||
20.33766,
|
||||
48.2643
|
||||
],
|
||||
[
|
||||
20.55395,
|
||||
48.52358
|
||||
],
|
||||
[
|
||||
20.82335,
|
||||
48.55714
|
||||
],
|
||||
[
|
||||
21.10271,
|
||||
48.47096
|
||||
],
|
||||
[
|
||||
21.45863,
|
||||
48.55513
|
||||
],
|
||||
[
|
||||
21.74536,
|
||||
48.31435
|
||||
],
|
||||
[
|
||||
22.15293,
|
||||
48.37179
|
||||
],
|
||||
[
|
||||
22.61255,
|
||||
49.08914
|
||||
],
|
||||
[
|
||||
22.09997,
|
||||
49.23814
|
||||
],
|
||||
[
|
||||
21.9686,
|
||||
49.36363
|
||||
],
|
||||
[
|
||||
21.6244,
|
||||
49.46989
|
||||
],
|
||||
[
|
||||
21.06873,
|
||||
49.46402
|
||||
],
|
||||
[
|
||||
20.94336,
|
||||
49.31088
|
||||
],
|
||||
[
|
||||
20.73052,
|
||||
49.44006
|
||||
],
|
||||
[
|
||||
20.22804,
|
||||
49.41714
|
||||
],
|
||||
[
|
||||
20.05234,
|
||||
49.23052
|
||||
],
|
||||
[
|
||||
19.83682,
|
||||
49.25529
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
},
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"logo-image": "https://raw.githubusercontent.com/FreemapSlovakia/freemap-v3-react/master/src/images/freemap-logo-small.png",
|
||||
"required": true,
|
||||
"text": "Copyright ©2007-2012 Freemap Slovakia (www.freemap.sk). Some rights reserved."
|
||||
},
|
||||
"country_code": "SK",
|
||||
"icon": "https://raw.githubusercontent.com/FreemapSlovakia/freemap-v3-react/master/src/images/freemap-logo-small.png",
|
||||
"id": "Freemap.sk-Cyclo",
|
||||
"max_zoom": 16,
|
||||
"min_zoom": 8,
|
||||
"name": "Freemap.sk Cyclo",
|
||||
"type": "tms",
|
||||
"url": "https://{switch:a,b,c,d}.freemap.sk/C/{zoom}/{x}/{y}.jpeg",
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
210
layers/josm/Freemap.sk-Hiking.geojson
Normal file
210
layers/josm/Freemap.sk-Hiking.geojson
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
{
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
19.83682,
|
||||
49.25529
|
||||
],
|
||||
[
|
||||
19.80075,
|
||||
49.42385
|
||||
],
|
||||
[
|
||||
19.60437,
|
||||
49.48058
|
||||
],
|
||||
[
|
||||
19.49179,
|
||||
49.63961
|
||||
],
|
||||
[
|
||||
19.21831,
|
||||
49.52604
|
||||
],
|
||||
[
|
||||
19.16778,
|
||||
49.42521
|
||||
],
|
||||
[
|
||||
19.00308,
|
||||
49.42236
|
||||
],
|
||||
[
|
||||
18.97611,
|
||||
49.5308
|
||||
],
|
||||
[
|
||||
18.54685,
|
||||
49.51425
|
||||
],
|
||||
[
|
||||
18.31432,
|
||||
49.33818
|
||||
],
|
||||
[
|
||||
18.15913,
|
||||
49.2961
|
||||
],
|
||||
[
|
||||
18.05564,
|
||||
49.11134
|
||||
],
|
||||
[
|
||||
17.56396,
|
||||
48.84938
|
||||
],
|
||||
[
|
||||
17.17929,
|
||||
48.88816
|
||||
],
|
||||
[
|
||||
17.058,
|
||||
48.81105
|
||||
],
|
||||
[
|
||||
16.90426,
|
||||
48.61947
|
||||
],
|
||||
[
|
||||
16.79685,
|
||||
48.38561
|
||||
],
|
||||
[
|
||||
17.06762,
|
||||
48.01116
|
||||
],
|
||||
[
|
||||
17.32787,
|
||||
47.97749
|
||||
],
|
||||
[
|
||||
17.51699,
|
||||
47.82535
|
||||
],
|
||||
[
|
||||
17.74776,
|
||||
47.73093
|
||||
],
|
||||
[
|
||||
18.29515,
|
||||
47.72075
|
||||
],
|
||||
[
|
||||
18.67959,
|
||||
47.75541
|
||||
],
|
||||
[
|
||||
18.89755,
|
||||
47.81203
|
||||
],
|
||||
[
|
||||
18.79463,
|
||||
47.88245
|
||||
],
|
||||
[
|
||||
18.84318,
|
||||
48.04046
|
||||
],
|
||||
[
|
||||
19.46212,
|
||||
48.05333
|
||||
],
|
||||
[
|
||||
19.62064,
|
||||
48.22938
|
||||
],
|
||||
[
|
||||
19.89585,
|
||||
48.09387
|
||||
],
|
||||
[
|
||||
20.33766,
|
||||
48.2643
|
||||
],
|
||||
[
|
||||
20.55395,
|
||||
48.52358
|
||||
],
|
||||
[
|
||||
20.82335,
|
||||
48.55714
|
||||
],
|
||||
[
|
||||
21.10271,
|
||||
48.47096
|
||||
],
|
||||
[
|
||||
21.45863,
|
||||
48.55513
|
||||
],
|
||||
[
|
||||
21.74536,
|
||||
48.31435
|
||||
],
|
||||
[
|
||||
22.15293,
|
||||
48.37179
|
||||
],
|
||||
[
|
||||
22.61255,
|
||||
49.08914
|
||||
],
|
||||
[
|
||||
22.09997,
|
||||
49.23814
|
||||
],
|
||||
[
|
||||
21.9686,
|
||||
49.36363
|
||||
],
|
||||
[
|
||||
21.6244,
|
||||
49.46989
|
||||
],
|
||||
[
|
||||
21.06873,
|
||||
49.46402
|
||||
],
|
||||
[
|
||||
20.94336,
|
||||
49.31088
|
||||
],
|
||||
[
|
||||
20.73052,
|
||||
49.44006
|
||||
],
|
||||
[
|
||||
20.22804,
|
||||
49.41714
|
||||
],
|
||||
[
|
||||
20.05234,
|
||||
49.23052
|
||||
],
|
||||
[
|
||||
19.83682,
|
||||
49.25529
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
},
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"logo-image": "https://raw.githubusercontent.com/FreemapSlovakia/freemap-v3-react/master/src/images/freemap-logo-small.png",
|
||||
"required": true,
|
||||
"text": "Copyright ©2007-2012 Freemap Slovakia (www.freemap.sk). Some rights reserved."
|
||||
},
|
||||
"country_code": "SK",
|
||||
"icon": "https://raw.githubusercontent.com/FreemapSlovakia/freemap-v3-react/master/src/images/freemap-logo-small.png",
|
||||
"id": "Freemap.sk-Hiking",
|
||||
"max_zoom": 16,
|
||||
"min_zoom": 8,
|
||||
"name": "Freemap.sk Hiking",
|
||||
"type": "tms",
|
||||
"url": "https://{switch:a,b,c,d}.freemap.sk/T/{zoom}/{x}/{y}.jpeg",
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
19
layers/josm/HDM_HOT.geojson
Normal file
19
layers/josm/HDM_HOT.geojson
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"text": "© OpenStreetMap contributors, tiles courtesy of Humanitarian OpenStreetMap Team",
|
||||
"url": "https://www.hotosm.org/"
|
||||
},
|
||||
"icon": "https://wiki.openstreetmap.org/w/images/thumb/c/c9/Hot_logo.svg/300px-Hot_logo.svg.png",
|
||||
"id": "HDM_HOT",
|
||||
"max_zoom": 20,
|
||||
"name": "HDM (Humanitarian OpenStreetMap Team)",
|
||||
"type": "tms",
|
||||
"url": "https://{switch:a,b,c}.tile.openstreetmap.fr/hot/{zoom}/{x}/{y}.png",
|
||||
"valid-georeference": true,
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
187
layers/josm/Israel_Hiking.geojson
Normal file
187
layers/josm/Israel_Hiking.geojson
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
{
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
34.64563,
|
||||
32.92073
|
||||
],
|
||||
[
|
||||
34.98374,
|
||||
33.13352
|
||||
],
|
||||
[
|
||||
35.15662,
|
||||
33.09994
|
||||
],
|
||||
[
|
||||
35.31781,
|
||||
33.11463
|
||||
],
|
||||
[
|
||||
35.36541,
|
||||
33.06285
|
||||
],
|
||||
[
|
||||
35.46229,
|
||||
33.09994
|
||||
],
|
||||
[
|
||||
35.51741,
|
||||
33.12652
|
||||
],
|
||||
[
|
||||
35.5266,
|
||||
33.21531
|
||||
],
|
||||
[
|
||||
35.53893,
|
||||
33.25442
|
||||
],
|
||||
[
|
||||
35.56446,
|
||||
33.2969
|
||||
],
|
||||
[
|
||||
35.61264,
|
||||
33.27918
|
||||
],
|
||||
[
|
||||
35.67429,
|
||||
33.30627
|
||||
],
|
||||
[
|
||||
35.70785,
|
||||
33.34269
|
||||
],
|
||||
[
|
||||
35.75363,
|
||||
33.35091
|
||||
],
|
||||
[
|
||||
35.81509,
|
||||
33.3392
|
||||
],
|
||||
[
|
||||
35.91531,
|
||||
32.9406
|
||||
],
|
||||
[
|
||||
35.80834,
|
||||
32.772
|
||||
],
|
||||
[
|
||||
35.77835,
|
||||
32.72446
|
||||
],
|
||||
[
|
||||
35.59491,
|
||||
32.62828
|
||||
],
|
||||
[
|
||||
35.5729,
|
||||
32.36541
|
||||
],
|
||||
[
|
||||
35.59461,
|
||||
32.21856
|
||||
],
|
||||
[
|
||||
35.55452,
|
||||
32.02901
|
||||
],
|
||||
[
|
||||
35.57225,
|
||||
31.75415
|
||||
],
|
||||
[
|
||||
35.48771,
|
||||
31.41951
|
||||
],
|
||||
[
|
||||
35.4209,
|
||||
31.25116
|
||||
],
|
||||
[
|
||||
35.47936,
|
||||
31.1783
|
||||
],
|
||||
[
|
||||
35.42771,
|
||||
30.95172
|
||||
],
|
||||
[
|
||||
35.3321,
|
||||
30.77107
|
||||
],
|
||||
[
|
||||
35.20709,
|
||||
30.53307
|
||||
],
|
||||
[
|
||||
35.17202,
|
||||
30.11204
|
||||
],
|
||||
[
|
||||
35.07514,
|
||||
29.83713
|
||||
],
|
||||
[
|
||||
35.02336,
|
||||
29.64569
|
||||
],
|
||||
[
|
||||
34.93992,
|
||||
29.39946
|
||||
],
|
||||
[
|
||||
34.89517,
|
||||
29.37711
|
||||
],
|
||||
[
|
||||
34.84785,
|
||||
29.59084
|
||||
],
|
||||
[
|
||||
34.69667,
|
||||
30.10714
|
||||
],
|
||||
[
|
||||
34.52423,
|
||||
30.40912
|
||||
],
|
||||
[
|
||||
34.48879,
|
||||
30.64515
|
||||
],
|
||||
[
|
||||
34.07929,
|
||||
31.52265
|
||||
],
|
||||
[
|
||||
34.64563,
|
||||
32.92073
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
},
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"text": "Tiles © IsraelHiking, CC BY-SA-NC 3.0. Data by OpenStreetMap under ODbL.",
|
||||
"url": "https://israelhiking.osm.org.il/"
|
||||
},
|
||||
"country_code": "IL",
|
||||
"description": "Israel Hiking map",
|
||||
"icon": "https://israelhiking.osm.org.il/content/favicons/favicon.ico",
|
||||
"id": "Israel_Hiking",
|
||||
"max_zoom": 16,
|
||||
"min_zoom": 7,
|
||||
"name": "Israel Hiking",
|
||||
"type": "tms",
|
||||
"url": "https://israelhiking.osm.org.il/Tiles/{zoom}/{x}/{y}.png",
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
187
layers/josm/Israel_MTB.geojson
Normal file
187
layers/josm/Israel_MTB.geojson
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
{
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
34.64563,
|
||||
32.92073
|
||||
],
|
||||
[
|
||||
34.98374,
|
||||
33.13352
|
||||
],
|
||||
[
|
||||
35.15662,
|
||||
33.09994
|
||||
],
|
||||
[
|
||||
35.31781,
|
||||
33.11463
|
||||
],
|
||||
[
|
||||
35.36541,
|
||||
33.06285
|
||||
],
|
||||
[
|
||||
35.46229,
|
||||
33.09994
|
||||
],
|
||||
[
|
||||
35.51741,
|
||||
33.12652
|
||||
],
|
||||
[
|
||||
35.5266,
|
||||
33.21531
|
||||
],
|
||||
[
|
||||
35.53893,
|
||||
33.25442
|
||||
],
|
||||
[
|
||||
35.56446,
|
||||
33.2969
|
||||
],
|
||||
[
|
||||
35.61264,
|
||||
33.27918
|
||||
],
|
||||
[
|
||||
35.67429,
|
||||
33.30627
|
||||
],
|
||||
[
|
||||
35.70785,
|
||||
33.34269
|
||||
],
|
||||
[
|
||||
35.75363,
|
||||
33.35091
|
||||
],
|
||||
[
|
||||
35.81509,
|
||||
33.3392
|
||||
],
|
||||
[
|
||||
35.91531,
|
||||
32.9406
|
||||
],
|
||||
[
|
||||
35.80834,
|
||||
32.772
|
||||
],
|
||||
[
|
||||
35.77835,
|
||||
32.72446
|
||||
],
|
||||
[
|
||||
35.59491,
|
||||
32.62828
|
||||
],
|
||||
[
|
||||
35.5729,
|
||||
32.36541
|
||||
],
|
||||
[
|
||||
35.59461,
|
||||
32.21856
|
||||
],
|
||||
[
|
||||
35.55452,
|
||||
32.02901
|
||||
],
|
||||
[
|
||||
35.57225,
|
||||
31.75415
|
||||
],
|
||||
[
|
||||
35.48771,
|
||||
31.41951
|
||||
],
|
||||
[
|
||||
35.4209,
|
||||
31.25116
|
||||
],
|
||||
[
|
||||
35.47936,
|
||||
31.1783
|
||||
],
|
||||
[
|
||||
35.42771,
|
||||
30.95172
|
||||
],
|
||||
[
|
||||
35.3321,
|
||||
30.77107
|
||||
],
|
||||
[
|
||||
35.20709,
|
||||
30.53307
|
||||
],
|
||||
[
|
||||
35.17202,
|
||||
30.11204
|
||||
],
|
||||
[
|
||||
35.07514,
|
||||
29.83713
|
||||
],
|
||||
[
|
||||
35.02336,
|
||||
29.64569
|
||||
],
|
||||
[
|
||||
34.93992,
|
||||
29.39946
|
||||
],
|
||||
[
|
||||
34.89517,
|
||||
29.37711
|
||||
],
|
||||
[
|
||||
34.84785,
|
||||
29.59084
|
||||
],
|
||||
[
|
||||
34.69667,
|
||||
30.10714
|
||||
],
|
||||
[
|
||||
34.52423,
|
||||
30.40912
|
||||
],
|
||||
[
|
||||
34.48879,
|
||||
30.64515
|
||||
],
|
||||
[
|
||||
34.07929,
|
||||
31.52265
|
||||
],
|
||||
[
|
||||
34.64563,
|
||||
32.92073
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
},
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"text": "Tiles © IsraelHiking, CC BY-SA-NC 3.0. Data by OpenStreetMap under ODbL.",
|
||||
"url": "https://israelhiking.osm.org.il/"
|
||||
},
|
||||
"country_code": "IL",
|
||||
"description": "Israel MTB map",
|
||||
"icon": "https://israelhiking.osm.org.il/content/favicons/favicon.ico",
|
||||
"id": "Israel_MTB",
|
||||
"max_zoom": 16,
|
||||
"min_zoom": 7,
|
||||
"name": "Israel MTB",
|
||||
"type": "tms",
|
||||
"url": "https://israelhiking.osm.org.il/MTBTiles/{zoom}/{x}/{y}.png",
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
7
layers/josm/LICENSE
Normal file
7
layers/josm/LICENSE
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
JOSM imagery database is licensed under Creative Commons (CC-BY-SA).
|
||||
Content since April 2014 is dual licensed with LGPL (except contents copied from ELI, which is only CC-BY-SA).
|
||||
|
||||
https://creativecommons.org/licenses/by-sa/3.0/
|
||||
|
||||
Source: https://josm.openstreetmap.de/wiki/Maps#Otherimportantinformation
|
||||
2319
layers/josm/OpenStreetMap-turistautak.geojson
Normal file
2319
layers/josm/OpenStreetMap-turistautak.geojson
Normal file
File diff suppressed because it is too large
Load diff
20
layers/josm/OpenTopoMap.geojson
Normal file
20
layers/josm/OpenTopoMap.geojson
Normal file
File diff suppressed because one or more lines are too long
20
layers/josm/Waymarked_Trails-Cycling.geojson
Normal file
20
layers/josm/Waymarked_Trails-Cycling.geojson
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"text": "© waymarkedtrails.org, OpenStreetMap contributors, CC by-SA 3.0",
|
||||
"url": "https://cycling.waymarkedtrails.org/en/help/legal"
|
||||
},
|
||||
"icon": "https://static.waymarkedtrails.org/img/map_cycling.png",
|
||||
"id": "Waymarked_Trails-Cycling",
|
||||
"max_zoom": 17,
|
||||
"name": "Waymarked Trails: Cycling",
|
||||
"overlay": true,
|
||||
"type": "tms",
|
||||
"url": "https://tile.waymarkedtrails.org/cycling/{zoom}/{x}/{y}.png",
|
||||
"valid-georeference": true,
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
20
layers/josm/Waymarked_Trails-Hiking.geojson
Normal file
20
layers/josm/Waymarked_Trails-Hiking.geojson
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"text": "© waymarkedtrails.org, OpenStreetMap contributors, CC by-SA 3.0",
|
||||
"url": "https://hiking.waymarkedtrails.org/en/help/legal"
|
||||
},
|
||||
"icon": "https://static.waymarkedtrails.org/img/map_hiking.png",
|
||||
"id": "Waymarked_Trails-Hiking",
|
||||
"max_zoom": 17,
|
||||
"name": "Waymarked Trails: Hiking",
|
||||
"overlay": true,
|
||||
"type": "tms",
|
||||
"url": "https://tile.waymarkedtrails.org/hiking/{zoom}/{x}/{y}.png",
|
||||
"valid-georeference": true,
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
20
layers/josm/Waymarked_Trails-MTB.geojson
Normal file
20
layers/josm/Waymarked_Trails-MTB.geojson
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"text": "© waymarkedtrails.org, OpenStreetMap contributors, CC by-SA 3.0",
|
||||
"url": "https://mtb.waymarkedtrails.org/en/help/legal"
|
||||
},
|
||||
"icon": "https://static.waymarkedtrails.org/img/map_mtb.png",
|
||||
"id": "Waymarked_Trails-MTB",
|
||||
"max_zoom": 17,
|
||||
"name": "Waymarked Trails: MTB",
|
||||
"overlay": true,
|
||||
"type": "tms",
|
||||
"url": "https://tile.waymarkedtrails.org/mtb/{zoom}/{x}/{y}.png",
|
||||
"valid-georeference": true,
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
63
layers/josm/extract.js
Normal file
63
layers/josm/extract.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const fetch = require('node-fetch');
|
||||
|
||||
const outDir = __dirname;
|
||||
|
||||
const includeList = [
|
||||
"osmbe",
|
||||
"osmbe-fr",
|
||||
"osmbe-nl",
|
||||
"osmfr-basque",
|
||||
"osmfr-breton",
|
||||
"osmfr-occitan",
|
||||
"OpenStreetMap-turistautak",
|
||||
"hu-hillshade",
|
||||
"Israel_Hiking",
|
||||
"Israel_MTB",
|
||||
"mtbmap-no",
|
||||
"Freemap.sk-Car",
|
||||
"Freemap.sk-Hiking",
|
||||
"Freemap.sk-Cyclo",
|
||||
"opencylemap",
|
||||
"standard",
|
||||
"HDM_HOT",
|
||||
"osmfr",
|
||||
"osm-mapnik-german_style",
|
||||
"OpenTopoMap",
|
||||
"osm-cambodia_laos_thailand_vietnam-bilingual",
|
||||
"Waymarked_Trails-Hiking",
|
||||
"Waymarked_Trails-Cycling",
|
||||
"Waymarked_Trails-MTB",
|
||||
"wikimedia-map",
|
||||
"openpt_map"
|
||||
];
|
||||
|
||||
function extract(layersJosm) {
|
||||
for (let i = 0; i < layersJosm.features.length; i++) {
|
||||
let layer = layersJosm.features[i];
|
||||
let props = layer.properties;
|
||||
let id = props.id;
|
||||
if (includeList.includes(id)) {
|
||||
//console.log(`${id}, ${props.name}, ${props.url}`);
|
||||
|
||||
props.dataSource = 'JOSM';
|
||||
|
||||
const outFileName = path.join(outDir, id + '.geojson');
|
||||
const data = JSON.stringify(layer, null, 2);
|
||||
fs.writeFileSync(outFileName, data);
|
||||
|
||||
includeList.splice(includeList.indexOf(id), 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (includeList.length > 0) {
|
||||
console.warn('Layers not found: ', includeList);
|
||||
}
|
||||
}
|
||||
|
||||
fetch('https://josm.openstreetmap.de/maps?format=geojson')
|
||||
.then(res => res.json())
|
||||
.then(json => extract(json))
|
||||
.catch(err => console.error(err));
|
||||
46
layers/josm/hu-hillshade.geojson
Normal file
46
layers/josm/hu-hillshade.geojson
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
15,
|
||||
45
|
||||
],
|
||||
[
|
||||
24,
|
||||
45
|
||||
],
|
||||
[
|
||||
24,
|
||||
49
|
||||
],
|
||||
[
|
||||
15,
|
||||
49
|
||||
],
|
||||
[
|
||||
15,
|
||||
45
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
},
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"text": "SRTM"
|
||||
},
|
||||
"country_code": "HU",
|
||||
"id": "hu-hillshade",
|
||||
"max_zoom": 18,
|
||||
"min_zoom": 0,
|
||||
"name": "Hillshade Hungary",
|
||||
"overlay": true,
|
||||
"type": "tms",
|
||||
"url": "https://{switch:a,b,c}.map.turistautak.hu/tiles/shading/{zoom}/{x}/{y}.png",
|
||||
"valid-georeference": true,
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
134
layers/josm/mtbmap-no.geojson
Normal file
134
layers/josm/mtbmap-no.geojson
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
{
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
31.904253,
|
||||
70.4368136
|
||||
],
|
||||
[
|
||||
28.4765186,
|
||||
71.3289643
|
||||
],
|
||||
[
|
||||
23.6865015,
|
||||
71.2514263
|
||||
],
|
||||
[
|
||||
16.8090601,
|
||||
70.0730823
|
||||
],
|
||||
[
|
||||
11.1620655,
|
||||
67.5253903
|
||||
],
|
||||
[
|
||||
9.975542,
|
||||
64.811576
|
||||
],
|
||||
[
|
||||
4.2187061,
|
||||
62.1449966
|
||||
],
|
||||
[
|
||||
4.3725367,
|
||||
59.1871966
|
||||
],
|
||||
[
|
||||
6.1743055,
|
||||
57.8915032
|
||||
],
|
||||
[
|
||||
7.932118,
|
||||
57.7393554
|
||||
],
|
||||
[
|
||||
10.777577,
|
||||
58.8649103
|
||||
],
|
||||
[
|
||||
11.7224012,
|
||||
58.762509
|
||||
],
|
||||
[
|
||||
12.722157,
|
||||
60.1141506
|
||||
],
|
||||
[
|
||||
13.0517469,
|
||||
61.3493518
|
||||
],
|
||||
[
|
||||
12.5243921,
|
||||
63.6169922
|
||||
],
|
||||
[
|
||||
14.2382593,
|
||||
63.9856094
|
||||
],
|
||||
[
|
||||
15.1171656,
|
||||
65.9016624
|
||||
],
|
||||
[
|
||||
18.6987085,
|
||||
68.3749083
|
||||
],
|
||||
[
|
||||
20.0610132,
|
||||
68.2612583
|
||||
],
|
||||
[
|
||||
21.0058375,
|
||||
68.7841518
|
||||
],
|
||||
[
|
||||
25.2465601,
|
||||
68.3506025
|
||||
],
|
||||
[
|
||||
26.9384546,
|
||||
69.8472011
|
||||
],
|
||||
[
|
||||
28.7621851,
|
||||
69.6112133
|
||||
],
|
||||
[
|
||||
28.5864039,
|
||||
68.8556004
|
||||
],
|
||||
[
|
||||
31.069314,
|
||||
69.5191547
|
||||
],
|
||||
[
|
||||
31.904253,
|
||||
70.4368136
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
},
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"text": "© MTBmap.no",
|
||||
"url": "https://www.mtbmap.no/"
|
||||
},
|
||||
"country_code": "NO",
|
||||
"description": "Norwegian mountain biking map from OSM (max zoom 14-16, varies per region)",
|
||||
"icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAyVBMVEUAAAAAAAAAAAAAAABHcEwAAAAAAAAAAAAAAAAAAAAAAAAGBgYAAAAAAAD///8DAwMKCgrX19d3d3fe3t4fHx/4+PikpKQGBgbb29vIyMizs7MlJSXExMQQEBA2NjYNDQ2pqam6urr+/v4UFBS8vLzg4OCMjIxvb297e3vLy8taWlqXl5fs7Oz7+/vn5+c7OzvQ0NDT09MxMTFFRUWTk5O/v7/k5OReXl6urq5iYmJLS0uGhoZOTk7y8vJpaWmcnJyDg4N/f3+bm5thW7HyAAAADXRSTlM9D3VaADJrd4BEKIEG/oGXoQAAAP1JREFUKM9tkIdywyAMhmmb0WVhjLcd2/HK3jvdff+HKjQ1kNr/HYdOH5J+hG463QbdtdCtJtXDImyje5nP5oaIkQLiKcwCxzH+A30PAAXpg30NdPJmMcLPWAXxINLwMAUuy7yewfT6YtgWJJ6ugmPoXDxH2BxiCTKAd1GJzQo4+bS/7ClN/wAeARB1WAV8loelXwczKHAZ+rgGtim4Zq1VSSkZr+Ar21Ga6xJsw1hbz9fwSdj6DCJBwR+d2O5CnhgtKvBE+R2sUv+DB/ZAVFA+dTLZRC7/kBsIcN6fFt8u65d4m7OXKK6CY1j+mjns8oO029Ea9Yie0UOD2q0frM8mZOHCEDcAAAAASUVORK5CYII=",
|
||||
"id": "mtbmap-no",
|
||||
"max_zoom": 14,
|
||||
"min_zoom": 3,
|
||||
"name": "MTBmap.no",
|
||||
"tile-size": "512",
|
||||
"tile_size": 512,
|
||||
"type": "tms",
|
||||
"url": "https://mtbmap.no/tiles/osm/mtbmap/{zoom}/{x}/{y}.jpg",
|
||||
"valid-georeference": true,
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
21
layers/josm/opencylemap.geojson
Normal file
21
layers/josm/opencylemap.geojson
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"terms-of-use-text": "Maps © Thunderforest",
|
||||
"terms-of-use-url": "https://thunderforest.com/terms/",
|
||||
"text": "Data © OpenStreetMap contributors",
|
||||
"url": "https://www.openstreetmap.org/copyright/"
|
||||
},
|
||||
"icon": "data:image/png;base64,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",
|
||||
"id": "opencylemap",
|
||||
"max_zoom": 22,
|
||||
"name": "OpenCycleMap",
|
||||
"type": "tms",
|
||||
"url": "https://{switch:a,b,c}.tile.thunderforest.com/cycle/{zoom}/{x}/{y}.png?apikey=7bd5ed2197cf4da29fa26de0ba6530cc",
|
||||
"valid-georeference": true,
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
21
layers/josm/openpt_map.geojson
Normal file
21
layers/josm/openpt_map.geojson
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"text": "© OpenStreetMap contributors, CC-BY-SA",
|
||||
"url": "http://openptmap.de/"
|
||||
},
|
||||
"icon": "http://openptmap.de/favicon_pt.png",
|
||||
"id": "openpt_map",
|
||||
"max_zoom": 17,
|
||||
"min_zoom": 4,
|
||||
"name": "OpenPT Map (overlay)",
|
||||
"overlay": true,
|
||||
"type": "tms",
|
||||
"url": "http://openptmap.de/tiles/{zoom}/{x}/{y}.png",
|
||||
"valid-georeference": true,
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
168
layers/josm/osm-cambodia_laos_thailand_vietnam-bilingual.geojson
Normal file
168
layers/josm/osm-cambodia_laos_thailand_vietnam-bilingual.geojson
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
{
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
92.1023798,
|
||||
20.8135629
|
||||
],
|
||||
[
|
||||
93.5690546,
|
||||
24.0975527
|
||||
],
|
||||
[
|
||||
94.1733026,
|
||||
23.9269484
|
||||
],
|
||||
[
|
||||
95.1950312,
|
||||
26.707274
|
||||
],
|
||||
[
|
||||
96.7550898,
|
||||
27.5286657
|
||||
],
|
||||
[
|
||||
97.5845575,
|
||||
28.5805966
|
||||
],
|
||||
[
|
||||
98.738122,
|
||||
27.514051
|
||||
],
|
||||
[
|
||||
98.7436151,
|
||||
25.8799151
|
||||
],
|
||||
[
|
||||
97.6779413,
|
||||
24.7577376
|
||||
],
|
||||
[
|
||||
97.9635858,
|
||||
24.042382
|
||||
],
|
||||
[
|
||||
98.8205194,
|
||||
24.1627239
|
||||
],
|
||||
[
|
||||
99.5236444,
|
||||
22.9593356
|
||||
],
|
||||
[
|
||||
100.3695917,
|
||||
21.5051376
|
||||
],
|
||||
[
|
||||
101.7923212,
|
||||
22.4830518
|
||||
],
|
||||
[
|
||||
105.3628778,
|
||||
23.3331079
|
||||
],
|
||||
[
|
||||
106.8185663,
|
||||
22.8480137
|
||||
],
|
||||
[
|
||||
108.1973505,
|
||||
21.3619661
|
||||
],
|
||||
[
|
||||
107.4389505,
|
||||
18.8539792
|
||||
],
|
||||
[
|
||||
117.1453714,
|
||||
7.4656173
|
||||
],
|
||||
[
|
||||
119.6172953,
|
||||
5.2875389
|
||||
],
|
||||
[
|
||||
118.1231546,
|
||||
4.0502277
|
||||
],
|
||||
[
|
||||
117.2552347,
|
||||
4.3624942
|
||||
],
|
||||
[
|
||||
115.8654642,
|
||||
4.3460623
|
||||
],
|
||||
[
|
||||
115.5084085,
|
||||
3.0249771
|
||||
],
|
||||
[
|
||||
114.552598,
|
||||
1.5100953
|
||||
],
|
||||
[
|
||||
113.5418558,
|
||||
1.2574836
|
||||
],
|
||||
[
|
||||
112.9650736,
|
||||
1.5704982
|
||||
],
|
||||
[
|
||||
112.2454691,
|
||||
1.5100953
|
||||
],
|
||||
[
|
||||
111.67418,
|
||||
1.0158321
|
||||
],
|
||||
[
|
||||
110.4546976,
|
||||
0.9004918
|
||||
],
|
||||
[
|
||||
109.4988871,
|
||||
1.9218969
|
||||
],
|
||||
[
|
||||
103.2256937,
|
||||
1.1256762
|
||||
],
|
||||
[
|
||||
100.4626322,
|
||||
3.2388904
|
||||
],
|
||||
[
|
||||
97.6721048,
|
||||
8.0588831
|
||||
],
|
||||
[
|
||||
93.892808,
|
||||
15.9398659
|
||||
],
|
||||
[
|
||||
92.1023798,
|
||||
20.8135629
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
},
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"text": "© osm-tools.org & OpenStreetMap contributors, CC-BY-SA",
|
||||
"url": "https://www.osm-tools.org/"
|
||||
},
|
||||
"id": "osm-cambodia_laos_thailand_vietnam-bilingual",
|
||||
"max_zoom": 20,
|
||||
"name": "Cambodia, Laos, Thailand, Vietnam, Malaysia, Myanmar bilingual",
|
||||
"type": "tms",
|
||||
"url": "https://{switch:a,b,c,d}.tile.osm-tools.org/osm/{zoom}/{x}/{y}.png",
|
||||
"valid-georeference": true,
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
20
layers/josm/osm-mapnik-german_style.geojson
Normal file
20
layers/josm/osm-mapnik-german_style.geojson
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"text": "© OpenStreetMap contributors, CC-BY-SA",
|
||||
"url": "https://www.openstreetmap.org/"
|
||||
},
|
||||
"icon": "data:image/png;base64,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",
|
||||
"id": "osm-mapnik-german_style",
|
||||
"max_zoom": 18,
|
||||
"mod-tile-features": true,
|
||||
"name": "OpenStreetMap (German Style)",
|
||||
"type": "tms",
|
||||
"url": "https://{switch:a,b,c,d}.tile.openstreetmap.de/tiles/osmde/{zoom}/{x}/{y}.png",
|
||||
"valid-georeference": true,
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
2023
layers/josm/osmbe-fr.geojson
Normal file
2023
layers/josm/osmbe-fr.geojson
Normal file
File diff suppressed because it is too large
Load diff
2023
layers/josm/osmbe-nl.geojson
Normal file
2023
layers/josm/osmbe-nl.geojson
Normal file
File diff suppressed because it is too large
Load diff
2023
layers/josm/osmbe.geojson
Normal file
2023
layers/josm/osmbe.geojson
Normal file
File diff suppressed because it is too large
Load diff
46
layers/josm/osmfr-basque.geojson
Normal file
46
layers/josm/osmfr-basque.geojson
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
16.2075922,
|
||||
62.7408449
|
||||
],
|
||||
[
|
||||
16.2900797,
|
||||
33.8453727
|
||||
],
|
||||
[
|
||||
-10.7364447,
|
||||
33.8043768
|
||||
],
|
||||
[
|
||||
-10.8189321,
|
||||
62.7182339
|
||||
],
|
||||
[
|
||||
16.2075922,
|
||||
62.7408449
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
},
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"text": "Tiles © OpenStreetMap France, data © OpenStreetMap contributors, ODbL",
|
||||
"url": "https://www.openstreetmap.org/"
|
||||
},
|
||||
"icon": "data:image/png;base64,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",
|
||||
"id": "osmfr-basque",
|
||||
"max_zoom": 20,
|
||||
"mod-tile-features": true,
|
||||
"name": "OpenStreetMap (Basque Style)",
|
||||
"type": "tms",
|
||||
"url": "https://tile.openstreetmap.bzh/eu/{zoom}/{x}/{y}.png",
|
||||
"valid-georeference": true,
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
46
layers/josm/osmfr-breton.geojson
Normal file
46
layers/josm/osmfr-breton.geojson
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
16.2075922,
|
||||
62.7408449
|
||||
],
|
||||
[
|
||||
16.2900797,
|
||||
33.8453727
|
||||
],
|
||||
[
|
||||
-10.7364447,
|
||||
33.8043768
|
||||
],
|
||||
[
|
||||
-10.8189321,
|
||||
62.7182339
|
||||
],
|
||||
[
|
||||
16.2075922,
|
||||
62.7408449
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
},
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"text": "Tiles © OpenStreetMap France, data © OpenStreetMap contributors, ODbL",
|
||||
"url": "https://www.openstreetmap.org/"
|
||||
},
|
||||
"icon": "data:image/png;base64,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",
|
||||
"id": "osmfr-breton",
|
||||
"max_zoom": 20,
|
||||
"mod-tile-features": true,
|
||||
"name": "OpenStreetMap (Breton Style)",
|
||||
"type": "tms",
|
||||
"url": "https://tile.openstreetmap.bzh/br/{zoom}/{x}/{y}.png",
|
||||
"valid-georeference": true,
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
46
layers/josm/osmfr-occitan.geojson
Normal file
46
layers/josm/osmfr-occitan.geojson
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
"geometry": {
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
16.2075922,
|
||||
62.7408449
|
||||
],
|
||||
[
|
||||
16.2900797,
|
||||
33.8453727
|
||||
],
|
||||
[
|
||||
-10.7364447,
|
||||
33.8043768
|
||||
],
|
||||
[
|
||||
-10.8189321,
|
||||
62.7182339
|
||||
],
|
||||
[
|
||||
16.2075922,
|
||||
62.7408449
|
||||
]
|
||||
]
|
||||
],
|
||||
"type": "Polygon"
|
||||
},
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"text": "Tiles © OpenStreetMap France, data © OpenStreetMap contributors, ODbL",
|
||||
"url": "https://www.openstreetmap.org/"
|
||||
},
|
||||
"icon": "data:image/png;base64,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",
|
||||
"id": "osmfr-occitan",
|
||||
"max_zoom": 20,
|
||||
"mod-tile-features": true,
|
||||
"name": "OpenStreetMap (Occitan Style)",
|
||||
"type": "tms",
|
||||
"url": "https://tile.openstreetmap.bzh/oc/{zoom}/{x}/{y}.png",
|
||||
"valid-georeference": true,
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
20
layers/josm/osmfr.geojson
Normal file
20
layers/josm/osmfr.geojson
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"text": "Tiles © cquest@Openstreetmap France, data © OpenStreetMap contributors, ODBL",
|
||||
"url": "https://www.openstreetmap.org/"
|
||||
},
|
||||
"icon": "data:image/png;base64,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",
|
||||
"id": "osmfr",
|
||||
"max_zoom": 20,
|
||||
"mod-tile-features": true,
|
||||
"name": "OpenStreetMap (French Style)",
|
||||
"type": "tms",
|
||||
"url": "https://{switch:a,b,c}.tile.openstreetmap.fr/osmfr/{zoom}/{x}/{y}.png",
|
||||
"valid-georeference": true,
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
21
layers/josm/standard.geojson
Normal file
21
layers/josm/standard.geojson
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"text": "© OpenStreetMap contributors, CC-BY-SA",
|
||||
"url": "https://www.openstreetmap.org/"
|
||||
},
|
||||
"default": true,
|
||||
"icon": "data:image/png;base64,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",
|
||||
"id": "standard",
|
||||
"max_zoom": 19,
|
||||
"mod-tile-features": true,
|
||||
"name": "OpenStreetMap Carto (Standard)",
|
||||
"type": "tms",
|
||||
"url": "https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png",
|
||||
"valid-georeference": true,
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
18
layers/josm/wikimedia-map.geojson
Normal file
18
layers/josm/wikimedia-map.geojson
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"geometry": null,
|
||||
"properties": {
|
||||
"attribution": {
|
||||
"required": true,
|
||||
"text": "© OpenStreetMap contributors, CC-BY-SA",
|
||||
"url": "https://www.openstreetmap.org/"
|
||||
},
|
||||
"id": "wikimedia-map",
|
||||
"max_zoom": 18,
|
||||
"name": "Wikimedia Map",
|
||||
"type": "tms",
|
||||
"url": "https://maps.wikimedia.org/osm-intl/{zoom}/{x}/{y}.png",
|
||||
"valid-georeference": true,
|
||||
"dataSource": "JOSM"
|
||||
},
|
||||
"type": "Feature"
|
||||
}
|
||||
209
locales/de.json
Normal file
209
locales/de.json
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
{
|
||||
"about": {
|
||||
"bug-reports": "Fehlerberichte und Funktionsanfragen:",
|
||||
"bug-reports-back": "Server / Backend, Routing Engine, Android-App, Profile, brouter.de Website",
|
||||
"bug-reports-front": "Web-Client / Frontend.",
|
||||
"chat": "Chatte mit Benutzern und Entwicklern",
|
||||
"contact": "Kontakt:",
|
||||
"data": "Daten:",
|
||||
"data-description": "Dies basiert auf <a href=\"https://www.openstreetmap.org\" target=\"_blank\">OpenStreetMap</a>. Es wird normalerweise einmal pro Woche aktualisiert, wenn ein neues Planet-File verfügbar ist. Siehe Datum der <a href=\"http://brouter.de/brouter/segments4/\" target=\"_blank\">Datendateien</a>.",
|
||||
"description": "Online-Service der BRouter Routing Engine. Für die Offline-Android-App und weitere Informationen siehe <a href=\"http://brouter.de/\" target=\"_blank\">brouter.de</a>.",
|
||||
"details": "<i><a href=\"http://brouter.de/privacypolicy.html\" target=\"_blank\">Datenschutz-Bestimmungen</a></i>,\n<i><a href=\"https://github.com/nrenner/brouter-web#credits-and-licenses\" target=\"_blank\">Credits</a></i>,\n<i><a href=\"https://github.com/nrenner/brouter-web/blob/master/CHANGELOG.md\" target=\"_blank\">Änderungsprotokoll</a></i> und\n<i><a href=\"https://github.com/nrenner/brouter-web#readme\" target=\"_blank\">weitere Infos</a></i> zum Client.",
|
||||
"support": "Generelle Diskussionen/Fragen, Support",
|
||||
"title": "Über"
|
||||
},
|
||||
"credits": {
|
||||
"brouter": "BRouter",
|
||||
"brouter-license": "<a target=\"_blank\" href=\"http://brouter.de/brouter\">BRouter</a> © Arndt Brenschede",
|
||||
"esri-license": "<a target=\"_blank\" href=\"http://goto.arcgisonline.com/maps/World_Imagery\">World Imagery</a> © <a target=\"_blank\" href=\"https://www.esri.com/\">Esri</a>, Quellen: Esri, DigitalGlobe, Earthstar Geographics, CNES/Airbus DS, GeoEye, USDA FSA, USGS, Getmapping, Aerogrid, IGN, IGP und die GIS Benutzergemeinschaft",
|
||||
"esri-tiles": "Esri World Imagery",
|
||||
"map-data": "Kartendaten",
|
||||
"map-tiles": "Kartendarstellung",
|
||||
"nominatim": "Suchen mit <a href=\"https://wiki.openstreetmap.org/wiki/Nominatim\" target=\"_blank\" data-i18n=\"credits.nominatim\">Nominatim</a>",
|
||||
"openstreetmap": "© <a target=\"_blank\" href=\"https://www.openstreetmap.org/copyright\" >OpenStreetMap contributors</a> unter <a target=\"_blank\" href=\"https://opendatacommons.org/licenses/odbl/\" >ODbL</a>"
|
||||
},
|
||||
"export": {
|
||||
"format": "Format",
|
||||
"format_csv": "CSV",
|
||||
"format_geojson": "GeoJSON",
|
||||
"format_gpx": "GPX",
|
||||
"format_kml": "KML",
|
||||
"route-from-to": "{{from}} -> {{to}} ({{distance}} km)",
|
||||
"route-loop": "{{from}} ({{distance}} km)",
|
||||
"title": "Route exportieren",
|
||||
"trackname": "Name"
|
||||
},
|
||||
"footer": {
|
||||
"ascend": "Aufsteigend",
|
||||
"cost": "Kosten",
|
||||
"distance": "Entfernung",
|
||||
"energy-per-100km": "Energie pro 100 km",
|
||||
"hours": "Stunden",
|
||||
"hours-abbrev": "h",
|
||||
"kilometer": "Kilometer",
|
||||
"kilometer-abbrev": "km",
|
||||
"kilowatthour": "Kilowattstunden",
|
||||
"kilowatthour-abbrev": "kWh",
|
||||
"mean-cost-factor": "durchschnittlicher Kostenfaktor",
|
||||
"meter": "Meter",
|
||||
"meter-abbrev": "m",
|
||||
"plain-ascend": "einfach aufsteigend",
|
||||
"total-energy": "Gesamtenergie",
|
||||
"travel-time": "Reisezeit"
|
||||
},
|
||||
"layers": {
|
||||
"add-base": "Basisebene hinzufügen",
|
||||
"add-overlay": "Overlay hinzufügen",
|
||||
"customize": "Ebenen anpassen",
|
||||
"placeholder-layer-name": "angepasster Ebenenname (Bsp: OpenStreetMap)",
|
||||
"placeholder-layer-url": "angepasste Ebenen-URL (Bsp: https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png)",
|
||||
"remove-selection": "Auswahl entfernen"
|
||||
},
|
||||
"loadNogos": {
|
||||
"defaultProperties": "Standardeigenschaften",
|
||||
"file": "Datei:",
|
||||
"load": "Laden",
|
||||
"nogoBuffer": "Puffer um No-go-Areas (in Metern):",
|
||||
"nogoRadius": "No-go Radius (für Punkte):",
|
||||
"nogoWeight": "No-go Gewicht:",
|
||||
"source": "Quelle",
|
||||
"title": "No-go-Areas laden",
|
||||
"url": "URL:"
|
||||
},
|
||||
"map": {
|
||||
"attribution-osm-long": "OpenStreetMap-Mitwirkende",
|
||||
"attribution-osm-short": "OpenStreetMap",
|
||||
"clear-route": "Route löschen",
|
||||
"copyright": "Copyright",
|
||||
"cycling": "Radfahren",
|
||||
"delete-last-point": "Letzten Punkt löschen",
|
||||
"delete-nogo-areas": " auch alle no-go areas löschen",
|
||||
"delete-route": "Route löschen?",
|
||||
"draw-route-start": "Route anzeigen (D Taste)",
|
||||
"draw-route-stop": "Route entfernen (ESC Taste)",
|
||||
"hikebike-hillshading": "Höhenschummerung",
|
||||
"hiking": "Wandern",
|
||||
"layer": {
|
||||
"bing": "Bing Luftbild",
|
||||
"cycle": "OpenCycleMap (Thunderf.)",
|
||||
"cycling": "Radfahren (markierte Routen)",
|
||||
"digitalglobe": "DigitalGlobe neueste Bilder",
|
||||
"esri": "Esri Weltbilder",
|
||||
"hikebike-hillshading": "Höhenschummerung (Hike & Bike Map)",
|
||||
"hiking": "Wandern (markierte Routen)",
|
||||
"osm": "OpenStreetMap",
|
||||
"osmde": "OpenStreetMap.de",
|
||||
"outdoors": "Outdoor (Thunderforest)",
|
||||
"stamen-terrain": "Terrain (Stamen)",
|
||||
"strava-segments": "Strava Segmente",
|
||||
"topo": "OpenTopoMap"
|
||||
},
|
||||
"loading": "Lade...",
|
||||
"locate-me": "Zeige meinen Standort",
|
||||
"nogo": {
|
||||
"cancel": "No-Go-Areas löschen",
|
||||
"click-drag": "klicken und ziehen zum Zeichnen eines Kreises",
|
||||
"draw": "No-Go-Area zeichnen (Kreis)",
|
||||
"edit": "Klicken zum Bearbeiten",
|
||||
"help": "□ = Bewegen / Größe anpassen, <span class=\"fa fa-trash-o\"></span> = Löschen,<br>Kreis anklicken um Bearbeiten zu beenden"
|
||||
},
|
||||
"opacity-slider": "Transparenz von Route und Markern anpassen",
|
||||
"privacy": "Datenschutz",
|
||||
"reverse-route": "Route umkehren",
|
||||
"strava-biking": "Zeige Strava Radfahrsegmente",
|
||||
"strava-running": "Zeige Strava Läufersegmente",
|
||||
"zoomInTitle": "Hineinzoomen",
|
||||
"zoomOutTitle": "Herauszoomen"
|
||||
},
|
||||
"modal": {
|
||||
"close": "Schließen"
|
||||
},
|
||||
"navbar": {
|
||||
"about": "Über",
|
||||
"alternative": {
|
||||
"first": "1. Alternative",
|
||||
"original": "Original",
|
||||
"second": "2. Alternative",
|
||||
"third": "3. Alternative"
|
||||
},
|
||||
"export": "Export",
|
||||
"load": {
|
||||
"nogos": "No-go-Areas",
|
||||
"title": "Laden"
|
||||
},
|
||||
"profile": {
|
||||
"car-eco": "Auto (effizient)",
|
||||
"car-fast": "Auto (schnell)",
|
||||
"car-test": "Auto (Test)",
|
||||
"custom": "Benutzerdefiniert",
|
||||
"fastbike": "Fahrrad (schnell)",
|
||||
"fastbike-asia-pacific": "Fahrrad (schnell, Asien Pazifik)",
|
||||
"fastbike-lowtraffic": "Fahrrad (schnell, Routen mit wenig Verkehr)",
|
||||
"hiking-beta": "Wandern (beta)",
|
||||
"moped": "Moped",
|
||||
"rail": "Eisenbahn",
|
||||
"river": "Fluss",
|
||||
"safety": "Sicherste Route",
|
||||
"shortest": "Kürzeste Route",
|
||||
"trekking": "Trekkingrad",
|
||||
"trekking-ignore-cr": "Trekkingrad (ignoriere Radrouten)",
|
||||
"trekking-noferries": "Trekkingrad (keine Fähren)",
|
||||
"trekking-nosteps": "Trekkingrad (keine Treppen)",
|
||||
"trekking-steep": "Trekkingrad (steil)",
|
||||
"vm-forum-liegerad-schnell": "Liegerad (schnell)",
|
||||
"vm-forum-velomobil-schnell": "Velomobil (schnell)"
|
||||
}
|
||||
},
|
||||
"sidebar": {
|
||||
"custom-profile": {
|
||||
"title": "Benutzerdefiniertes Profil"
|
||||
},
|
||||
"data": {
|
||||
"title": "Daten"
|
||||
},
|
||||
"itinerary": {
|
||||
"title": "Reiseroute"
|
||||
},
|
||||
"layers": {
|
||||
"category": {
|
||||
"base-layers": "Grundkarten",
|
||||
"country": "Land",
|
||||
"europe": "Europa",
|
||||
"europe-monolingual": "Europa einsprachig",
|
||||
"overlays": "Überlagerungen",
|
||||
"worldwide": "Weltweit",
|
||||
"worldwide-international": "Weltweit international",
|
||||
"worldwide-monolingual": "Weltweit einsprachig"
|
||||
},
|
||||
"collapse": "Alle zusammenklappen",
|
||||
"custom-layers": "Benutzerdefinierte Ebenen",
|
||||
"customize": "Benutzerdefinierte Ebenen hinzufügen oder entfernen",
|
||||
"expand": "Alle ausklappen",
|
||||
"optional": "Optionale Ebenen hinzufügen oder entfernen",
|
||||
"optional-layers": "Mehr",
|
||||
"table": {
|
||||
"URL": "URL",
|
||||
"empty": "Noch keine benutzerdefinierte Ebene definiert.",
|
||||
"name": "Name",
|
||||
"type": "Type"
|
||||
},
|
||||
"title": "Ebenen"
|
||||
},
|
||||
"profile": {
|
||||
"clear": "Löschen",
|
||||
"help": "Hilfe",
|
||||
"placeholder": "Erstelle benutzerdefiniertes Profil hier.",
|
||||
"upload": "Hochladen"
|
||||
}
|
||||
},
|
||||
"title": "BRouter Web Client",
|
||||
"warning": {
|
||||
"cannot-get-route": "Fehler beim Abrufen der Routen-URL",
|
||||
"no-response": "Keine Antwort vom Server",
|
||||
"no-route-found": "Fehler: kann für angegebene Punkte keine Route finden. Vielleicht die Punkte näher an Straßen verschieben?",
|
||||
"profile-error": "Profil-Fehler: keine oder leere Antwort vom Server",
|
||||
"strava-error": "Fehler beim Laden der Strava Segmente: {{error}}",
|
||||
"temporary-profile": "<strong>Note:</strong> Hochgeladene benutzerdefinierte Profile nur verübergehend auf dem Server zwischengespeichert. <br/>Bitte Bearbeitungen auf dem lokalen PC speichern.",
|
||||
"upload-error": "Fehler beim Hochladen: {{error}}"
|
||||
}
|
||||
}
|
||||
209
locales/en.json
Normal file
209
locales/en.json
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
{
|
||||
"about": {
|
||||
"bug-reports": "Bug reports and feature requests:",
|
||||
"bug-reports-back": "server / backend, routing engine, Android app, profiles, brouter.de site",
|
||||
"bug-reports-front": "web client / frontend.",
|
||||
"chat": "Chat with users and developers",
|
||||
"contact": "Contact:",
|
||||
"data": "Data:",
|
||||
"data-description": "This is based on <a href=\"https://www.openstreetmap.org\" target=\"_blank\">OpenStreetMap</a>. It is usually updated once a week when a new Planet file is available, see dates of <a href=\"http://brouter.de/brouter/segments4/\" target=\"_blank\">data files</a>.",
|
||||
"description": "Online service of the BRouter routing engine. For the offline Android app and more information see <a href=\"http://brouter.de/\" target=\"_blank\">brouter.de</a>",
|
||||
"details": "<i><a href=\"http://brouter.de/privacypolicy.html\" target=\"_blank\">Privacy Policy</a></i>, \n<i><a href=\"https://github.com/nrenner/brouter-web#credits-and-licenses\" target=\"_blank\">Credits</a></i>,\n<i><a href=\"https://github.com/nrenner/brouter-web/blob/master/CHANGELOG.md\" target=\"_blank\">Changelog</a></i> and\n<i><a href=\"https://github.com/nrenner/brouter-web#readme\" target=\"_blank\">more info</a></i> on the client.",
|
||||
"support": "General discussions/questions, support",
|
||||
"title": "About"
|
||||
},
|
||||
"credits": {
|
||||
"brouter": "BRouter",
|
||||
"brouter-license": "<a target=\"_blank\" href=\"http://brouter.de/brouter\">BRouter</a> © Arndt Brenschede",
|
||||
"esri-license": "<a target=\"_blank\" href=\"http://goto.arcgisonline.com/maps/World_Imagery\">World Imagery</a> © <a target=\"_blank\" href=\"https://www.esri.com/\">Esri</a>, sources: Esri, DigitalGlobe, Earthstar Geographics, CNES/Airbus DS, GeoEye, USDA FSA, USGS, Getmapping, Aerogrid, IGN, IGP, and the GIS User Community",
|
||||
"esri-tiles": "Esri World Imagery",
|
||||
"map-data": "Map data",
|
||||
"map-tiles": "Map tiles",
|
||||
"nominatim": "Search by <a href=\"https://wiki.openstreetmap.org/wiki/Nominatim\" target=\"_blank\" data-i18n=\"credits.nominatim\">Nominatim</a>",
|
||||
"openstreetmap": "© <a target=\"_blank\" href=\"https://www.openstreetmap.org/copyright\" >OpenStreetMap contributors</a> under <a target=\"_blank\" href=\"https://opendatacommons.org/licenses/odbl/\" >ODbL</a>"
|
||||
},
|
||||
"export": {
|
||||
"format": "Format",
|
||||
"format_csv": "CSV",
|
||||
"format_geojson": "GeoJSON",
|
||||
"format_gpx": "GPX",
|
||||
"format_kml": "KML",
|
||||
"route-from-to": "{{from}} -> {{to}} ({{distance}}km)",
|
||||
"route-loop": "{{from}} ({{distance}}km)",
|
||||
"title": "Export route",
|
||||
"trackname": "Name"
|
||||
},
|
||||
"footer": {
|
||||
"ascend": "Ascend",
|
||||
"cost": "Cost",
|
||||
"distance": "Distance",
|
||||
"energy-per-100km": "Energy per 100 km",
|
||||
"hours": "hours",
|
||||
"hours-abbrev": "h",
|
||||
"kilometer": "kilometers",
|
||||
"kilometer-abbrev": "km",
|
||||
"kilowatthour": "kilowatt hours",
|
||||
"kilowatthour-abbrev": "kWh",
|
||||
"mean-cost-factor": "Mean cost factor",
|
||||
"meter": "meters",
|
||||
"meter-abbrev": "m",
|
||||
"plain-ascend": "Plain ascend",
|
||||
"total-energy": "Total Energy",
|
||||
"travel-time": "Travel time"
|
||||
},
|
||||
"layers": {
|
||||
"add-base": "Add base layer",
|
||||
"add-overlay": "Add overlay",
|
||||
"customize": "Customize layers",
|
||||
"placeholder-layer-name": "Custom layer name. (ex: OpenStreetMap)",
|
||||
"placeholder-layer-url": "Custom layer URL. (ex: https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png)",
|
||||
"remove-selection": "Remove selection"
|
||||
},
|
||||
"loadNogos": {
|
||||
"defaultProperties": "Default properties",
|
||||
"file": "File: ",
|
||||
"load": "Load",
|
||||
"nogoBuffer": "Buffer no-go areas (in meters): ",
|
||||
"nogoRadius": "No-go radius (for points): ",
|
||||
"nogoWeight": "No-go weight: ",
|
||||
"source": "Source",
|
||||
"title": "Load no-go areas",
|
||||
"url": "URL: "
|
||||
},
|
||||
"map": {
|
||||
"attribution-osm-long": "OpenStreetMap contributors",
|
||||
"attribution-osm-short": "OpenStreetMap",
|
||||
"clear-route": "Clear route",
|
||||
"copyright": "Copyright",
|
||||
"cycling": "Cycling",
|
||||
"delete-last-point": "Delete last point",
|
||||
"delete-nogo-areas": " also delete all no-go areas",
|
||||
"delete-route": "Delete route?",
|
||||
"draw-route-start": "Draw route (D key)",
|
||||
"draw-route-stop": "Stop drawing route (ESC key)",
|
||||
"hikebike-hillshading": "Hillshading",
|
||||
"hiking": "Hiking",
|
||||
"layer": {
|
||||
"bing": "Bing Aerial",
|
||||
"cycle": "OpenCycleMap (Thunderf.)",
|
||||
"cycling": "Cycling (Waymarked Trails)",
|
||||
"digitalglobe": "DigitalGlobe Recent Imagery",
|
||||
"esri": "Esri World Imagery",
|
||||
"hikebike-hillshading": "Hillshading (Hike & Bike Map)",
|
||||
"hiking": "Hiking (Waymarked Trails)",
|
||||
"osm": "OpenStreetMap",
|
||||
"osmde": "OpenStreetMap.de",
|
||||
"outdoors": "Outdoors (Thunderforest)",
|
||||
"stamen-terrain": "Terrain (Stamen)",
|
||||
"strava-segments": "Strava segments",
|
||||
"topo": "OpenTopoMap"
|
||||
},
|
||||
"loading": "Loading…",
|
||||
"locate-me": "Show me where I am",
|
||||
"nogo": {
|
||||
"cancel": "Cancel drawing no-go area",
|
||||
"click-drag": "Click and drag to draw circle",
|
||||
"draw": "Draw no-go area (circle)",
|
||||
"edit": "Click to edit",
|
||||
"help": "□ = move / resize, <span class=\"fa fa-trash-o\"></span> = delete,<br>click circle to quit editing"
|
||||
},
|
||||
"opacity-slider": "Set transparency of route track and markers",
|
||||
"privacy": "Privacy",
|
||||
"reverse-route": "Reverse route",
|
||||
"strava-biking": "Show Strava biking segments",
|
||||
"strava-running": "Show Strava running segments",
|
||||
"zoomInTitle": "Zoom in",
|
||||
"zoomOutTitle": "Zoom out"
|
||||
},
|
||||
"modal": {
|
||||
"close": "Close"
|
||||
},
|
||||
"navbar": {
|
||||
"about": "About",
|
||||
"alternative": {
|
||||
"first": "1st alternative",
|
||||
"original": "Original",
|
||||
"second": "2nd alternative",
|
||||
"third": "3rd alternative"
|
||||
},
|
||||
"export": "Export",
|
||||
"load": {
|
||||
"nogos": "No-go areas",
|
||||
"title": "Load"
|
||||
},
|
||||
"profile": {
|
||||
"car-eco": "Car (economic)",
|
||||
"car-fast": "Car (fast)",
|
||||
"car-test": "Car (test)",
|
||||
"custom": "Custom",
|
||||
"fastbike": "Fastbike",
|
||||
"fastbike-asia-pacific": "Fastbike (Asia Pacific)",
|
||||
"fastbike-lowtraffic": "Fastbike (low traffic)",
|
||||
"hiking-beta": "Hiking (beta)",
|
||||
"moped": "Moped",
|
||||
"rail": "Rail",
|
||||
"river": "River",
|
||||
"safety": "Safety",
|
||||
"shortest": "Shortest",
|
||||
"trekking": "Trekking bike",
|
||||
"trekking-ignore-cr": "Trekking bike (ignore cycle routes)",
|
||||
"trekking-noferries": "Trekking bike (no ferries)",
|
||||
"trekking-nosteps": "Trekking bike (no steps)",
|
||||
"trekking-steep": "Trekking bike (steep)",
|
||||
"vm-forum-liegerad-schnell": "Recumbent bike (fast)",
|
||||
"vm-forum-velomobil-schnell": "Velomobile (fast)"
|
||||
}
|
||||
},
|
||||
"sidebar": {
|
||||
"custom-profile": {
|
||||
"title": "Custom profile"
|
||||
},
|
||||
"data": {
|
||||
"title": "Data"
|
||||
},
|
||||
"itinerary": {
|
||||
"title": "Itinerary"
|
||||
},
|
||||
"layers": {
|
||||
"category": {
|
||||
"base-layers": "Base layers",
|
||||
"country": "Country",
|
||||
"europe": "Europe",
|
||||
"europe-monolingual": "Europe monolingual",
|
||||
"overlays": "Overlays",
|
||||
"worldwide": "Worldwide",
|
||||
"worldwide-international": "Worldwide international",
|
||||
"worldwide-monolingual": "Worldwide monolingual"
|
||||
},
|
||||
"collapse": "Collapse all",
|
||||
"custom-layers": "Custom layers",
|
||||
"customize": "Add or remove custom layers",
|
||||
"expand": "Expand all",
|
||||
"optional": "Add or remove optional layers",
|
||||
"optional-layers": "More",
|
||||
"table": {
|
||||
"URL": "URL",
|
||||
"empty": "No custom layer configured yet.",
|
||||
"name": "Name",
|
||||
"type": "Type"
|
||||
},
|
||||
"title": "Layers"
|
||||
},
|
||||
"profile": {
|
||||
"clear": "Clear",
|
||||
"help": "Help",
|
||||
"placeholder": "Write your custom profile here.",
|
||||
"upload": "Upload"
|
||||
}
|
||||
},
|
||||
"title": "BRouter web client",
|
||||
"warning": {
|
||||
"cannot-get-route": "Error getting route URL",
|
||||
"no-response": "no response from server",
|
||||
"no-route-found": "Error: cannot find a route for given points. Maybe try to move them closer to roads?",
|
||||
"profile-error": "Profile error: no or empty response from server",
|
||||
"strava-error": "Error getting Strava segments: {{error}}",
|
||||
"temporary-profile": "<strong>Note:</strong> Uploaded custom profiles are only cached temporarily on the server.<br/>Please save your edits to your local PC.",
|
||||
"upload-error": "Upload error: {{error}}"
|
||||
}
|
||||
}
|
||||
209
locales/fr.json
Normal file
209
locales/fr.json
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
{
|
||||
"about": {
|
||||
"bug-reports": "Rapporter un problème ou une amélioration :",
|
||||
"bug-reports-back": "serveur, moteur de routage, appli Android, profils, site brouter.de ;",
|
||||
"bug-reports-front": "client web.",
|
||||
"chat": "Discuter avec d'autres utilisateurs et développeurs",
|
||||
"contact": "Contact :",
|
||||
"data": "Données :",
|
||||
"data-description": "Les données reposent sur <a href=\"https://www.openstreetmap.org\" target=\"_blank\">OpenStreetMap</a>. La mise à jour est généralement hebdomadaire, voir <a href=\"http://brouter.de/brouter/segments4/\" target=\"_blank\">les fichiers de données</a>. ",
|
||||
"description": "Service web pour le moteur de routage BRouter. Pour l'appli Android et de plus amples informations, voir <a href=\"http://brouter.de/\" target=\"_blank\">brouter.de</a>.",
|
||||
"details": "<i><a href=\"http://brouter.de/privacypolicy.html\" target=\"_blank\">Respect de la vie privée</a></i>, \n<i><a href=\"https://github.com/nrenner/brouter-web#credits-and-licenses\" target=\"_blank\">Crédits</a></i>,\n<i><a href=\"https://github.com/nrenner/brouter-web/blob/master/CHANGELOG.md\" target=\"_blank\">Changements</a></i> et\n<i><a href=\"https://github.com/nrenner/brouter-web#readme\" target=\"_blank\">plus d'infos</a></i> sur le client web.",
|
||||
"support": "Discussions/Questions générales, support ;",
|
||||
"title": "À propos"
|
||||
},
|
||||
"credits": {
|
||||
"brouter": "BRouter",
|
||||
"brouter-license": "<a target=\"_blank\" href=\"http://brouter.de/brouter\">BRouter</a> © Arndt Brenschede",
|
||||
"esri-license": "<a target=\"_blank\" href=\"http://goto.arcgisonline.com/maps/World_Imagery\">World Imagery</a> © <a target=\"_blank\" href=\"https://www.esri.com/\">Esri</a>, sources : Esri, DigitalGlobe, Earthstar Geographics, CNES/Airbus DS, GeoEye, USDA FSA, USGS, Getmapping, Aerogrid, IGN, IGP, et la communauté d'utilisateurs GIS",
|
||||
"esri-tiles": "Imagerie mondiale Esri",
|
||||
"map-data": "Données de carte",
|
||||
"map-tiles": "Tuiles de carte",
|
||||
"nominatim": "Recherche par <a href=\"https://wiki.openstreetmap.org/wiki/Nominatim\" target=\"_blank\" data-i18n=\"credits.nominatim\">Nominatim</a>",
|
||||
"openstreetmap": "© <a target=\"_blank\" href=\"https://www.openstreetmap.org/copyright\" >contributeurs OpenStreetMap</a> sous <a target=\"_blank\" href=\"https://opendatacommons.org/licenses/odbl/\" >ODbL</a>"
|
||||
},
|
||||
"export": {
|
||||
"format": "Format",
|
||||
"format_csv": "CSV",
|
||||
"format_geojson": "GeoJSON",
|
||||
"format_gpx": "GPX",
|
||||
"format_kml": "KML",
|
||||
"route-from-to": "{{from}} -> {{to}} ({{distance}} km)",
|
||||
"route-loop": "{{from}} ({{distance}} km)",
|
||||
"title": "Exporter l'itinéraire",
|
||||
"trackname": "Nom"
|
||||
},
|
||||
"footer": {
|
||||
"ascend": "Dénivelé cumulé",
|
||||
"cost": "Coût",
|
||||
"distance": "Distance",
|
||||
"energy-per-100km": "pour 100km",
|
||||
"hours": "heures",
|
||||
"hours-abbrev": "h",
|
||||
"kilometer": "kilomètres",
|
||||
"kilometer-abbrev": "km",
|
||||
"kilowatthour": "kilowattheures",
|
||||
"kilowatthour-abbrev": "kWh",
|
||||
"mean-cost-factor": "Facteur coût moyen",
|
||||
"meter": "mètres",
|
||||
"meter-abbrev": "m",
|
||||
"plain-ascend": "global",
|
||||
"total-energy": "Énergie totale",
|
||||
"travel-time": "Temps de trajet"
|
||||
},
|
||||
"layers": {
|
||||
"add-base": "Ajouter un fond de carte ",
|
||||
"add-overlay": "Ajouter un calque superposable",
|
||||
"customize": "Personnaliser les calques",
|
||||
"placeholder-layer-name": "Nom du calque (p. ex. OpenStreetMap).",
|
||||
"placeholder-layer-url": "URL du calque (p. ex. https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png).",
|
||||
"remove-selection": "Supprimer la sélection"
|
||||
},
|
||||
"loadNogos": {
|
||||
"defaultProperties": "Propriétés par défaut",
|
||||
"file": "Fichier :",
|
||||
"load": "Charger",
|
||||
"nogoBuffer": "Tampon des zones interdites (en mètres) :",
|
||||
"nogoRadius": "Rayon des zones interdites (pour les points) :",
|
||||
"nogoWeight": "Poids des zones interdites :",
|
||||
"source": "Source",
|
||||
"title": "Charger les zones interdites",
|
||||
"url": "URL :"
|
||||
},
|
||||
"map": {
|
||||
"attribution-osm-long": "Contributeurs OpenStreetMap",
|
||||
"attribution-osm-short": "OpenStreetMap",
|
||||
"clear-route": "Supprimer l'itinéraire",
|
||||
"copyright": "Copyright",
|
||||
"cycling": "Vélo",
|
||||
"delete-last-point": "Supprimer le dernier point",
|
||||
"delete-nogo-areas": " supprimer aussi toutes les zones interdites",
|
||||
"delete-route": "Supprimer l'itinéraire ?",
|
||||
"draw-route-start": "Dessiner l'itinéraire (touche D)",
|
||||
"draw-route-stop": "Arrêter de dessiner l'itinéraire (touche ECH)",
|
||||
"hikebike-hillshading": "Relief avec ombre",
|
||||
"hiking": "Randonnée",
|
||||
"layer": {
|
||||
"bing": "Imagerie aérienne BING",
|
||||
"cycle": "OpenCycleMap (Thunderf.)",
|
||||
"cycling": "Cycling (Sentiers balisés)",
|
||||
"digitalglobe": "Imagerie récente DigitalGlobe",
|
||||
"esri": "Imagerie mondiale Esri",
|
||||
"hikebike-hillshading": "Relief avec ombre (carte randonnée et vélo)",
|
||||
"hiking": "Randonnée (Sentiers balisés)",
|
||||
"osm": "OpenStreetMap",
|
||||
"osmde": "OpenStreetMap.de",
|
||||
"outdoors": "Extérieur (Thunderforest)",
|
||||
"stamen-terrain": "Terrain (Stamen)",
|
||||
"strava-segments": "Segments Strava",
|
||||
"topo": "OpenTopoMap"
|
||||
},
|
||||
"loading": "Chargement…",
|
||||
"locate-me": "Où suis-je ?",
|
||||
"nogo": {
|
||||
"cancel": "Annuler la zone interdite",
|
||||
"click-drag": "Cliquer et faire glisser pour dessiner un cercle",
|
||||
"draw": "Dessiner une zone interdite (cercle)",
|
||||
"edit": "Cliquer pour éditer",
|
||||
"help": "□ = déplacer / redimensionner, <span class=\"fa fa-trash-o\"></span> = supprimer,<br>cliquer sur le cercle pour arrêter l'édition"
|
||||
},
|
||||
"opacity-slider": "Définie l'opacité de l'itinéraire et des marqueurs",
|
||||
"privacy": "Vie privée",
|
||||
"reverse-route": "Inverse l'itinéraire",
|
||||
"strava-biking": "Afficher les segments Strava vélo",
|
||||
"strava-running": "Afficher les segments Strava à pied",
|
||||
"zoomInTitle": "Zoomer",
|
||||
"zoomOutTitle": "Dézoomer"
|
||||
},
|
||||
"modal": {
|
||||
"close": "Fermer"
|
||||
},
|
||||
"navbar": {
|
||||
"about": "À propos",
|
||||
"alternative": {
|
||||
"first": "1ère alternative",
|
||||
"original": "Originale",
|
||||
"second": "2nde alternative",
|
||||
"third": "3ème alternative"
|
||||
},
|
||||
"export": "Exporter",
|
||||
"load": {
|
||||
"nogos": "Zones interdites",
|
||||
"title": "Charger"
|
||||
},
|
||||
"profile": {
|
||||
"car-eco": "Voiture (économique)",
|
||||
"car-fast": "Voiture (rapide)",
|
||||
"car-test": "Voiture (test)",
|
||||
"custom": "Personnalisé",
|
||||
"fastbike": "Vélo de route",
|
||||
"fastbike-asia-pacific": "Vélo de route (Asie Pacifique)",
|
||||
"fastbike-lowtraffic": "Vélo de route (faible traffic)",
|
||||
"hiking-beta": "Randonnée (beta)",
|
||||
"moped": "Mobylette",
|
||||
"rail": "Train",
|
||||
"river": "Fluvial",
|
||||
"safety": "Sécurité",
|
||||
"shortest": "Le plus court",
|
||||
"trekking": "Cyclotourisme",
|
||||
"trekking-ignore-cr": "Cycloutourisme (ignore pistes cyclables)",
|
||||
"trekking-noferries": "Cyclotourisme (pas de ferries)",
|
||||
"trekking-nosteps": "Cyclotourisme (pas d'escaliers)",
|
||||
"trekking-steep": "Cyclotourisme (escarpé)",
|
||||
"vm-forum-liegerad-schnell": "Vélo couché (rapide)",
|
||||
"vm-forum-velomobil-schnell": "Vélomobile (rapide)"
|
||||
}
|
||||
},
|
||||
"sidebar": {
|
||||
"custom-profile": {
|
||||
"title": "Profil personnalisé"
|
||||
},
|
||||
"data": {
|
||||
"title": "Données"
|
||||
},
|
||||
"itinerary": {
|
||||
"title": "Itinéraire"
|
||||
},
|
||||
"layers": {
|
||||
"category": {
|
||||
"base-layers": "Fonds de carte",
|
||||
"country": "Pays",
|
||||
"europe": "Europe",
|
||||
"europe-monolingual": "Europe monolingue",
|
||||
"overlays": "Calques superposables",
|
||||
"worldwide": "Mondial",
|
||||
"worldwide-international": "Mondial international",
|
||||
"worldwide-monolingual": "Mondial monolingue"
|
||||
},
|
||||
"collapse": "Tout réduire",
|
||||
"custom-layers": "Calques personels",
|
||||
"customize": "Ajouter ou supprimer des calques",
|
||||
"expand": "Tout ouvrir",
|
||||
"optional": "Ajouter ou supprimer des calques optionnels",
|
||||
"optional-layers": "Plus",
|
||||
"table": {
|
||||
"URL": "URL",
|
||||
"empty": "Aucun calque personnel trouvé.",
|
||||
"name": "Nom",
|
||||
"type": "Type"
|
||||
},
|
||||
"title": "Calques"
|
||||
},
|
||||
"profile": {
|
||||
"clear": "Nettoyer",
|
||||
"help": "Aide",
|
||||
"placeholder": "Saisissez votre profil personnalisé ici.",
|
||||
"upload": "Envoyer"
|
||||
}
|
||||
},
|
||||
"title": "Client web BRouter",
|
||||
"warning": {
|
||||
"cannot-get-route": "Erreur lors de la réception de l'itinéraire",
|
||||
"no-response": "aucune réponse du serveur",
|
||||
"no-route-found": "Erreur : impossible de trouver un itinéraire correspondant aux points donnés. Essayez peut-être de rapprocher les points des routes ?",
|
||||
"profile-error": "Erreur de profil : pas de réponse ou réponse invalide du serveur",
|
||||
"strava-error": "Impossible d'afficher les segments Strava : {{error}}",
|
||||
"temporary-profile": "<strong>Note :</strong> Les profils personnalisés téléversés ne sont disponibles que temporairement sur le serveur.<br/>Merci de sauvegarder votre profil sur votre ordinateur.",
|
||||
"upload-error": "Erreur d'envoi : {{error}}"
|
||||
}
|
||||
}
|
||||
209
locales/gl.json
Normal file
209
locales/gl.json
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
{
|
||||
"about": {
|
||||
"bug-reports": "Bug reports and feature requests:",
|
||||
"bug-reports-back": "server / backend, routing engine, Android app, profiles, brouter.de site",
|
||||
"bug-reports-front": "web client / frontend.",
|
||||
"chat": "Chat with users and developers",
|
||||
"contact": "Contacto:",
|
||||
"data": "Datos:",
|
||||
"data-description": "This is based on <a href=\"https://www.openstreetmap.org\" target=\"_blank\">OpenStreetMap</a>. It is usually updated once a week when a new Planet file is available, see dates of <a href=\"http://brouter.de/brouter/segments4/\" target=\"_blank\">data files</a>.",
|
||||
"description": "Online service of the BRouter routing engine. For the offline Android app and more information see <a href=\"http://brouter.de/\" target=\"_blank\">brouter.de</a>",
|
||||
"details": "<i><a href=\"http://brouter.de/privacypolicy.html\" target=\"_blank\">Privacy Policy</a></i>, \n<i><a href=\"https://github.com/nrenner/brouter-web#credits-and-licenses\" target=\"_blank\">Credits</a></i>,\n<i><a href=\"https://github.com/nrenner/brouter-web/blob/master/CHANGELOG.md\" target=\"_blank\">Changelog</a></i> and\n<i><a href=\"https://github.com/nrenner/brouter-web#readme\" target=\"_blank\">more info</a></i> on the client.",
|
||||
"support": "General discussions/questions, support",
|
||||
"title": "Sobre nós"
|
||||
},
|
||||
"credits": {
|
||||
"brouter": "BRouter",
|
||||
"brouter-license": "<a target=\"_blank\" href=\"http://brouter.de/brouter\">BRouter</a> © Arndt Brenschede",
|
||||
"esri-license": "<a target=\"_blank\" href=\"http://goto.arcgisonline.com/maps/World_Imagery\">World Imagery</a> © <a target=\"_blank\" href=\"https://www.esri.com/\">Esri</a>, sources: Esri, DigitalGlobe, Earthstar Geographics, CNES/Airbus DS, GeoEye, USDA FSA, USGS, Getmapping, Aerogrid, IGN, IGP, and the GIS User Community",
|
||||
"esri-tiles": "Esri World Imagery",
|
||||
"map-data": "Map data",
|
||||
"map-tiles": "Map tiles",
|
||||
"nominatim": "Search by <a href=\"https://wiki.openstreetmap.org/wiki/Nominatim\" target=\"_blank\" data-i18n=\"credits.nominatim\">Nominatim</a>",
|
||||
"openstreetmap": "© <a target=\"_blank\" href=\"https://www.openstreetmap.org/copyright\" >OpenStreetMap contributors</a> under <a target=\"_blank\" href=\"https://opendatacommons.org/licenses/odbl/\" >ODbL</a>"
|
||||
},
|
||||
"export": {
|
||||
"format": "Format",
|
||||
"format_csv": "CSV",
|
||||
"format_geojson": "GeoJSON",
|
||||
"format_gpx": "GPX",
|
||||
"format_kml": "KML",
|
||||
"route-from-to": "{{from}} -> {{to}} ({{distance}}km)",
|
||||
"route-loop": "{{from}} ({{distance}}km)",
|
||||
"title": "Export route",
|
||||
"trackname": "Name"
|
||||
},
|
||||
"footer": {
|
||||
"ascend": "Ascend",
|
||||
"cost": "Cost",
|
||||
"distance": "Distance",
|
||||
"energy-per-100km": "Energy per 100 km",
|
||||
"hours": "hours",
|
||||
"hours-abbrev": "h",
|
||||
"kilometer": "kilometers",
|
||||
"kilometer-abbrev": "km",
|
||||
"kilowatthour": "kilowatt hours",
|
||||
"kilowatthour-abbrev": "kWh",
|
||||
"mean-cost-factor": "Mean cost factor",
|
||||
"meter": "meters",
|
||||
"meter-abbrev": "m",
|
||||
"plain-ascend": "Plain ascend",
|
||||
"total-energy": "Total Energy",
|
||||
"travel-time": "Travel time"
|
||||
},
|
||||
"layers": {
|
||||
"add-base": "Add base layer",
|
||||
"add-overlay": "Add overlay",
|
||||
"customize": "Customize layers",
|
||||
"placeholder-layer-name": "Custom layer name. (ex: OpenStreetMap)",
|
||||
"placeholder-layer-url": "Custom layer URL. (ex: https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png)",
|
||||
"remove-selection": "Remove selection"
|
||||
},
|
||||
"loadNogos": {
|
||||
"defaultProperties": "Default properties",
|
||||
"file": "File: ",
|
||||
"load": "Load",
|
||||
"nogoBuffer": "Buffer no-go areas (in meters): ",
|
||||
"nogoRadius": "No-go radius (for points): ",
|
||||
"nogoWeight": "No-go weight: ",
|
||||
"source": "Source",
|
||||
"title": "Load no-go areas",
|
||||
"url": "URL: "
|
||||
},
|
||||
"map": {
|
||||
"attribution-osm-long": "OpenStreetMap contributors",
|
||||
"attribution-osm-short": "OpenStreetMap",
|
||||
"clear-route": "Clear route",
|
||||
"copyright": "Copyright",
|
||||
"cycling": "Cycling",
|
||||
"delete-last-point": "Delete last point",
|
||||
"delete-nogo-areas": " also delete all no-go areas",
|
||||
"delete-route": "Delete route?",
|
||||
"draw-route-start": "Draw route (D key)",
|
||||
"draw-route-stop": "Stop drawing route (ESC key)",
|
||||
"hikebike-hillshading": "Hillshading",
|
||||
"hiking": "Hiking",
|
||||
"layer": {
|
||||
"bing": "Bing Aerial",
|
||||
"cycle": "OpenCycleMap (Thunderf.)",
|
||||
"cycling": "Cycling (Waymarked Trails)",
|
||||
"digitalglobe": "DigitalGlobe Recent Imagery",
|
||||
"esri": "Esri World Imagery",
|
||||
"hikebike-hillshading": "Hillshading (Hike & Bike Map)",
|
||||
"hiking": "Hiking (Waymarked Trails)",
|
||||
"osm": "OpenStreetMap",
|
||||
"osmde": "OpenStreetMap.de",
|
||||
"outdoors": "Outdoors (Thunderforest)",
|
||||
"stamen-terrain": "Terrain (Stamen)",
|
||||
"strava-segments": "Strava segments",
|
||||
"topo": "OpenTopoMap"
|
||||
},
|
||||
"loading": "Loading…",
|
||||
"locate-me": "Show me where I am",
|
||||
"nogo": {
|
||||
"cancel": "Cancel drawing no-go area",
|
||||
"click-drag": "Click and drag to draw circle",
|
||||
"draw": "Draw no-go area (circle)",
|
||||
"edit": "Click to edit",
|
||||
"help": "□ = move / resize, <span class=\"fa fa-trash-o\"></span> = delete,<br>click circle to quit editing"
|
||||
},
|
||||
"opacity-slider": "Set transparency of route track and markers",
|
||||
"privacy": "Privacy",
|
||||
"reverse-route": "Reverse route",
|
||||
"strava-biking": "Show Strava biking segments",
|
||||
"strava-running": "Show Strava running segments",
|
||||
"zoomInTitle": "Zoom in",
|
||||
"zoomOutTitle": "Zoom out"
|
||||
},
|
||||
"modal": {
|
||||
"close": "Close"
|
||||
},
|
||||
"navbar": {
|
||||
"about": "About",
|
||||
"alternative": {
|
||||
"first": "1st alternative",
|
||||
"original": "Original",
|
||||
"second": "2nd alternative",
|
||||
"third": "3rd alternative"
|
||||
},
|
||||
"export": "Export",
|
||||
"load": {
|
||||
"nogos": "No-go areas",
|
||||
"title": "Load"
|
||||
},
|
||||
"profile": {
|
||||
"car-eco": "Car (economic)",
|
||||
"car-fast": "Car (fast)",
|
||||
"car-test": "Car (test)",
|
||||
"custom": "Custom",
|
||||
"fastbike": "Fastbike",
|
||||
"fastbike-asia-pacific": "Fastbike (Asia Pacific)",
|
||||
"fastbike-lowtraffic": "Fastbike (low traffic)",
|
||||
"hiking-beta": "Hiking (beta)",
|
||||
"moped": "Moped",
|
||||
"rail": "Rail",
|
||||
"river": "River",
|
||||
"safety": "Safety",
|
||||
"shortest": "Shortest",
|
||||
"trekking": "Trekking bike",
|
||||
"trekking-ignore-cr": "Trekking bike (ignore cycle routes)",
|
||||
"trekking-noferries": "Trekking bike (no ferries)",
|
||||
"trekking-nosteps": "Trekking bike (no steps)",
|
||||
"trekking-steep": "Trekking bike (steep)",
|
||||
"vm-forum-liegerad-schnell": "Recumbent bike (fast)",
|
||||
"vm-forum-velomobil-schnell": "Velomobile (fast)"
|
||||
}
|
||||
},
|
||||
"sidebar": {
|
||||
"custom-profile": {
|
||||
"title": "Custom profile"
|
||||
},
|
||||
"data": {
|
||||
"title": "Data"
|
||||
},
|
||||
"itinerary": {
|
||||
"title": "Itinerary"
|
||||
},
|
||||
"layers": {
|
||||
"category": {
|
||||
"base-layers": "Base layers",
|
||||
"country": "Country",
|
||||
"europe": "Europe",
|
||||
"europe-monolingual": "Europe monolingual",
|
||||
"overlays": "Overlays",
|
||||
"worldwide": "Worldwide",
|
||||
"worldwide-international": "Worldwide international",
|
||||
"worldwide-monolingual": "Worldwide monolingual"
|
||||
},
|
||||
"collapse": "Collapse all",
|
||||
"custom-layers": "Custom layers",
|
||||
"customize": "Add or remove custom layers",
|
||||
"expand": "Expand all",
|
||||
"optional": "Add or remove optional layers",
|
||||
"optional-layers": "More",
|
||||
"table": {
|
||||
"URL": "URL",
|
||||
"empty": "No custom layer configured yet.",
|
||||
"name": "Name",
|
||||
"type": "Type"
|
||||
},
|
||||
"title": "Layers"
|
||||
},
|
||||
"profile": {
|
||||
"clear": "Clear",
|
||||
"help": "Help",
|
||||
"placeholder": "Write your custom profile here.",
|
||||
"upload": "Upload"
|
||||
}
|
||||
},
|
||||
"title": "BRouter web client",
|
||||
"warning": {
|
||||
"cannot-get-route": "Error getting route URL",
|
||||
"no-response": "no response from server",
|
||||
"no-route-found": "Error: cannot find a route for given points. Maybe try to move them closer to roads?",
|
||||
"profile-error": "Profile error: no or empty response from server",
|
||||
"strava-error": "Error getting Strava segments: {{error}}",
|
||||
"temporary-profile": "<strong>Note:</strong> Uploaded custom profiles are only cached temporarily on the server.<br/>Please save your edits to your local PC.",
|
||||
"upload-error": "Upload error: {{error}}"
|
||||
}
|
||||
}
|
||||
209
locales/hu.json
Normal file
209
locales/hu.json
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
{
|
||||
"about": {
|
||||
"bug-reports": "Hibák és kérések bejelentése:",
|
||||
"bug-reports-back": "kiszolgálóoldal / back end, útvonaltervező motor, Android alkalmazás, profilok, brouter.de weboldal",
|
||||
"bug-reports-front": "weboldali kliens / frontend.",
|
||||
"chat": "Chat with users and developers",
|
||||
"contact": "Kapcsolat:",
|
||||
"data": "Adatok:",
|
||||
"data-description": "Az adatok alapja az <a href=\"https://www.openstreetmap.org\" target=\"_blank\">OpenStreetMap</a>. Az oldal általában hetente frissül, amikor az új bolygófájl (Planet fájl) elérhetővé válik. A dátumok megtalálhatók az <a href=\"http://brouter.de/brouter/segments4/\" target=\"_blank\">adatfájlokban</a>.",
|
||||
"description": "Ez itt a BRouter útvonaltervező motor online szolgáltatása. Az Android alkalmazásról és a további információkról a <a href=\"http://brouter.de/\" target=\"_blank\">brouter.de</a> oldalon olvashat.",
|
||||
"details": "<i><a href=\"http://brouter.de/privacypolicy.html\" target=\"_blank\">Adatvédelmi irányelvek</a></i> \n<i><a href=\"https://github.com/nrenner/brouter-web#credits-and-licenses\" target=\"_blank\">stáblista</a></i>,\n<i><a href=\"https://github.com/nrenner/brouter-web/blob/master/CHANGELOG.md\" target=\"_blank\">változásnapló</a></i> és\n<i><a href=\"https://github.com/nrenner/brouter-web#readme\" target=\"_blank\">további tájékoztatás</a></i> a kliensen.",
|
||||
"support": "Általános viták/kérdések, támogatás",
|
||||
"title": "Névjegy"
|
||||
},
|
||||
"credits": {
|
||||
"brouter": "BRouter",
|
||||
"brouter-license": "<a target=\"_blank\" href=\"http://brouter.de/brouter\">BRouter</a> © Arndt Brenschede",
|
||||
"esri-license": "<a target=\"_blank\" href=\"http://goto.arcgisonline.com/maps/World_Imagery\">Globális légi felvételek</a> © <a target=\"_blank\" href=\"https://www.esri.com/\">Esri</a>, források: Esri, DigitalGlobe, Earthstar Geographics, CNES/Airbus DS, GeoEye, USDA FSA, USGS, Getmapping, Aerogrid, IGN, IGP valamint a GIS felhasználói közösség",
|
||||
"esri-tiles": "Esri World Imagery",
|
||||
"map-data": "Térképadatok",
|
||||
"map-tiles": "Map tiles",
|
||||
"nominatim": "Keresés: <a href=\"https://wiki.openstreetmap.org/wiki/Nominatim\" target=\"_blank\" data-i18n=\"credits.nominatim\">Nominatim</a>",
|
||||
"openstreetmap": "© <a target=\"_blank\" href=\"https://www.openstreetmap.org/copyright\" >OpenStreetMap közreműködők</a>, <a target=\"_blank\" href=\"https://opendatacommons.org/licenses/odbl/\" >ODbL</a> licenc szerint"
|
||||
},
|
||||
"export": {
|
||||
"format": "Formátum",
|
||||
"format_csv": "CSV",
|
||||
"format_geojson": "GeoJSON",
|
||||
"format_gpx": "GPX",
|
||||
"format_kml": "KML",
|
||||
"route-from-to": "{{from}} -> {{to}} ({{distance}} km)",
|
||||
"route-loop": "{{from}} ({{distance}} km)",
|
||||
"title": "Útvonal exportálása",
|
||||
"trackname": "Név"
|
||||
},
|
||||
"footer": {
|
||||
"ascend": "Összes szintkülönbség",
|
||||
"cost": "Ráfordítás",
|
||||
"distance": "Távolság",
|
||||
"energy-per-100km": "Energia / 100 km",
|
||||
"hours": "óra",
|
||||
"hours-abbrev": "h",
|
||||
"kilometer": "kilométer",
|
||||
"kilometer-abbrev": "km",
|
||||
"kilowatthour": "kilowattóra",
|
||||
"kilowatthour-abbrev": "kWh",
|
||||
"mean-cost-factor": "Közepes ráfordítástényező",
|
||||
"meter": "méter",
|
||||
"meter-abbrev": "m",
|
||||
"plain-ascend": "Végpontok közötti szintkülönbség",
|
||||
"total-energy": "Teljes energiafelhasználás",
|
||||
"travel-time": "Utazási idő"
|
||||
},
|
||||
"layers": {
|
||||
"add-base": "Alapréteg hozzáadása",
|
||||
"add-overlay": "Rátétréteg hozzáadása",
|
||||
"customize": "Rétegek személyre szabása",
|
||||
"placeholder-layer-name": "Egyedi rétegnév (pl. OpenStreetMap)",
|
||||
"placeholder-layer-url": "Egyedi réteg URL-je (pl. https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png)",
|
||||
"remove-selection": "Kijelölés eltávolítása"
|
||||
},
|
||||
"loadNogos": {
|
||||
"defaultProperties": "Alapértelmezett tulajdonságok",
|
||||
"file": "Fájl:",
|
||||
"load": "Betöltés",
|
||||
"nogoBuffer": "Elkerülendő területek körüli távolság (méter)",
|
||||
"nogoRadius": "Elkerülendő pontok körüli sugár:",
|
||||
"nogoWeight": "Elkerülés súlyozása:",
|
||||
"source": "Forrás",
|
||||
"title": "Elkerülendő területek betöltése",
|
||||
"url": "URL:"
|
||||
},
|
||||
"map": {
|
||||
"attribution-osm-long": "OpenStreetMap közreműködők",
|
||||
"attribution-osm-short": "OpenStreetMap",
|
||||
"clear-route": "Útvonal törlése",
|
||||
"copyright": "Szerzői jogok",
|
||||
"cycling": "Kerékpározás",
|
||||
"delete-last-point": "Utolsó pont törlése",
|
||||
"delete-nogo-areas": " törlődjenek az elkerülendő területek is",
|
||||
"delete-route": "Útvonal törlése?",
|
||||
"draw-route-start": "Útvonal rajzolása (D billentyű)",
|
||||
"draw-route-stop": "Útvonal rajzolásának megszakítása (ESC billentyű)",
|
||||
"hikebike-hillshading": "Domborzatárnyékolás",
|
||||
"hiking": "Túrázás",
|
||||
"layer": {
|
||||
"bing": "Bing Aerial",
|
||||
"cycle": "OpenCycleMap (Thunderfores)",
|
||||
"cycling": "Kerékpározás (Waymarked Trails)",
|
||||
"digitalglobe": "DigitalGlobe Recent Imagery",
|
||||
"esri": "Esri World Imagery",
|
||||
"hikebike-hillshading": "Domborzatárnyékolás (Hike & Bike Map)",
|
||||
"hiking": "Túrázás (Waymarked Trails)",
|
||||
"osm": "OpenStreetMap",
|
||||
"osmde": "OpenStreetMap.de",
|
||||
"outdoors": "Outdoors (Thunderforest)",
|
||||
"stamen-terrain": "Terrain (Stamen)",
|
||||
"strava-segments": "Strava útvonalszakaszok",
|
||||
"topo": "OpenTopoMap"
|
||||
},
|
||||
"loading": "Betöltés…",
|
||||
"locate-me": "Mutassa a térképen, hol vagyok",
|
||||
"nogo": {
|
||||
"cancel": "Elkerülendő terület rajzolásának megszakítása",
|
||||
"click-drag": "Kör rajzolása kattintással és húzással",
|
||||
"draw": "Elkerülendő terület rajzolása (kör)",
|
||||
"edit": "Szerkesztés kattintással",
|
||||
"help": "□ = áthelyezés / átméretezés, <span class=\"fa fa-trash-o\"></span> = törlés,<br>a szerkesztés befejezéséhez kattintson a körre"
|
||||
},
|
||||
"opacity-slider": "Nyomvonal és jelölők átlátszóságának beállítása",
|
||||
"privacy": "Adatvédelem",
|
||||
"reverse-route": "Útvonal megfordítása",
|
||||
"strava-biking": "Strava motoros útvonalszakaszok megjelenítése",
|
||||
"strava-running": "Strava futó útvonalszakaszok megjelenítése",
|
||||
"zoomInTitle": "Nagyítás",
|
||||
"zoomOutTitle": "Kicsinyítés"
|
||||
},
|
||||
"modal": {
|
||||
"close": "Bezárás"
|
||||
},
|
||||
"navbar": {
|
||||
"about": "Névjegy",
|
||||
"alternative": {
|
||||
"first": "1. alternatíva",
|
||||
"original": "Eredeti",
|
||||
"second": "2. alternatíva",
|
||||
"third": "3. alternatíva"
|
||||
},
|
||||
"export": "Exportálás",
|
||||
"load": {
|
||||
"nogos": "Elkerülendő területek",
|
||||
"title": "Betöltés"
|
||||
},
|
||||
"profile": {
|
||||
"car-eco": "Személyautó (gazdaságos)",
|
||||
"car-fast": "Személyautó (gyors)",
|
||||
"car-test": "Személyautó (teszt)",
|
||||
"custom": "Egyedi",
|
||||
"fastbike": "Versenykerékpár",
|
||||
"fastbike-asia-pacific": "Versenykerékpár (ázsiai-csendes-óceáni térség)",
|
||||
"fastbike-lowtraffic": "Versenykerékpár (kis forgalom)",
|
||||
"hiking-beta": "Túrázás (béta)",
|
||||
"moped": "Robogó",
|
||||
"rail": "Vasút",
|
||||
"river": "Hajózás",
|
||||
"safety": "Biztonság",
|
||||
"shortest": "Legrövidebb",
|
||||
"trekking": "Túrakerékpár",
|
||||
"trekking-ignore-cr": "Túrakerékpár (kerékpárutak figyelmen kívül hagyása)",
|
||||
"trekking-noferries": "Túrakerékpár (komp nélkül)",
|
||||
"trekking-nosteps": "Túrakerékpár (lépcső nélkül)",
|
||||
"trekking-steep": "Túrakerékpár (meredek)",
|
||||
"vm-forum-liegerad-schnell": "Rekumbens kerékpár (gyors)",
|
||||
"vm-forum-velomobil-schnell": "Velomobil (aerodinamikus kerékpár, gyors)"
|
||||
}
|
||||
},
|
||||
"sidebar": {
|
||||
"custom-profile": {
|
||||
"title": "Egyedi profil"
|
||||
},
|
||||
"data": {
|
||||
"title": "Adatok"
|
||||
},
|
||||
"itinerary": {
|
||||
"title": "Útiterv"
|
||||
},
|
||||
"layers": {
|
||||
"category": {
|
||||
"base-layers": "Alaprétegek",
|
||||
"country": "Ország",
|
||||
"europe": "Európa",
|
||||
"europe-monolingual": "Európa (egynyelvű)",
|
||||
"overlays": "Rátétrétegek",
|
||||
"worldwide": "Világ",
|
||||
"worldwide-international": "Világ (nemzetközi)",
|
||||
"worldwide-monolingual": "Világ (egynyelvű)"
|
||||
},
|
||||
"collapse": "Minden összecsukása",
|
||||
"custom-layers": "Egyedi rétegek",
|
||||
"customize": "Egyedi rétegek hozzáadása vagy eltávolítása",
|
||||
"expand": "Minden kibontása",
|
||||
"optional": "Rétegek hozzáadása vagy eltávolítása",
|
||||
"optional-layers": "Több",
|
||||
"table": {
|
||||
"URL": "URL",
|
||||
"empty": "Még nincs beállítva egyedi réteg",
|
||||
"name": "Név",
|
||||
"type": "Típus"
|
||||
},
|
||||
"title": "Rétegek"
|
||||
},
|
||||
"profile": {
|
||||
"clear": "Törlés",
|
||||
"help": "Súgó",
|
||||
"placeholder": "Ide írhatja egyedi profilját",
|
||||
"upload": "Feltöltés"
|
||||
}
|
||||
},
|
||||
"title": "BRouter webkliens",
|
||||
"warning": {
|
||||
"cannot-get-route": "Hiba történt az útvonal URL-jének beolvasásakor",
|
||||
"no-response": "a kiszolgáló nem válaszol",
|
||||
"no-route-found": "Hiba: az adott pontokhoz nem sikerül útvonalat találni. Esetleg próbálja meg közelebb tenni őket az utakhoz.",
|
||||
"profile-error": "Profilhiba: a kiszolgáló nem válaszol vagy üres választ küld",
|
||||
"strava-error": "Hiba történt a Strava útvonalszakaszok lekérésénél: {{error}}",
|
||||
"temporary-profile": "<strong>Figyelem:</strong> A kiszolgáló csak ideiglenesen gyorsítótárazza a feltöltött egyedi profilokat.<br/>Kérjük, szerkesztéseit mentse el saját számítógépére.",
|
||||
"upload-error": "Feltöltési hiba: {{error}}"
|
||||
}
|
||||
}
|
||||
36
locales/keys.js
Normal file
36
locales/keys.js
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
// this file contains translatable keys that are dynamic / not visible by i18n extractor tool
|
||||
i18next.t('navbar.profile.car-eco');
|
||||
i18next.t('navbar.profile.car-fast');
|
||||
i18next.t('navbar.profile.car-test');
|
||||
i18next.t('navbar.profile.fastbike');
|
||||
i18next.t('navbar.profile.fastbike-asia-pacific');
|
||||
i18next.t('navbar.profile.fastbike-asia-pacific');
|
||||
i18next.t('navbar.profile.fastbike-lowtraffic');
|
||||
i18next.t('navbar.profile.hiking-beta');
|
||||
i18next.t('navbar.profile.moped');
|
||||
i18next.t('navbar.profile.rail');
|
||||
i18next.t('navbar.profile.river');
|
||||
i18next.t('navbar.profile.safety');
|
||||
i18next.t('navbar.profile.shortest');
|
||||
i18next.t('navbar.profile.trekking');
|
||||
i18next.t('navbar.profile.trekking-ignore-cr');
|
||||
i18next.t('navbar.profile.trekking-noferries');
|
||||
i18next.t('navbar.profile.trekking-nosteps');
|
||||
i18next.t('navbar.profile.trekking-steep');
|
||||
i18next.t('navbar.profile.vm-forum-liegerad-schnell');
|
||||
i18next.t('navbar.profile.vm-forum-velomobil-schnell');
|
||||
|
||||
i18next.t('sidebar.layers.category.base-layers', 'Base layers');
|
||||
i18next.t(
|
||||
'sidebar.layers.category.worldwide-international',
|
||||
'Worldwide international'
|
||||
);
|
||||
i18next.t(
|
||||
'sidebar.layers.category.worldwide-monolingual',
|
||||
'Worldwide monolingual'
|
||||
);
|
||||
i18next.t('sidebar.layers.category.europe', 'Europe');
|
||||
i18next.t('sidebar.layers.category.europe-monolingual', 'Europe monolingual');
|
||||
i18next.t('sidebar.layers.category.country', 'Country');
|
||||
i18next.t('sidebar.layers.category.overlays', 'Overlays');
|
||||
i18next.t('sidebar.layers.category.worldwide', 'Worldwide');
|
||||
209
locales/pl.json
Normal file
209
locales/pl.json
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
{
|
||||
"about": {
|
||||
"bug-reports": "Zgłaszanie błędów i nowych funkcji:",
|
||||
"bug-reports-back": "serwer / aplikacja, silnik wyznaczania tras, aplikacja na Androida, profile, strona brouter.de",
|
||||
"bug-reports-front": "klient przeglądarkowy / interfejs.",
|
||||
"chat": "Czat z użytkownikami i twórcami",
|
||||
"contact": "Kontakt:",
|
||||
"data": "Dane:",
|
||||
"data-description": "Bazujemy na <a href=\"https://www.openstreetmap.org\" target=\"_blank\">OpenStreetMap</a>. Aktualizacje są zazwyczaj raz w tygodniu, kiedy są dostępne nowe pliki Planet, więc sprawdź daty <a href=\"http://brouter.de/brouter/segments4/\" target=\"_blank\">plików z danymi</a>.",
|
||||
"description": "Dostęp online do silnika wyznaczania tras BRouter. Aplikację offline na Androida i więcej informacji znajdziesz na <a href=\"http://brouter.de/\" target=\"_blank\">brouter.de</a>",
|
||||
"details": "<i><a href=\"http://brouter.de/privacypolicy.html\" target=\"_blank\">Polityka prywatności</a></i>, \n<i><a href=\"https://github.com/nrenner/brouter-web#credits-and-licenses\" target=\"_blank\">Autorzy</a></i>,\n<i><a href=\"https://github.com/nrenner/brouter-web/blob/master/CHANGELOG.md\" target=\"_blank\">Histroia zmian</a></i> i\n<i><a href=\"https://github.com/nrenner/brouter-web#readme\" target=\"_blank\">więcej informacji</a></i> na temat klienta.",
|
||||
"support": "Ogólna dyskusja/pytania, wsparcie",
|
||||
"title": "Informacje"
|
||||
},
|
||||
"credits": {
|
||||
"brouter": "BRouter",
|
||||
"brouter-license": "<a target=\"_blank\" href=\"http://brouter.de/brouter\">BRouter</a> © Arndt Brenschede",
|
||||
"esri-license": "<a target=\"_blank\" href=\"http://goto.arcgisonline.com/maps/World_Imagery\">World Imagery</a> © <a target=\"_blank\" href=\"https://www.esri.com/\">Esri</a>, źródła: Esri, DigitalGlobe, Earthstar Geographics, CNES/Airbus DS, GeoEye, USDA FSA, USGS, Getmapping, Aerogrid, IGN, IGP oraz Społeczność Użytkowników GIS",
|
||||
"esri-tiles": "Obrazowanie świata Esri",
|
||||
"map-data": "Dane mapy",
|
||||
"map-tiles": "Kafelki mapy",
|
||||
"nominatim": "Wyszukaj przez <a href=\"https://wiki.openstreetmap.org/wiki/Nominatim\" target=\"_blank\" data-i18n=\"credits.nominatim\">Nominatim</a>",
|
||||
"openstreetmap": "© <a target=\"_blank\" href=\"https://www.openstreetmap.org/copyright\" >Współtwórcy OpenStreetMap</a> na licencji <a target=\"_blank\" href=\"https://opendatacommons.org/licenses/odbl/\" >ODbL</a>"
|
||||
},
|
||||
"export": {
|
||||
"format": "Format",
|
||||
"format_csv": "CSV",
|
||||
"format_geojson": "GeoJSON",
|
||||
"format_gpx": "GPX",
|
||||
"format_kml": "KML",
|
||||
"route-from-to": "{{from}} -> {{to}} ({{distance}}km)",
|
||||
"route-loop": "{{from}} ({{distance}}km)",
|
||||
"title": "Eksportuj trasę",
|
||||
"trackname": "Nazwa"
|
||||
},
|
||||
"footer": {
|
||||
"ascend": "Przewyższenie",
|
||||
"cost": "Koszt",
|
||||
"distance": "Odległość",
|
||||
"energy-per-100km": "Energia na 100 km",
|
||||
"hours": "godzin",
|
||||
"hours-abbrev": "godz.",
|
||||
"kilometer": "kilometrów",
|
||||
"kilometer-abbrev": "km",
|
||||
"kilowatthour": "kilowatogodziny",
|
||||
"kilowatthour-abbrev": "kWh",
|
||||
"mean-cost-factor": "Średni współczynnik kosztów",
|
||||
"meter": "metrów",
|
||||
"meter-abbrev": "m",
|
||||
"plain-ascend": "Różnica wysokości",
|
||||
"total-energy": "Całkowita energia",
|
||||
"travel-time": "Czas podróży"
|
||||
},
|
||||
"layers": {
|
||||
"add-base": "Dodaj warstwę bazową",
|
||||
"add-overlay": "Dodaj nakładkę",
|
||||
"customize": "Dostosuj warstwy",
|
||||
"placeholder-layer-name": "Własna nazwa warstwy. (np. OpenStreetMap)",
|
||||
"placeholder-layer-url": "URL niestandardowej warstwy. (np: https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png)",
|
||||
"remove-selection": "Usuń zaznaczenie"
|
||||
},
|
||||
"loadNogos": {
|
||||
"defaultProperties": "Domyślne właściwości",
|
||||
"file": "Plik:",
|
||||
"load": "Wczytaj",
|
||||
"nogoBuffer": "Bufor stref no-go (w metrach):",
|
||||
"nogoRadius": "Promień no-go (dla punktów):",
|
||||
"nogoWeight": "Waga no-go:",
|
||||
"source": "Źródło",
|
||||
"title": "Wczytaj strefy no-go",
|
||||
"url": "URL: "
|
||||
},
|
||||
"map": {
|
||||
"attribution-osm-long": "Współtwórcy OpenStreetMap",
|
||||
"attribution-osm-short": "OpenStreetMap",
|
||||
"clear-route": "Wyczyść trasę",
|
||||
"copyright": "Prawa autorskie",
|
||||
"cycling": "Kolarstwo",
|
||||
"delete-last-point": "Usuń ostatni punkt",
|
||||
"delete-nogo-areas": " usunie również wszystkie strefy no-go",
|
||||
"delete-route": "Usunąć trasę?",
|
||||
"draw-route-start": "Rysuj trasę (klawisz D)",
|
||||
"draw-route-stop": "Przestań rysować trasę (klawisz Esc)",
|
||||
"hikebike-hillshading": "Cieniowanie",
|
||||
"hiking": "Wspinaczka",
|
||||
"layer": {
|
||||
"bing": "Zdjęcia lotnicze Bing",
|
||||
"cycle": "OpenCycleMap (Thunderf.)",
|
||||
"cycling": "Jazda na rowerze (oznaczone szlaki)",
|
||||
"digitalglobe": "Najnowsze obrazowanie DigitalGlobe",
|
||||
"esri": "Obrazowanie świata Esri",
|
||||
"hikebike-hillshading": "Cieniowanie (Mapa wspinaczkowo-rowerowa)",
|
||||
"hiking": "Wspinaczka (oznaczone szlaki)",
|
||||
"osm": "OpenStreetMap",
|
||||
"osmde": "OpenStreetMap.de",
|
||||
"outdoors": "Na zewnątrz (Thunderforest)",
|
||||
"stamen-terrain": "Teren (Stamen)",
|
||||
"strava-segments": "Segmenty Strava",
|
||||
"topo": "OpenTopoMap"
|
||||
},
|
||||
"loading": "Wczytywanie…",
|
||||
"locate-me": "Pokaż mi gdzie jestem",
|
||||
"nogo": {
|
||||
"cancel": "Anuluj rysowanie strefy no-go",
|
||||
"click-drag": "Kliknij i przeciągnij, aby narysować okrąg",
|
||||
"draw": "Rysuj strefę no-go (okrąg)",
|
||||
"edit": "Kliknij, aby edytować",
|
||||
"help": "□ = przesuń / zmień rozmiar, <span class=\"fa fa-trash-o\"></span> = usuń,<br>kliknij okrąg, aby wyjść z edycji"
|
||||
},
|
||||
"opacity-slider": "Ustaw przezroczystość trasy i znaczników",
|
||||
"privacy": "Prywatność",
|
||||
"reverse-route": "Odwróć trasę",
|
||||
"strava-biking": "Pokaż rowerowe segmenty Strava ",
|
||||
"strava-running": "Pokaż biegowe segmenty Strava",
|
||||
"zoomInTitle": "Przybliż",
|
||||
"zoomOutTitle": "Oddal"
|
||||
},
|
||||
"modal": {
|
||||
"close": "Zamknij"
|
||||
},
|
||||
"navbar": {
|
||||
"about": "Informacje",
|
||||
"alternative": {
|
||||
"first": "Alternatywa nr 1",
|
||||
"original": "Pierwotna",
|
||||
"second": "Alternatywa nr 2",
|
||||
"third": "Alternatywa nr 3"
|
||||
},
|
||||
"export": "Eksportuj",
|
||||
"load": {
|
||||
"nogos": "Stefy no-go",
|
||||
"title": "Wczytaj"
|
||||
},
|
||||
"profile": {
|
||||
"car-eco": "Samochód (ekonomicznie)",
|
||||
"car-fast": "Samochód (szybko)",
|
||||
"car-test": "Samochód (testowo)",
|
||||
"custom": "Własne",
|
||||
"fastbike": "Rower szosowy",
|
||||
"fastbike-asia-pacific": "Rower szosowy (Azja Pacyfik)",
|
||||
"fastbike-lowtraffic": "Rower szosowy (mały ruch)",
|
||||
"hiking-beta": "Wspinaczka (beta)",
|
||||
"moped": "Motorower",
|
||||
"rail": "Kolej",
|
||||
"river": "Rzeka",
|
||||
"safety": "Bezpieczeństwo",
|
||||
"shortest": "Najkrótsza",
|
||||
"trekking": "Rower trekkingowy",
|
||||
"trekking-ignore-cr": "Rower trekkingowy (ignoruj trasy rowerowe)",
|
||||
"trekking-noferries": "Rower trekkingowy (bez promów)",
|
||||
"trekking-nosteps": "Rower trekkingowy (bez schodów)",
|
||||
"trekking-steep": "Rower trekkingowy (stromo)",
|
||||
"vm-forum-liegerad-schnell": "Rower poziomy (szosowy)",
|
||||
"vm-forum-velomobil-schnell": "Velomobile (szosowy)"
|
||||
}
|
||||
},
|
||||
"sidebar": {
|
||||
"custom-profile": {
|
||||
"title": "Własny profil"
|
||||
},
|
||||
"data": {
|
||||
"title": "Dane"
|
||||
},
|
||||
"itinerary": {
|
||||
"title": "Plan podróży"
|
||||
},
|
||||
"layers": {
|
||||
"category": {
|
||||
"base-layers": "Warstwy bazowe",
|
||||
"country": "Kraj",
|
||||
"europe": "Europa",
|
||||
"europe-monolingual": "Europa jeden język",
|
||||
"overlays": "Nakładki",
|
||||
"worldwide": "Cały świat",
|
||||
"worldwide-international": "Świat wielojęzyczny",
|
||||
"worldwide-monolingual": "Świat jeden język"
|
||||
},
|
||||
"collapse": "Zwiń wszystkie",
|
||||
"custom-layers": "Własne warstwy",
|
||||
"customize": "Dodaj lub usuń niestandardowe warstwy",
|
||||
"expand": "Rozwiń wszystkie",
|
||||
"optional": "Dodaj lub usuń opcjonalne warstwy",
|
||||
"optional-layers": "Więcej",
|
||||
"table": {
|
||||
"URL": "URL",
|
||||
"empty": "Nie skonfigurowano jeszcze niestandardowych warstw.",
|
||||
"name": "Nazwa",
|
||||
"type": "Rodzaj"
|
||||
},
|
||||
"title": "Warstwy"
|
||||
},
|
||||
"profile": {
|
||||
"clear": "Wyczyść",
|
||||
"help": "Pomoc",
|
||||
"placeholder": "Zapisz tutaj swój własny profil.",
|
||||
"upload": "Prześlij"
|
||||
}
|
||||
},
|
||||
"title": "Klient przeglądarkowy BRouter",
|
||||
"warning": {
|
||||
"cannot-get-route": "Błąd pobierania URL trasy",
|
||||
"no-response": "brak odpowiedzi z serwera",
|
||||
"no-route-found": "Błąd: nie można znaleźć trasy dla zadanych punktów. Spróbuj przesunąć je bliżej dróg.",
|
||||
"profile-error": "Błąd profilu: brak lub pusta odpowiedź z serwera",
|
||||
"strava-error": "Błąd pobierania segmentów Strava: {{error}}",
|
||||
"temporary-profile": "<strong>Uwaga:</strong> Przesłane własne profile są zapisywane na serwerze tylko tymczasowo.<br/>Zapisz zmiany na swoim komputerze.",
|
||||
"upload-error": "Błąd przesyłania: {{error}}"
|
||||
}
|
||||
}
|
||||
209
locales/pt.json
Normal file
209
locales/pt.json
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
{
|
||||
"about": {
|
||||
"bug-reports": "Relatórios de erros e pedidos de novas funcionalidades:",
|
||||
"bug-reports-back": "server / backend, routing engine, Android app, profiles, brouter.de site",
|
||||
"bug-reports-front": "web client / frontend.",
|
||||
"chat": "Chat with users and developers",
|
||||
"contact": "Contacto:",
|
||||
"data": "Dados:",
|
||||
"data-description": "This is based on <a href=\"https://www.openstreetmap.org\" target=\"_blank\">OpenStreetMap</a>. It is usually updated once a week when a new Planet file is available, see dates of <a href=\"http://brouter.de/brouter/segments4/\" target=\"_blank\">data files</a>.",
|
||||
"description": "Online service of the BRouter routing engine. For the offline Android app and more information see <a href=\"http://brouter.de/\" target=\"_blank\">brouter.de</a>",
|
||||
"details": "<i><a href=\"http://brouter.de/privacypolicy.html\" target=\"_blank\">Privacy Policy</a></i>, \n<i><a href=\"https://github.com/nrenner/brouter-web#credits-and-licenses\" target=\"_blank\">Credits</a></i>,\n<i><a href=\"https://github.com/nrenner/brouter-web/blob/master/CHANGELOG.md\" target=\"_blank\">Changelog</a></i> and\n<i><a href=\"https://github.com/nrenner/brouter-web#readme\" target=\"_blank\">more info</a></i> on the client.",
|
||||
"support": "General discussions/questions, support",
|
||||
"title": "Sobre"
|
||||
},
|
||||
"credits": {
|
||||
"brouter": "BRouter",
|
||||
"brouter-license": "<a target=\"_blank\" href=\"http://brouter.de/brouter\">BRouter</a> © Arndt Brenschede",
|
||||
"esri-license": "<a target=\"_blank\" href=\"http://goto.arcgisonline.com/maps/World_Imagery\">World Imagery</a> © <a target=\"_blank\" href=\"https://www.esri.com/\">Esri</a>, sources: Esri, DigitalGlobe, Earthstar Geographics, CNES/Airbus DS, GeoEye, USDA FSA, USGS, Getmapping, Aerogrid, IGN, IGP, and the GIS User Community",
|
||||
"esri-tiles": "Esri World Imagery",
|
||||
"map-data": "Dados do mapa",
|
||||
"map-tiles": "Map tiles",
|
||||
"nominatim": "Search by <a href=\"https://wiki.openstreetmap.org/wiki/Nominatim\" target=\"_blank\" data-i18n=\"credits.nominatim\">Nominatim</a>",
|
||||
"openstreetmap": "© <a target=\"_blank\" href=\"https://www.openstreetmap.org/copyright\" >OpenStreetMap contributors</a> under <a target=\"_blank\" href=\"https://opendatacommons.org/licenses/odbl/\" >ODbL</a>"
|
||||
},
|
||||
"export": {
|
||||
"format": "Format",
|
||||
"format_csv": "CSV",
|
||||
"format_geojson": "GeoJSON",
|
||||
"format_gpx": "GPX",
|
||||
"format_kml": "KML",
|
||||
"route-from-to": "{{from}} -> {{to}} ({{distance}}km)",
|
||||
"route-loop": "{{from}} ({{distance}}km)",
|
||||
"title": "Export route",
|
||||
"trackname": "Name"
|
||||
},
|
||||
"footer": {
|
||||
"ascend": "Ascend",
|
||||
"cost": "Cost",
|
||||
"distance": "Distance",
|
||||
"energy-per-100km": "Energy per 100 km",
|
||||
"hours": "hours",
|
||||
"hours-abbrev": "h",
|
||||
"kilometer": "kilometers",
|
||||
"kilometer-abbrev": "km",
|
||||
"kilowatthour": "kilowatt hours",
|
||||
"kilowatthour-abbrev": "kWh",
|
||||
"mean-cost-factor": "Mean cost factor",
|
||||
"meter": "meters",
|
||||
"meter-abbrev": "m",
|
||||
"plain-ascend": "Plain ascend",
|
||||
"total-energy": "Total Energy",
|
||||
"travel-time": "Travel time"
|
||||
},
|
||||
"layers": {
|
||||
"add-base": "Add base layer",
|
||||
"add-overlay": "Add overlay",
|
||||
"customize": "Customize layers",
|
||||
"placeholder-layer-name": "Custom layer name. (ex: OpenStreetMap)",
|
||||
"placeholder-layer-url": "Custom layer URL. (ex: https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png)",
|
||||
"remove-selection": "Remove selection"
|
||||
},
|
||||
"loadNogos": {
|
||||
"defaultProperties": "Default properties",
|
||||
"file": "File: ",
|
||||
"load": "Load",
|
||||
"nogoBuffer": "Buffer no-go areas (in meters): ",
|
||||
"nogoRadius": "No-go radius (for points): ",
|
||||
"nogoWeight": "No-go weight: ",
|
||||
"source": "Source",
|
||||
"title": "Load no-go areas",
|
||||
"url": "URL: "
|
||||
},
|
||||
"map": {
|
||||
"attribution-osm-long": "OpenStreetMap contributors",
|
||||
"attribution-osm-short": "OpenStreetMap",
|
||||
"clear-route": "Clear route",
|
||||
"copyright": "Copyright",
|
||||
"cycling": "Cycling",
|
||||
"delete-last-point": "Delete last point",
|
||||
"delete-nogo-areas": " also delete all no-go areas",
|
||||
"delete-route": "Delete route?",
|
||||
"draw-route-start": "Draw route (D key)",
|
||||
"draw-route-stop": "Stop drawing route (ESC key)",
|
||||
"hikebike-hillshading": "Hillshading",
|
||||
"hiking": "Hiking",
|
||||
"layer": {
|
||||
"bing": "Bing Aerial",
|
||||
"cycle": "OpenCycleMap (Thunderf.)",
|
||||
"cycling": "Cycling (Waymarked Trails)",
|
||||
"digitalglobe": "DigitalGlobe Recent Imagery",
|
||||
"esri": "Esri World Imagery",
|
||||
"hikebike-hillshading": "Hillshading (Hike & Bike Map)",
|
||||
"hiking": "Hiking (Waymarked Trails)",
|
||||
"osm": "OpenStreetMap",
|
||||
"osmde": "OpenStreetMap.de",
|
||||
"outdoors": "Outdoors (Thunderforest)",
|
||||
"stamen-terrain": "Terrain (Stamen)",
|
||||
"strava-segments": "Strava segments",
|
||||
"topo": "OpenTopoMap"
|
||||
},
|
||||
"loading": "Loading…",
|
||||
"locate-me": "Show me where I am",
|
||||
"nogo": {
|
||||
"cancel": "Cancel drawing no-go area",
|
||||
"click-drag": "Click and drag to draw circle",
|
||||
"draw": "Draw no-go area (circle)",
|
||||
"edit": "Click to edit",
|
||||
"help": "□ = move / resize, <span class=\"fa fa-trash-o\"></span> = delete,<br>click circle to quit editing"
|
||||
},
|
||||
"opacity-slider": "Set transparency of route track and markers",
|
||||
"privacy": "Privacy",
|
||||
"reverse-route": "Reverse route",
|
||||
"strava-biking": "Show Strava biking segments",
|
||||
"strava-running": "Show Strava running segments",
|
||||
"zoomInTitle": "Zoom in",
|
||||
"zoomOutTitle": "Zoom out"
|
||||
},
|
||||
"modal": {
|
||||
"close": "Close"
|
||||
},
|
||||
"navbar": {
|
||||
"about": "About",
|
||||
"alternative": {
|
||||
"first": "1st alternative",
|
||||
"original": "Original",
|
||||
"second": "2nd alternative",
|
||||
"third": "3rd alternative"
|
||||
},
|
||||
"export": "Export",
|
||||
"load": {
|
||||
"nogos": "No-go areas",
|
||||
"title": "Load"
|
||||
},
|
||||
"profile": {
|
||||
"car-eco": "Car (economic)",
|
||||
"car-fast": "Car (fast)",
|
||||
"car-test": "Car (test)",
|
||||
"custom": "Custom",
|
||||
"fastbike": "Fastbike",
|
||||
"fastbike-asia-pacific": "Fastbike (Asia Pacific)",
|
||||
"fastbike-lowtraffic": "Fastbike (low traffic)",
|
||||
"hiking-beta": "Hiking (beta)",
|
||||
"moped": "Moped",
|
||||
"rail": "Rail",
|
||||
"river": "River",
|
||||
"safety": "Safety",
|
||||
"shortest": "Shortest",
|
||||
"trekking": "Trekking bike",
|
||||
"trekking-ignore-cr": "Trekking bike (ignore cycle routes)",
|
||||
"trekking-noferries": "Trekking bike (no ferries)",
|
||||
"trekking-nosteps": "Trekking bike (no steps)",
|
||||
"trekking-steep": "Trekking bike (steep)",
|
||||
"vm-forum-liegerad-schnell": "Recumbent bike (fast)",
|
||||
"vm-forum-velomobil-schnell": "Velomobile (fast)"
|
||||
}
|
||||
},
|
||||
"sidebar": {
|
||||
"custom-profile": {
|
||||
"title": "Custom profile"
|
||||
},
|
||||
"data": {
|
||||
"title": "Data"
|
||||
},
|
||||
"itinerary": {
|
||||
"title": "Itinerary"
|
||||
},
|
||||
"layers": {
|
||||
"category": {
|
||||
"base-layers": "Base layers",
|
||||
"country": "Country",
|
||||
"europe": "Europe",
|
||||
"europe-monolingual": "Europe monolingual",
|
||||
"overlays": "Overlays",
|
||||
"worldwide": "Worldwide",
|
||||
"worldwide-international": "Worldwide international",
|
||||
"worldwide-monolingual": "Worldwide monolingual"
|
||||
},
|
||||
"collapse": "Collapse all",
|
||||
"custom-layers": "Custom layers",
|
||||
"customize": "Add or remove custom layers",
|
||||
"expand": "Expand all",
|
||||
"optional": "Add or remove optional layers",
|
||||
"optional-layers": "More",
|
||||
"table": {
|
||||
"URL": "URL",
|
||||
"empty": "No custom layer configured yet.",
|
||||
"name": "Name",
|
||||
"type": "Type"
|
||||
},
|
||||
"title": "Layers"
|
||||
},
|
||||
"profile": {
|
||||
"clear": "Clear",
|
||||
"help": "Help",
|
||||
"placeholder": "Write your custom profile here.",
|
||||
"upload": "Upload"
|
||||
}
|
||||
},
|
||||
"title": "BRouter web client",
|
||||
"warning": {
|
||||
"cannot-get-route": "Error getting route URL",
|
||||
"no-response": "no response from server",
|
||||
"no-route-found": "Error: cannot find a route for given points. Maybe try to move them closer to roads?",
|
||||
"profile-error": "Profile error: no or empty response from server",
|
||||
"strava-error": "Error getting Strava segments: {{error}}",
|
||||
"temporary-profile": "<strong>Note:</strong> Uploaded custom profiles are only cached temporarily on the server.<br/>Please save your edits to your local PC.",
|
||||
"upload-error": "Upload error: {{error}}"
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue