Work around iOS 3rd party browser download (#418)
- use FileReader.readAsDataURL (for iOS Chromium) - add alternative Download from Server for now until proven in Prod and fixed in iOS Firefox (no i18n) - replace cloud icons as client-side now
This commit is contained in:
parent
1d26949770
commit
0fc60c1821
5 changed files with 47 additions and 18 deletions
27
index.html
27
index.html
|
|
@ -64,7 +64,7 @@
|
||||||
data-i18n-options='{ "action": "$t(navbar.export-tooltip)", "key": "X" }'
|
data-i18n-options='{ "action": "$t(navbar.export-tooltip)", "key": "X" }'
|
||||||
title="Export route"
|
title="Export route"
|
||||||
>
|
>
|
||||||
<span class="fa fa-lg fa-cloud-download" aria-hidden="true"> </span>
|
<span class="fa fa-lg fa-download" aria-hidden="true"> </span>
|
||||||
<span data-i18n="navbar.export">Export</span>
|
<span data-i18n="navbar.export">Export</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -88,7 +88,7 @@
|
||||||
}'
|
}'
|
||||||
title="Load route"
|
title="Load route"
|
||||||
>
|
>
|
||||||
<span class="fa fa-lg fa-cloud-upload" aria-hidden="true"> </span>
|
<span class="fa fa-lg fa-upload" aria-hidden="true"> </span>
|
||||||
<span data-i18n="navbar.load.title">Load</span>
|
<span data-i18n="navbar.load.title">Load</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="dropdown-menu" aria-labelledby="navbarLoadDropdown">
|
<div class="dropdown-menu" aria-labelledby="navbarLoadDropdown">
|
||||||
|
|
@ -515,14 +515,20 @@
|
||||||
<button type="button" class="btn btn-secondary" data-i18n="modal.close" data-dismiss="modal">
|
<button type="button" class="btn btn-secondary" data-i18n="modal.close" data-dismiss="modal">
|
||||||
Close
|
Close
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button type="button" class="btn btn-secondary" id="serverExport">
|
||||||
type="submit"
|
<span>
|
||||||
class="btn btn-primary"
|
<i class="fa fa-cloud-download"></i>
|
||||||
data-i18n="export.title"
|
<i
|
||||||
form="exportForm"
|
hidden
|
||||||
id="submitExport"
|
id="export-beeline-warning"
|
||||||
>
|
class="fa fa-exclamation-triangle"
|
||||||
Export route
|
style="font-size: 10px; position: absolute; margin-top: -3px; margin-left: -1px"
|
||||||
|
></i>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
<button type="submit" class="btn btn-primary" form="exportForm" id="submitExport">
|
||||||
|
<span class="fa fa-download"></span>
|
||||||
|
<span data-i18n="export.title">Export route</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -919,7 +925,6 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="preview" hidden data-i18n="map.preview">Preview</div>
|
<div id="preview" hidden data-i18n="map.preview">Preview</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="sidebar" class="leaflet-sidebar collapsed">
|
<div id="sidebar" class="leaflet-sidebar collapsed">
|
||||||
<div class="leaflet-sidebar-content">
|
<div class="leaflet-sidebar-content">
|
||||||
<div class="leaflet-sidebar-pane" id="tab_layers_control">
|
<div class="leaflet-sidebar-pane" id="tab_layers_control">
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,10 @@
|
||||||
touchScreen: touchScreen,
|
touchScreen: touchScreen,
|
||||||
touchScreenDetectable: touchScreenDetectable,
|
touchScreenDetectable: touchScreenDetectable,
|
||||||
touch: touch,
|
touch: touch,
|
||||||
download: 'Blob' in window && 'createObjectURL' in URL && 'download' in document.createElement('a'),
|
download:
|
||||||
|
'Blob' in window &&
|
||||||
|
'FileReader' in window &&
|
||||||
|
'readAsDataURL' in FileReader.prototype &&
|
||||||
|
'download' in document.createElement('a'),
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,12 @@ BR.Export = L.Class.extend({
|
||||||
|
|
||||||
this.exportButton.on('click', L.bind(this._generateTrackname, this));
|
this.exportButton.on('click', L.bind(this._generateTrackname, this));
|
||||||
L.DomUtil.get('submitExport').onclick = L.bind(this._export, this);
|
L.DomUtil.get('submitExport').onclick = L.bind(this._export, this);
|
||||||
|
L.DomUtil.get('serverExport').onclick = L.bind(this._exportServer, this);
|
||||||
|
|
||||||
L.DomEvent.addListener(document, 'keydown', this._keydownListener, this);
|
L.DomEvent.addListener(document, 'keydown', this._keydownListener, this);
|
||||||
|
|
||||||
|
$('#export').on('show.bs.modal', this._warnStraightLine.bind(this));
|
||||||
|
|
||||||
this.update([]);
|
this.update([]);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -44,6 +47,16 @@ BR.Export = L.Class.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_warnStraightLine: function () {
|
||||||
|
const hasBeeline = BR.Routing.hasBeeline(this.segments);
|
||||||
|
document.getElementById('export-beeline-warning').hidden = !hasBeeline;
|
||||||
|
let title = 'Download from server (deprecated)';
|
||||||
|
if (hasBeeline) {
|
||||||
|
title = '[Warning: straight lines not supported] ' + title;
|
||||||
|
}
|
||||||
|
document.getElementById('serverExport').title = title;
|
||||||
|
},
|
||||||
|
|
||||||
_getMimeType: function (format) {
|
_getMimeType: function (format) {
|
||||||
const mimeTypeMap = {
|
const mimeTypeMap = {
|
||||||
gpx: 'application/gpx+xml',
|
gpx: 'application/gpx+xml',
|
||||||
|
|
@ -64,7 +77,11 @@ BR.Export = L.Class.extend({
|
||||||
link.click();
|
link.click();
|
||||||
},
|
},
|
||||||
|
|
||||||
_export: function (e) {
|
_exportServer: function (e) {
|
||||||
|
this._export(e, true);
|
||||||
|
},
|
||||||
|
|
||||||
|
_export: function (e, server = false) {
|
||||||
var exportForm = document.forms['export'];
|
var exportForm = document.forms['export'];
|
||||||
var format = exportForm['format'].value || $('#export-format input:radio:checked').val();
|
var format = exportForm['format'].value || $('#export-format input:radio:checked').val();
|
||||||
var name = exportForm['trackname'].value;
|
var name = exportForm['trackname'].value;
|
||||||
|
|
@ -73,7 +90,7 @@ BR.Export = L.Class.extend({
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (BR.Browser.download) {
|
if (!server && BR.Browser.download) {
|
||||||
const track = this._formatTrack(format, name, includeWaypoints);
|
const track = this._formatTrack(format, name, includeWaypoints);
|
||||||
const fileName = (name || 'brouter') + '.' + format;
|
const fileName = (name || 'brouter') + '.' + format;
|
||||||
|
|
||||||
|
|
@ -81,9 +98,10 @@ BR.Export = L.Class.extend({
|
||||||
const blob = new Blob([track], {
|
const blob = new Blob([track], {
|
||||||
type: mimeType + ';charset=utf-8',
|
type: mimeType + ';charset=utf-8',
|
||||||
});
|
});
|
||||||
const objectUrl = URL.createObjectURL(blob);
|
|
||||||
|
|
||||||
this._triggerDownload(objectUrl, fileName);
|
const reader = new FileReader();
|
||||||
|
reader.onload = (e) => this._triggerDownload(reader.result, fileName);
|
||||||
|
reader.readAsDataURL(blob);
|
||||||
} else {
|
} else {
|
||||||
var serverUrl = this.router.getUrl(
|
var serverUrl = this.router.getUrl(
|
||||||
this.latLngs,
|
this.latLngs,
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,7 @@ BR.TrackStats = L.Class.extend({
|
||||||
$('#stats-container').show();
|
$('#stats-container').show();
|
||||||
$('#stats-info').hide();
|
$('#stats-info').hide();
|
||||||
|
|
||||||
const hasBeeline = segments.filter((line) => line?._routing?.beeline).length > 0;
|
document.getElementById('beeline-warning').hidden = !BR.Routing.hasBeeline(segments);
|
||||||
document.getElementById('beeline-warning').hidden = !hasBeeline;
|
|
||||||
|
|
||||||
var stats = this.calcStats(polyline, segments),
|
var stats = this.calcStats(polyline, segments),
|
||||||
length1 = L.Util.formatNum(stats.trackLength / 1000, 1).toLocaleString(),
|
length1 = L.Util.formatNum(stats.trackLength / 1000, 1).toLocaleString(),
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,9 @@ L.Routing.Draw.prototype._hideTrailer = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
BR.Routing = L.Routing.extend({
|
BR.Routing = L.Routing.extend({
|
||||||
|
statics: {
|
||||||
|
hasBeeline: (segments) => segments?.filter((line) => line?._routing?.beeline).length > 0,
|
||||||
|
},
|
||||||
options: {
|
options: {
|
||||||
position: 'topright',
|
position: 'topright',
|
||||||
icons: {
|
icons: {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue