Let user upload Nogos through GeoJSON file.
This commit is contained in:
parent
1f81c043ad
commit
e7db4a7aae
5 changed files with 1518 additions and 19 deletions
|
|
@ -20,7 +20,7 @@ body, #content {
|
||||||
.dataTables_scroll,
|
.dataTables_scroll,
|
||||||
.dataTables_scrollBody {
|
.dataTables_scrollBody {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,7 +61,7 @@ table.dataTable {
|
||||||
.navbar {
|
.navbar {
|
||||||
/* align with leaflet-control */
|
/* align with leaflet-control */
|
||||||
padding: .5rem 10px;
|
padding: .5rem 10px;
|
||||||
}
|
}
|
||||||
.navbar-brand {
|
.navbar-brand {
|
||||||
float: right;
|
float: right;
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
|
|
@ -278,7 +278,7 @@ https://css-tricks.com/svg-line-animation-works/
|
||||||
}
|
}
|
||||||
.leaflet-bar .fa {
|
.leaflet-bar .fa {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
||||||
/* override fa with Leaflet button height for vertical center */
|
/* override fa with Leaflet button height for vertical center */
|
||||||
line-height: 26px;
|
line-height: 26px;
|
||||||
}
|
}
|
||||||
|
|
@ -340,7 +340,7 @@ 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
|
* No-go areas
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -384,7 +384,7 @@ table.dataTable.display tbody tr.even:hover {
|
||||||
.leaflet-sidebar-pane#tab_profile,
|
.leaflet-sidebar-pane#tab_profile,
|
||||||
.leaflet-sidebar-pane#tab_data,
|
.leaflet-sidebar-pane#tab_data,
|
||||||
.leaflet-sidebar-pane#tab_itinerary {
|
.leaflet-sidebar-pane#tab_itinerary {
|
||||||
/* Full height for content with inner scrolling,
|
/* Full height for content with inner scrolling,
|
||||||
overrides scroll fix for long content in Firefox */
|
overrides scroll fix for long content in Firefox */
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
@ -425,9 +425,27 @@ table.dataTable.display tbody tr.even:hover {
|
||||||
flex: auto;
|
flex: auto;
|
||||||
/* override default 300px, behaves like min-height with flex auto */
|
/* override default 300px, behaves like min-height with flex auto */
|
||||||
height: 0;
|
height: 0;
|
||||||
|
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
|
|
||||||
font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
|
font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
|
||||||
line-height: 1.2em;
|
line-height: 1.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#uploadNogos 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#uploadNogos legend {
|
||||||
|
display: block;
|
||||||
|
padding-left: 2px;
|
||||||
|
padding-right: 2px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
|
||||||
69
index.html
69
index.html
|
|
@ -49,6 +49,16 @@
|
||||||
<a class="dropdown-item" data-i18n="navbar.download.csv" id="dl-csv" href="#" disabled>data CSV</a>
|
<a class="dropdown-item" data-i18n="navbar.download.csv" id="dl-csv" href="#" disabled>data CSV</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="nav-item dropdown">
|
||||||
|
<a class="nav-link dropdown-toggle" href="" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">
|
||||||
|
<span class="fa fa-lg fa-cloud-upload" aria-hidden="true">
|
||||||
|
</span>
|
||||||
|
<span data-i18n="navbar.load.title">Load</span>
|
||||||
|
</a>
|
||||||
|
<div class="dropdown-menu">
|
||||||
|
<a class="dropdown-item" data-i18n="navbar.load.nogos" data-toggle="modal" data-target="#loadNogos" href="#">Nogos</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="nav-item">
|
<div class="nav-item">
|
||||||
<a class="nav-link" href="#" data-toggle="modal" data-target="#about"><span class="fa fa-lg fa-info-circle" aria-hidden="true"></span><span data-i18n="navbar.about">About</span></a>
|
<a class="nav-link" href="#" data-toggle="modal" data-target="#about"><span class="fa fa-lg fa-info-circle" aria-hidden="true"></span><span data-i18n="navbar.about">About</span></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -78,7 +88,7 @@
|
||||||
</dd>
|
</dd>
|
||||||
<dt data-i18n="credits.osm-tiles">OpenStreetMap tiles</dt>
|
<dt data-i18n="credits.osm-tiles">OpenStreetMap tiles</dt>
|
||||||
<dd data-i18n="[html]credits.osm-license">
|
<dd data-i18n="[html]credits.osm-license">
|
||||||
<a target="_blank" href="https://www.openstreetmap.org/copyright">openstreetmap.org</a>
|
<a target="_blank" href="https://www.openstreetmap.org/copyright">openstreetmap.org</a>
|
||||||
under <a target="_blank" href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA 2.0</a>
|
under <a target="_blank" href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA 2.0</a>
|
||||||
</dd>
|
</dd>
|
||||||
<dt data-i18n="credits.osmde-tiles">OpenStreetMap.de tiles</dt>
|
<dt data-i18n="credits.osmde-tiles">OpenStreetMap.de tiles</dt>
|
||||||
|
|
@ -98,8 +108,8 @@
|
||||||
</dd>
|
</dd>
|
||||||
<dt data-i18n="credits.esri-tiles">Esri World Imagery</dt>
|
<dt data-i18n="credits.esri-tiles">Esri World Imagery</dt>
|
||||||
<dd data-i18n="[html]credits.esri-license">
|
<dd data-i18n="[html]credits.esri-license">
|
||||||
<a target="_blank" href="http://goto.arcgisonline.com/maps/World_Imagery">World Imagery</a>
|
<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:
|
© <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, DigitalGlobe, Earthstar Geographics, CNES/Airbus DS, GeoEye, USDA FSA, USGS, Getmapping, Aerogrid, IGN, IGP, and the GIS User Community
|
||||||
</dd>
|
</dd>
|
||||||
<dt data-i18n="credits.cycling-hiking-tiles">Cycling & Hiking tiles</dt>
|
<dt data-i18n="credits.cycling-hiking-tiles">Cycling & Hiking tiles</dt>
|
||||||
|
|
@ -181,7 +191,7 @@
|
||||||
</div>
|
</div>
|
||||||
</p>
|
</p>
|
||||||
<p data-i18n="[html]about.details">
|
<p data-i18n="[html]about.details">
|
||||||
<i><a href="http://brouter.de/privacypolicy.html" target="_blank">Privacy Policy</a></i>,
|
<i><a href="http://brouter.de/privacypolicy.html" target="_blank">Privacy Policy</a></i>,
|
||||||
<i><a href="https://github.com/nrenner/brouter-web#credits-and-licenses" target="_blank">Credits</a></i>,
|
<i><a href="https://github.com/nrenner/brouter-web#credits-and-licenses" target="_blank">Credits</a></i>,
|
||||||
<i><a href="https://github.com/nrenner/brouter-web/blob/master/CHANGELOG.md" target="_blank">Changelog</a></i> and
|
<i><a href="https://github.com/nrenner/brouter-web/blob/master/CHANGELOG.md" target="_blank">Changelog</a></i> and
|
||||||
<i><a href="https://github.com/nrenner/brouter-web#readme" target="_blank">more info</a></i> on the client.
|
<i><a href="https://github.com/nrenner/brouter-web#readme" target="_blank">more info</a></i> on the client.
|
||||||
|
|
@ -191,6 +201,53 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Load nogos modal window -->
|
||||||
|
<div class="modal fade" id="loadNogos" tabindex="-1" role="dialog" aria-labelledby="Load nogos window" aria-hidden="true">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
<h4 class="modal-title" data-i18n="loadNogos.title">Load nogos</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p id="nogoError" style="display: none;"></p>
|
||||||
|
<form>
|
||||||
|
<fieldset>
|
||||||
|
<legend data-i18n="loadNogos.source">Source</legend>
|
||||||
|
<p>
|
||||||
|
<label for="nogoURL" data-i18n="loadNogos.url">URL: </label>
|
||||||
|
<input type="text" name="nogoURL" id="nogoURL" /><br/>
|
||||||
|
or<br/>
|
||||||
|
<label for="nogoFile" data-i18n="loadNogos.file">File: </label>
|
||||||
|
<input type="file" name="nogoFile" id="nogoFile" />
|
||||||
|
</p>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend data-i18n="loadNogos.defaultProperties">Default properties</legend>
|
||||||
|
<p>
|
||||||
|
<label for="nogoWeight" data-i18n="loadNogos.nogoWeight">Nogo weight: </label>
|
||||||
|
<input type="number" name="nogoWeight" id="nogoWeight" value="-1" />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label for="nogoRadius" data-i18n="loadNogos.nogoRadius">Nogo radius (for points): </label>
|
||||||
|
<input type="number" name="nogoRadius" id="nogoRadius" value="20" />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label for="nogoBuffer" data-i18n="loadNogos.nogoBuffer">Buffer nogos areas (in meters): </label>
|
||||||
|
<input type="number" name="nogoBuffer" id="nogoBuffer" value="0" />
|
||||||
|
</p>
|
||||||
|
</fieldset>
|
||||||
|
<p style="margin-top: 1em; text-align: center;">
|
||||||
|
<input type="submit" data-i18n="[value]loadNogos.load" value="Load" id="submitNogos" />
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="content" class="flexcolumn flexgrow">
|
<div id="content" class="flexcolumn flexgrow">
|
||||||
<div id="sidebarTabs" class="leaflet-sidebar-tabs collapsed">
|
<div id="sidebarTabs" class="leaflet-sidebar-tabs collapsed">
|
||||||
<ul role="tablist">
|
<ul role="tablist">
|
||||||
|
|
@ -208,10 +265,10 @@
|
||||||
</a></li>
|
</a></li>
|
||||||
<li hidden><a href="#tab_itinerary" role="tab" data-i18n="[title]sidebar.itinerary.title" title="Itinerary"><i class="fa fa-map-signs"></i></a></li>
|
<li hidden><a href="#tab_itinerary" role="tab" data-i18n="[title]sidebar.itinerary.title" title="Itinerary"><i class="fa fa-map-signs"></i></a></li>
|
||||||
<li><a href="#tab_profile" role="tab" data-i18n="[title]sidebar.custom-profile.title" title="Custom profile"><i class="fa fa-wrench"></i></a></li>
|
<li><a href="#tab_profile" role="tab" data-i18n="[title]sidebar.custom-profile.title" title="Custom profile"><i class="fa fa-wrench"></i></a></li>
|
||||||
<li><a href="#tab_data" role="tab" data-i18n="[title]sidebar.data.title" title="Data"><i class="fa fa-table"></i></a></li>
|
<li><a href="#tab_data" role="tab" data-i18n="[title]sidebar.data.title" title="Data"><i class="fa fa-table"></i></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="leaflet-sidebar-flex-row flexgrow">
|
<div class="leaflet-sidebar-flex-row flexgrow">
|
||||||
<div id="map" class="leaflet-sidebar-map">
|
<div id="map" class="leaflet-sidebar-map">
|
||||||
<div id="message"></div>
|
<div id="message"></div>
|
||||||
|
|
|
||||||
96
js/index.js
96
js/index.js
|
|
@ -356,6 +356,102 @@
|
||||||
$(this).collapse('show');
|
$(this).collapse('show');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#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) {
|
||||||
|
if (!feature.properties.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
|
i18next
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
"browserslist": "> 0.5%, last 2 versions, Firefox ESR, not dead, Explorer >= 10, Android >= 4.1, Safari >= 7, iOS >= 7",
|
"browserslist": "> 0.5%, last 2 versions, Firefox ESR, not dead, Explorer >= 10, Android >= 4.1, Safari >= 7, iOS >= 7",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mapbox/polyline": "^0.2.0",
|
"@mapbox/polyline": "^0.2.0",
|
||||||
|
"@turf/turf": "^5.1.6",
|
||||||
"async": "~0.9.2",
|
"async": "~0.9.2",
|
||||||
"bootbox": "~4.4.0",
|
"bootbox": "~4.4.0",
|
||||||
"bootstrap": "4.0.0-alpha.5",
|
"bootstrap": "4.0.0-alpha.5",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue