diff --git a/.gitignore b/.gitignore index d66347e..552abf8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -bower_components/ node_modules/ nbproject/ .idea/ @@ -7,3 +6,4 @@ nbproject/ /keys.js /dist brouter-web.*.zip +yarn-error.log diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..dda0423 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,10 @@ +LICENSE +dist/ +*.zip +yarn.lock +.idea +.gitignore +.prettierignore +.tx/ +layers/ +locales/*.json diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..cd93fd9 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "tabWidth": 4 +} diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..e52163c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - lts/* +cache: yarn diff --git a/.tx/config b/.tx/config new file mode 100644 index 0000000..28c21f4 --- /dev/null +++ b/.tx/config @@ -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/.json +source_file = locales/en.json +source_lang = en +type = JSON diff --git a/CHANGELOG.md b/CHANGELOG.md index 037ff1a..40877d6 100644 --- a/CHANGELOG.md +++ b/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), - also fix max zoom of other services -* overscale tiles to common max zoom (avoids gray screen when switching) +- 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) ## 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 - 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 +- 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 ### 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) diff --git a/LICENSE b/LICENSE index 689128d..b649eb9 100644 --- a/LICENSE +++ b/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 diff --git a/README.md b/README.md index a7cfe8d..693b480 100644 --- a/README.md +++ b/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 -General BRouter discussions/questions, support: -https://groups.google.com/group/osm-android-bikerouting +## Contact + +General BRouter discussions/questions, support: + +- [`#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 @@ -24,116 +35,148 @@ 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): +1. download and unzip latest [BRouter revision](http://brouter.de/brouter/revisions.html) + 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 - chmod +x ./standalone/server.sh + mkdir ~/opt/brouter + cd ~/opt/brouter + 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 - https://github.com/nrenner/brouter-web/releases: +1. download BRouter-Web as subdirectory `brouter-web` of the `brouter` directory - 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 + - using the latest stable release - adjust to current version number - from + https://github.com/nrenner/brouter-web/releases: - * OR the current development state (potentially instable and without runtime distributables): + 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 - wget https://github.com/nrenner/brouter-web/archive/master.zip - unzip master.zip - mv brouter-web-master brouter-web + - OR the current development state (potentially instable and without runtime distributables): - * build the distributable files required for runtime (only for development state), see section [Build](#build) + wget https://github.com/nrenner/brouter-web/archive/master.zip + unzip master.zip + mv brouter-web-master brouter-web -2. copy ``config.template.js`` to ``config.js`` -3. configure URL to ``profiles2`` directory -set ``BR.conf.profilesUrl`` in config.js, e.g. uncomment: + - build the distributable files required for runtime (only for development state), see section [Build](#build) - BR.conf.profilesUrl = 'http://localhost:8000/profiles2/'; +2. copy `config.template.js` to `config.js` +3. configure URL to `profiles2` directory + set `BR.conf.profilesUrl` in config.js, e.g. uncomment: -4. add your API keys (optional) -copy ``keys.template.js`` to ``keys.js`` and edit to add your keys + 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 ### 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 + 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 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) diff --git a/bower.json b/bower.json deleted file mode 100644 index 466c829..0000000 --- a/bower.json +++ /dev/null @@ -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" - } -} diff --git a/config.template.js b/config.template.js index 0b090c5..bedbc30 100644 --- a/config.template.js +++ b/config.template.js @@ -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 \\._\\-'; })(); diff --git a/css/leaflet-routing.css b/css/leaflet-routing.css index 6e098e4..540c852 100644 --- a/css/leaflet-routing.css +++ b/css/leaflet-routing.css @@ -1,5 +1,5 @@ div.line-mouse-marker { - background-color: white; - border: 4px solid magenta; - border-radius: 8px; + background-color: white; + border: 4px solid magenta; + border-radius: 8px; } diff --git a/css/style.css b/css/style.css index 7c6b033..dd96a07 100644 --- a/css/style.css +++ b/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; } diff --git a/gulpfile.js b/gulpfile.js index 1db27e4..9d853e6 100644 --- a/gulpfile.js +++ b/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,219 +19,376 @@ 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([ - 'js/Browser.js', - 'js/Util.js', - 'js/Map.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/*'), - dest: 'dist', - destName: 'brouter-web' + // 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: 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() { - // just copy for now - return gulp.src(paths.scriptsConfig) - .pipe(gulp.dest(paths.dest)); +gulp.task('scripts_config', function() { + // just copy for now + 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: '.' }) - .pipe(sourcemaps.init()) - .pipe(cached('scripts')) - .pipe(gulpif(!debug, uglify())) - .pipe(remember('scripts')) - .pipe(concat(paths.destName + '.js')) - .pipe(sourcemaps.write('.')) - .pipe(gulp.dest(paths.dest)); + return gulp + .src(paths.scripts, { base: '.' }) + .pipe(sourcemaps.init()) + .pipe(cached('scripts')) + .pipe(gulpif(!debug, uglify())) + .pipe(remember('scripts')) + .pipe(concat(paths.destName + '.js')) + .pipe(sourcemaps.write('.')) + .pipe(gulp.dest(paths.dest)); }); // separate, fallback task for debugging (switch manually in index.html) gulp.task('concat', function() { - return gulp.src(paths.scripts) - .pipe(concat(paths.destName + '.src.js')) - .pipe(gulp.dest(paths.dest)); + 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 = '.'; - } - })) - .pipe(concatCss(paths.destName + '.css')) - .pipe(minifyCss({ - rebase: false - })) - .pipe(gulp.dest(paths.dest)); + 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); + } + + 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) { - if (event.type === 'deleted') { - delete cached.caches.scripts[event.path]; - remember.forget('scripts', event.path); - } - }); - gulp.watch(paths.styles, ['styles']); + debug = true; + 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, 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.styles) - //return gulp.src(paths.images) - .pipe(gulpDebug()); - - //return gulp.src(mainBowerFiles({debugging: true})); + //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()); }); -gulp.task('inject', function () { - var target = gulp.src('index.html'); - var sources = gulp.src(paths.scripts, { base: '.', read: false }); +gulp.task('inject', function() { + var target = gulp.src('index.html'); + var sources = gulp.src(paths.scripts.concat(paths.styles), { + base: '.', + read: false + }); - 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'); + return target + .pipe(inject(sources, { relative: true })) + .pipe(gulp.dest('.')); }); 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() { - var tag = gutil.env.tag; - if (!tag) { - gutil.log(gutil.colors.red('--tag is required')); - process.exit(1); - } - if (['major', 'minor', 'patch'].indexOf(tag) < 0) { - gutil.log(gutil.colors.red('--tag must be major, minor or patch')); - process.exit(2); - } - ghToken = gutil.env.token; - if (!ghToken) { - gutil.log(gutil.colors.red('--token is required (github personnal access token)')); - process.exit(3); - } - if (ghToken.length != 40) { - gutil.log(gutil.colors.red('--token length must be 40')); - process.exit(4); - } - 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); +gulp.task('release:init', function(cb) { + var tag = gutil.env.tag; + if (!tag) { + return cb(new Error('--tag is required')); } - }); - nextVersion = semver.inc(pkg.version, tag); - return; + if (['major', 'minor', 'patch'].indexOf(tag) < 0) { + return cb(new Error('--tag must be major, minor or patch')); + } + ghToken = gutil.env.token; + if (!ghToken) { + return cb( + new Error('--token is required (github personnal access token') + ); + } + if (ghToken.length != 40) { + return cb(new Error('--token length must be 40')); + } + + nextVersion = semver.inc(pkg.version, tag); + + 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' + ) + ); + } + + cb(); + }); }); -gulp.task('bump', ['bump:json', 'bump:html']); - -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:json', function() { + gutil.log(gutil.colors.green('Bump to ' + nextVersion)); + return gulp + .src(['./package.json']) + .pipe(bump({ version: nextVersion })) + .pipe(gulp.dest('./')); }); -gulp.task('bump:html', ['release:init'], function() { - return(gulp.src('./index.html') - .pipe(replace(/(.*)<\/sup>/, ''+nextVersion+'')) - .pipe(gulp.dest('.'))); +gulp.task('bump:html', function() { + return gulp + .src('./index.html') + .pipe( + replace( + /(.*)<\/sup>/, + '' + nextVersion + '' + ) + ) + .pipe(gulp.dest('.')); }); -gulp.task('release:commit', ['bump'], function() { - gulp.src(['./index.html', './package.json', './bower.json']) - .pipe(git.commit('release: '+nextVersion)); +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', ['release:commit'], function() { - return(git.tag(nextVersion, '', function(err) { - if (err) throw err; - })); +gulp.task('release:tag', function(cb) { + return git.tag(nextVersion, '', cb); }); -gulp.task('release:push', ['release:tag'], function() { - git.push('origin', 'master', {args: '--tags'}, function(err) { - if (err) throw err; - }); +gulp.task('release:push', function(cb) { + git.push('origin', 'master', { args: '--tags' }, 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('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('release:publish', ['release:zip'], function() { - gulp.src('./brouter-web.'+nextVersion+'.zip') - .pipe(release({ - tag: nextVersion, - token: ghToken, - manifeste: pkg, - })) +gulp.task('layers_config', function() { + return gulp + .src(paths.layersConfig) + .pipe(concat(paths.layersConfigDestName)) + .pipe(gulp.dest(paths.dest)); }); -gulp.task('release', ['release:init', 'bump', 'release:commit', 'release:tag', - 'release:push', 'release:zip', 'release:publish']); \ No newline at end of file +// 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, + manifest: pkg + }) + ); +}); + +gulp.task( + 'release', + gulp.series( + 'release:init', + 'bump', + 'release:commit', + 'release:tag', + 'release:push', + 'default', + 'release:zip', + 'release:publish' + ) +); diff --git a/index.html b/index.html index 4366844..2539e3e 100644 --- a/index.html +++ b/index.html @@ -1,247 +1,1115 @@ - - - - + + + + - BRouter web client + BRouter web client - - - - + + +