(function($, OC) {
$(function() {
if (window.isSecureContext) {
window.navigator.registerProtocolHandler('geo', OC.generateUrl('/apps/maps/openGeoLink/') + '%s', 'Nextcloud Maps');
}
mapController.initMap();
mapController.map.favoritesController = favoritesController;
favoritesController.initFavorites(mapController.map);
photosController.initLayer(mapController.map);
nonLocalizedPhotosController.initLayer(mapController.map);
mapController.map.photosController = photosController;
contactsController.initLayer(mapController.map);
mapController.map.contactsController = contactsController;
tracksController.initController(mapController.map);
tracksController.map.tracksController = tracksController;
devicesController.initController(mapController.map);
mapController.map.devicesController = devicesController;
searchController.initController(mapController.map);
// once controllers have been set/initialized, we can restore option values from server
optionsController.restoreOptions();
geoLinkController.showLinkLocation();
// Popup
$(document).on('click', '#opening-hours-header', function() {
$('#opening-hours-table').toggle();
$('#opening-hours-table-toggle-expand').toggle();
$('#opening-hours-table-toggle-collapse').toggle();
});
document.onkeydown = function (e) {
e = e || window.event;
if (e.key === 'Escape') {
if (favoritesController.movingFavoriteId !== null) {
favoritesController.leaveMoveFavoriteMode();
}
if (contactsController.movingBookid !== null) {
contactsController.leaveMoveContactMode();
}
if (photosController.movingPhotoPath !== null) {
photosController.leaveMovePhotoMode();
}
}
};
window.onclick = function(event) {
if (event.button === 0) {
$('.leaflet-control-layers').hide();
$('.easy-button-container').show();
if (!event.target.matches('.app-navigation-entry-utils-menu-button button')) {
$('.app-navigation-entry-menu.open').removeClass('open');
}
mapController.map.contextmenu.hide();
}
};
$('#display-slider').click(function(e) {
optionsController.saveOptionValues({displaySlider: $(this).is(':checked')});
if ($(this).is(':checked')) {
$('#timeRangeSlider').show();
}
else {
$('#timeRangeSlider').hide();
}
});
// click on menu buttons
$('body').on('click',
'.routingMenuButton, .favoritesMenuButton, .categoryMenuButton, .photosMenuButton, .contactsMenuButton, ' +
'.nonLocalizedPhotosMenuButton, .devicesMenuButton, .deviceMenuButton, .tracksMenuButton, .trackMenuButton',
function(e) {
var menu = $(this).parent().parent().parent().find('> .app-navigation-entry-menu');
var wasOpen = menu.hasClass('open');
$('.app-navigation-entry-menu.open').removeClass('open');
if (!wasOpen) {
menu.addClass('open');
}
});
// right click on entry line
$('body').on('contextmenu',
'#navigation-routing > .app-navigation-entry-utils, #navigation-routing > a, ' +
'#navigation-favorites > .app-navigation-entry-utils, #navigation-favorites > a, ' +
'.category-line > a, .category-line > .app-navigation-entry-utils, ' +
'#navigation-devices > .app-navigation-entry-utils, #navigation-devices > a, ' +
'.device-line > a, .device-line > .app-navigation-entry-utils, ' +
'#navigation-tracks > .app-navigation-entry-utils, #navigation-tracks > a, ' +
'.track-line > a, .track-line > .app-navigation-entry-utils, ' +
'#navigation-nonLocalizedPhotos > .app-navigation-entry-utils, #navigation-nonLocalizedPhotos > a, ' +
'#navigation-contacts > .app-navigation-entry-utils, #navigation-contacts > a, ' +
'#navigation-photos > .app-navigation-entry-utils, #navigation-photos > a ',
function(e) {
var menu = $(this).parent().find('> .app-navigation-entry-menu');
var wasOpen = menu.hasClass('open');
$('.app-navigation-entry-menu.open').removeClass('open');
if (!wasOpen) {
menu.addClass('open');
}
return false;
});
// right click on expand icon
$('body').on('contextmenu', '#navigation-favorites, #navigation-photos, #navigation-devices, #navigation-tracks', function(e) {
var id = $(e.target).attr('id');
if (e.target.tagName === 'LI' && (id === 'navigation-favorites' || id === 'navigation-photos' || id === 'navigation-devices' || id === 'navigation-tracks')) {
var menu = $(this).find('> .app-navigation-entry-menu');
var wasOpen = menu.hasClass('open');
$('.app-navigation-entry-menu.open').removeClass('open');
if (!wasOpen) {
menu.addClass('open');
}
return false;
}
});
});
var geoLinkController = {
marker: null,
lat: null,
lng: null,
showLinkLocation: function() {
var geourlElem = document.getElementById('geourl');
if (geourlElem) {
var geourl = geourlElem.value;
[this.lat, this.lng] = geourl.substring(4).split(',');
this.marker = L.marker([this.lat, this.lng]);
mapController.map.addLayer(this.marker);
mapController.map.setView([this.lat, this.lng], 15);
}
},
shareLocation: function(e) {
var lat = e.latlng.lat;
var lng = e.latlng.lng;
var geoLink = 'geo:' + lat.toFixed(6) + ',' + lng.toFixed(6);
var dummy = $('').val(geoLink).appendTo('body').select();
document.execCommand('copy');
$('#dummycopy').remove();
OC.Notification.showTemporary(t('maps', 'Geo link ({geoLink}) copied to clipboard', {geoLink: geoLink}));
},
};
var optionsController = {
optionValues: {},
enabledFavoriteCategories: [],
enabledTracks: [],
enabledDevices: [],
enabledDeviceLines: [],
saveOptionValues: function (optionValues) {
var req = {
options: optionValues
};
var url = OC.generateUrl('/apps/maps/saveOptionValue');
$.ajax({
type: 'POST',
url: url,
data: req,
async: true
}).done(function (response) {
}).fail(function() {
OC.Notification.showTemporary(
t('maps', 'Failed to save option values')
);
});
},
restoreOptions: function () {
var that = this;
var url = OC.generateUrl('/apps/maps/getOptionsValues');
var req = {};
var optionsValues = {};
$.ajax({
type: 'POST',
url: url,
data: req,
async: true
}).done(function (response) {
optionsValues = response.values;
// set tilelayer before showing photo layer because it needs a max zoom value
if (optionsValues.hasOwnProperty('displaySlider') && optionsValues.displaySlider === 'true') {
$('#timeRangeSlider').show();
$('#display-slider').prop('checked', true);
}
if (optionsValues.hasOwnProperty('tileLayer')) {
mapController.changeTileLayer(optionsValues.tileLayer);
}
else {
mapController.changeTileLayer('OpenStreetMap');
}
if (optionsValues.hasOwnProperty('mapBounds')) {
var nsew = optionsValues.mapBounds.split(';');
if (nsew.length === 4) {
var n = parseFloat(nsew[0]);
var s = parseFloat(nsew[1]);
var e = parseFloat(nsew[2]);
var w = parseFloat(nsew[3]);
if (n && s && e && w) {
mapController.map.fitBounds([
[n, e],
[s, w]
]);
}
}
}
if (!optionsValues.hasOwnProperty('photosLayer') || optionsValues.photosLayer === 'true') {
photosController.toggleLayer();
}
if (!optionsValues.hasOwnProperty('contactLayer') || optionsValues.contactLayer === 'true') {
contactsController.toggleLayer();
}
if (optionsValues.hasOwnProperty('locControlEnabled') && optionsValues.locControlEnabled === 'true') {
mapController.locControl.start();
}
if (!optionsValues.hasOwnProperty('favoriteCategoryListShow') || optionsValues.favoriteCategoryListShow === 'true') {
favoritesController.toggleCategoryList();
}
if (optionsValues.hasOwnProperty('enabledFavoriteCategories')
&& optionsValues.enabledFavoriteCategories
&& optionsValues.enabledFavoriteCategories !== '')
{
that.enabledFavoriteCategories = optionsValues.enabledFavoriteCategories.split('|');
}
if (!optionsValues.hasOwnProperty('favoritesEnabled') || optionsValues.favoritesEnabled === 'true') {
favoritesController.toggleFavorites();
}
if (!optionsValues.hasOwnProperty('trackListShow') || optionsValues.trackListShow === 'true') {
tracksController.toggleTrackList();
}
if (optionsValues.hasOwnProperty('enabledTracks')
&& optionsValues.enabledTracks
&& optionsValues.enabledTracks !== '')
{
that.enabledTracks = optionsValues.enabledTracks.split('|').map(function (x) {
return parseInt(x);
});
}
if (getUrlParameter('track') || !optionsValues.hasOwnProperty('tracksEnabled') || optionsValues.tracksEnabled === 'true') {
tracksController.toggleTracks();
}
if (!optionsValues.hasOwnProperty('deviceListShow') || optionsValues.deviceListShow === 'true') {
devicesController.toggleDeviceList();
}
if (optionsValues.hasOwnProperty('enabledDevices')
&& optionsValues.enabledDevices
&& optionsValues.enabledDevices !== '')
{
that.enabledDevices = optionsValues.enabledDevices.split('|').map(function (x) {
return parseInt(x);
});
}
if (optionsValues.hasOwnProperty('enabledDeviceLines')
&& optionsValues.enabledDeviceLines
&& optionsValues.enabledDeviceLines !== '')
{
that.enabledDeviceLines = optionsValues.enabledDeviceLines.split('|').map(function (x) {
return parseInt(x);
});
}
if (!optionsValues.hasOwnProperty('devicesEnabled') || optionsValues.devicesEnabled === 'true') {
devicesController.toggleDevices();
}
if (optionsValues.hasOwnProperty('trackMe') && optionsValues.trackMe === 'true') {
$('#track-me').prop('checked', true);
devicesController.launchTrackLoop();
}
// save tile layer when changed
// do it after restore, otherwise restoring triggers save
mapController.map.on('baselayerchange ', function(e) {
optionsController.saveOptionValues({tileLayer: e.name});
// make sure map is clean
for (var ol in mapController.baseOverlays) {
mapController.map.removeLayer(mapController.baseOverlays[ol]);
}
for (var tl in mapController.baseLayers) {
if (tl !== e.name) {
mapController.map.removeLayer(mapController.baseLayers[tl]);
}
}
if (e.name === 'Watercolor') {
mapController.map.addLayer(mapController.baseOverlays['Roads and labels']);
}
mapController.layerChanged(e.name);
});
// routing
var nbRouters = 0;
if (optionsValues.hasOwnProperty('osrmCarURL') && optionsValues.osrmCarURL !== '') {
nbRouters++;
}
if (optionsValues.hasOwnProperty('osrmBikeURL') && optionsValues.osrmBikeURL !== '') {
nbRouters++;
}
if (optionsValues.hasOwnProperty('osrmFootURL') && optionsValues.osrmFootURL !== '') {
nbRouters++;
}
if (optionsValues.hasOwnProperty('mapboxAPIKEY') && optionsValues.mapboxAPIKEY !== '') {
nbRouters++;
}
if ((optionsValues.hasOwnProperty('graphhopperURL') && optionsValues.graphhopperURL !== '') ||
(optionsValues.hasOwnProperty('graphhopperAPIKEY') && optionsValues.graphhopperAPIKEY !== '') ){
nbRouters++;
}
if (nbRouters === 0 && !OC.isUserAdmin()) {
// disable routing and hide it to the user
// search bar
$('#route-submit').hide();
$('#search-submit').css('right', '10px');
// context menu: remove routing related items
mapController.map.contextmenu.removeItem(mapController.map.contextmenu._items[mapController.map.contextmenu._items.length-1].el);
mapController.map.contextmenu.removeItem(mapController.map.contextmenu._items[mapController.map.contextmenu._items.length-1].el);
mapController.map.contextmenu.removeItem(mapController.map.contextmenu._items[mapController.map.contextmenu._items.length-1].el);
mapController.map.contextmenu.removeItem(mapController.map.contextmenu._items[mapController.map.contextmenu._items.length-1].el);
// and we don't init routingController
}
else {
routingController.initRoutingControl(mapController.map, optionsValues);
}
//if (optionsValues.hasOwnProperty('routingEnabled') && optionsValues.routingEnabled === 'true') {
// routingController.toggleRouting();
//}
}).fail(function() {
OC.Notification.showTemporary(
t('maps', 'Failed to restore options values')
);
});
}
};
var mapController = {
searchMarkerLayerGroup: null,
map: {},
locControl: undefined,
baseLayers: undefined,
displaySearchResult: function(results) {
this.searchMarkerLayerGroup.clearLayers();
var result, searchMarker;
for (var i=0; i < results.length; i++) {
result = results[i];
searchMarker = L.marker([result.lat, result.lon], {
icon: this.searchIcon
});
var name = result.display_name;
// popup
var popupContent = searchController.parseOsmResult(result);
searchMarker.bindPopup(popupContent, {className: 'search-result-popup'});
// tooltip
var name = '';
if (result.namedetails && result.namedetails.name) {
name = result.namedetails.name;
}
else {
name = result.display_name;
}
var tooltipContent = brify(name, 40);
searchMarker.bindTooltip(tooltipContent, {className: 'search-result-tooltip'});
searchMarker.addTo(this.searchMarkerLayerGroup);
}
if (results.length === 1) {
this.searchMarkerLayerGroup.getLayers()[0].openPopup();
this.map.flyTo([results[0].lat, results[0].lon], 15, {duration: 1});
}
},
initMap: function() {
var that = this;
this.searchIcon = L.divIcon({
iconAnchor: [12, 25],
className: 'route-waypoint route-middle-waypoint',
html: ''
});
var attribution = '© OpenStreetMap contributors, CC-BY-SA';
var osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution : attribution,
noWrap: false,
detectRetina: false,
maxZoom: 19
});
var attributionESRI = 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN...';
var ESRIAerial = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
attribution : attributionESRI,
noWrap: false,
detectRetina: true,
maxZoom: 19
});
var roadsOverlay = L.tileLayer('https://{s}.tile.openstreetmap.se/hydda/roads_and_labels/{z}/{x}/{y}.png', {
maxZoom: 18,
opacity: 0.7,
attribution: 'OpenStreetMap Sweden — Map data © OpenStreetMap contributors'
});
var ESRITopo = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}', {
attribution : attributionESRI,
noWrap: false,
detectRetina: false,
maxZoom: 19
});
var attributionOpenTopo = 'Map data: © OpenStreetMap, SRTM | Map style: © OpenTopoMap (CC-BY-SA)';
var openTopo = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
attribution : attributionOpenTopo,
noWrap: false,
detectRetina: false,
maxZoom: 17
});
var attributionDark = '© Map tiles by CartoDB, under CC BY 3.0. Data by OpenStreetMap, under ODbL.';
var dark = L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png', {
attribution : attributionDark,
noWrap: false,
detectRetina: false,
maxZoom: 18
});
var attributionWatercolor = 'Leaflet | © Map tiles by Stamen Design, under CC BY 3.0, Data by OpenStreetMap, under CC BY SA.';
var watercolor = L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.{ext}', {
attribution : attributionWatercolor,
noWrap: false,
detectRetina: false,
maxZoom: 18,
ext: 'jpg',
subdomains: 'abcd'
});
var starImageUrl = OC.generateUrl('/svg/core/actions/star-dark?color=000000');
var markerRedImageUrl = OC.generateUrl('/svg/core/actions/address?color=EE3333');
var markerBlueImageUrl = OC.generateUrl('/svg/core/actions/address?color=3333EE');
var markerGreenImageUrl = OC.generateUrl('/svg/core/actions/address?color=33EE33');
var photoImageUrl = OC.generateUrl('/svg/core/places/picture?color=000000');
var contactImageUrl = OC.generateUrl('/svg/core/actions/user?color=000000');
var shareImageUrl = OC.generateUrl('/svg/core/actions/share?color=000000');
this.map = L.map('map', {
zoom: 2,
zoomControl: false,
maxZoom: 19,
minZoom: 2,
center: new L.LatLng(0, 0),
maxBounds: new L.LatLngBounds(new L.LatLng(-90, 720), new L.LatLng(90, -720)),
layers: [],
// right click menu
contextmenu: false,
contextmenuWidth: 160,
contextmenuItems: [{
text: t('maps', 'Add a favorite'),
icon: starImageUrl,
callback: favoritesController.contextAddFavorite
}, {
text: t('maps', 'Place photos'),
icon: photoImageUrl,
callback: photosController.contextPlacePhotos
//}, {
// text: t('maps', 'Place photo folder'),
// icon: photoImageUrl,
// callback: photosController.contextPlacePhotoFolder
}, {
text: t('maps', 'Place contact'),
icon: contactImageUrl,
callback: contactsController.contextPlaceContact
}, {
text: t('maps', 'Share this location'),
icon: shareImageUrl,
callback: geoLinkController.shareLocation
}, '-', {
text: t('maps', 'Route from here'),
icon: markerGreenImageUrl,
callback: routingController.contextRouteFrom
}, {
text: t('maps', 'Add route point'),
icon: markerBlueImageUrl,
callback: routingController.contextRoutePoint
}, {
text: t('maps', 'Route to here'),
icon: markerRedImageUrl,
callback: routingController.contextRouteTo
}]
});
this.map.on('contextmenu', function(e) {
if ($(e.originalEvent.target).attr('id') === 'map') {
that.map.contextmenu.showAt(L.latLng(e.latlng.lat, e.latlng.lng));
}
});
this.map.clickpopup = null;
this.map.leftClickLock = false;
this.map.on('click', function(e) {
if ($(e.originalEvent.target).attr('id') === 'map') {
if (!that.map.leftClickLock && that.map.clickpopup === null) {
console.log('no popup');
searchController.mapLeftClick(e);
that.map.clickpopup = true;
}
else {
that.map.closePopup();
that.map.clickpopup = null;
}
}
});
this.map.on('moveend', function(e) {
var bounds = that.map.getBounds();
optionsController.saveOptionValues({
mapBounds: bounds.getNorth() + ';' +
bounds.getSouth() + ';' +
bounds.getEast() + ';' +
bounds.getWest()
});
});
this.searchMarkerLayerGroup = L.featureGroup();
this.map.addLayer(this.searchMarkerLayerGroup);
var locale = OC.getLocale();
var imperial = (
locale === 'en_US' ||
locale === 'en_GB' ||
locale === 'en_AU' ||
locale === 'en_IE' ||
locale === 'en_NZ' ||
locale === 'en_CA'
);
var metric = !imperial;
L.control.scale({metric: metric, imperial: imperial, position: 'bottomleft'})
.addTo(this.map);
//L.control.mousePosition().addTo(this.map);
L.control.zoom({position: 'bottomright'}).addTo(this.map);
this.locControl = L.control.locate({
position: 'bottomright',
drawCircle: true,
drawMarker: true,
showPopup: false,
icon: 'fa fa-map-marker-alt',
iconLoading: 'fa fa-spinner fa-spin',
strings: {
title: t('maps', 'See current location')
},
flyTo: true,
returnToPrevBounds: true,
setView: 'untilPan',
showCompass: true,
locateOptions: {enableHighAccuracy: true, maxZoom: 15}
}).addTo(this.map);
$('.leaflet-control-locate a').click( function(e) {
optionsController.saveOptionValues({locControlEnabled: mapController.locControl._active});
});
this.layersButton = L.easyButton({
position: 'bottomright',
states: [{
stateName: 'no-importa',
icon: ' ',
title: t('maps', 'Other layers'),
onClick: function(btn, map) {
$('.leaflet-control-layers').toggle();
$('.easy-button-container').toggle();
}
}]
});
this.layersButton.addTo(this.map);
// tile layer selector
this.baseLayers = {
'OpenStreetMap': osm,
'ESRI Aerial': ESRIAerial,
'ESRI Topo': ESRITopo,
'OpenTopoMap': openTopo,
'Dark': dark,
'Watercolor': watercolor
}
this.baseOverlays = {
'Roads and labels': roadsOverlay
}
this.controlLayers = L.control.layers(
this.baseLayers,
this.baseOverlays,
{position: 'bottomright', collapsed: false}
).addTo(this.map);
// hide openstreetmap, ESRI Aerial and roads/labels because they are dynamically managed
this.controlLayers.removeLayer(this.baseLayers['OpenStreetMap']);
this.controlLayers.removeLayer(this.baseLayers['ESRI Aerial']);
this.controlLayers.removeLayer(this.baseOverlays['Roads and labels']);
$('.leaflet-control-layers').toggle();
// main layers buttons
var esriImageUrl = OC.filePath('maps', 'css/images', 'esri.jpg');
this.esriButton = L.easyButton({
position: 'bottomright',
states: [{
stateName: 'no-importa',
icon: '',
title: t('maps', 'Aerial map'),
onClick: function(btn, map) {
that.changeTileLayer('ESRI Aerial', true);
}
}]
});
var osmImageUrl = OC.filePath('maps', 'css/images', 'osm.png');
this.osmButton = L.easyButton({
position: 'bottomright',
states: [{
stateName: 'no-importa',
icon: '',
title: t('maps', 'Classic map'),
onClick: function(btn, map) {
that.changeTileLayer('OpenStreetMap', true);
}
}]
});
},
changeTileLayer: function(name, save=false) {
for (var tl in this.baseLayers) {
this.map.removeLayer(this.baseLayers[tl]);
}
for (var ol in this.baseOverlays) {
this.map.removeLayer(this.baseOverlays[ol]);
}
this.map.addLayer(this.baseLayers[name]);
if (name === 'ESRI Aerial' || name === 'Watercolor') {
this.map.addLayer(this.baseOverlays['Roads and labels']);
}
this.layerChanged(name);
if (save) {
optionsController.saveOptionValues({tileLayer: name});
}
},
layerChanged: function(name) {
if (name !== 'OpenStreetMap') {
this.esriButton.remove();
this.osmButton.addTo(this.map);
}
else {
this.osmButton.remove();
this.esriButton.addTo(this.map);
}
// map maxZoom should be dynamic (if not specified at map creation) but something crashes like that
// so we set it on map creation and
// we change it on tile layer change
if (this.baseLayers[name].options.maxZoom) {
this.map.setMaxZoom(this.baseLayers[name].options.maxZoom);
}
$('.leaflet-control-layers').hide();
$('.easy-button-container').show();
},
};
var routingController = {
control: undefined,
map: undefined,
enabled: false,
routers: {},
selectedRouter: 'osrmDEMO',
initRoutingControl: function(map, optionsValues) {
this.map = map;
var that = this;
$('body').on('click', '#routing-close', function(e) {
routingController.toggleRouting();
});
this.beginIcon = L.divIcon({
iconAnchor: [12, 25],
className: 'route-waypoint route-begin-waypoint',
html: ''
});
this.middleIcon = L.divIcon({
iconAnchor: [12, 25],
className: 'route-waypoint route-middle-waypoint',
html: ''
});
this.endIcon = L.divIcon({
iconAnchor: [12, 25],
className: 'route-waypoint route-end-waypoint',
html: ''
});
var lang = OC.getLocale();
// this is for all routing engines except OSRM
L.Routing.Localization[lang] = {
directions: {
N: t('maps', 'north'),
NE: t('maps', 'northeast'),
E: t('maps', 'east'),
SE: t('maps', 'southeast'),
S: t('maps', 'south'),
SW: t('maps', 'southwest'),
W: t('maps', 'west'),
NW: t('maps', 'northwest'),
SlightRight: t('maps', 'slight right'),
Right: t('maps', 'right'),
SharpRight: t('maps', 'sharp right'),
SlightLeft: t('maps', 'slight left'),
Left: t('maps', 'left'),
SharpLeft: t('maps', 'sharp left'),
Uturn: t('maps', 'Turn around')
},
instructions: {
// instruction, postfix if the road is named
'Head':
[t('maps', 'Head {dir}'), t('maps', ' on {road}')],
'Continue':
[t('maps', 'Continue {dir}')],
'TurnAround':
[t('maps', 'Turn around')],
'WaypointReached':
[t('maps', 'Waypoint reached')],
'Roundabout':
[t('maps', 'Take the {exitStr} exit in the roundabout'), t('maps', ' onto {road}')],
'DestinationReached':
[t('maps', 'Destination reached')],
'Fork': [t('maps', 'At the fork, turn {modifier}'), t('maps', ' onto {road}')],
'Merge': [t('maps', 'Merge {modifier}'), t('maps', ' onto {road}')],
'OnRamp': [t('maps', 'Turn {modifier} on the ramp'), t('maps', ' onto {road}')],
'OffRamp': [t('maps', 'Take the ramp on the {modifier}'), t('maps', ' onto {road}')],
'EndOfRoad': [t('maps', 'Turn {modifier} at the end of the road'), t('maps', ' onto {road}')],
'Onto': t('maps', 'onto {road}')
},
ui: {
startPlaceholder: t('maps', 'Start'),
viaPlaceholder: t('maps', 'Via {viaNumber}'),
endPlaceholder: t('maps', 'Destination')
},
formatOrder: function(n) {
return n + 'º';
},
units: {
meters: t('maps', 'm'),
kilometers: t('maps', 'km'),
yards: t('maps', 'yd'),
miles: t('maps', 'mi'),
hours: t('maps', 'h'),
minutes: t('maps', 'min'),
seconds: t('maps', 's')
}
};
this.routers.osrmDEMO = {
name: 'By car (OSRM demo)',
router: L.Routing.osrmv1({
serviceUrl: 'https://router.project-osrm.org/route/v1',
//profile: 'driving', // works with demo server
profile: 'car', // works with demo server
//profile: 'bicycle', // does not work with demo server...
//profile: 'foot', // does not work with demo server...
suppressDemoServerWarning: true,
// this makes OSRM use our local translations
// otherwise it uses osrm-text-instructions which requires to import another lib
stepToText: function(e) {
}
})
};
this.control = L.Routing.control({
router: this.routers.osrmDEMO.router,
position: 'topleft',
routeWhileDragging: true,
reverseWaypoints: true,
geocoder: L.Control.Geocoder.nominatim(),
language: lang,
lineOptions: {
styles: [
{color: 'black', opacity: 0.15, weight: 9},
{color: 'white', opacity: 0.8, weight: 6},
{color: 'blue', opacity: 1, weight: 2}
],
},
pointMarkerStyle: {radius: 5, color: '#03f', fillColor: 'white', opacity: 1, fillOpacity: 0.7},
createMarker: this.createMarker
})
.on('routingerror', this.onRoutingError)
.on('routingstart', this.onRoutingStart)
.on('routesfound', this.onRoutingEnd);
//// toggle routing control
//$('body').on('click', '#navigation-routing > a', function(e) {
// that.toggleRouting();
// optionsController.saveOptionValues({routingEnabled: that.enabled});
//});
// export
$('body').on('click', '.exportCurrentRoute', function(e) {
that.exportRoute();
});
// select router
$('body').on('change', '#router-select', function(e) {
var type = $(this).val();
that.selectedRouter = type;
var router = that.routers[type].router;
that.setRouter(type);
optionsController.saveOptionValues({selectedRouter: type});
that.control.route();
});
// add routers from options values
if (optionsValues.hasOwnProperty('osrmCarURL') && optionsValues.osrmCarURL !== '') {
this.addRouter('osrmCar', 'By car (OSRM)', optionsValues.osrmCarURL, null);
}
if (optionsValues.hasOwnProperty('osrmBikeURL') && optionsValues.osrmBikeURL !== '') {
this.addRouter('osrmBike', 'By bike (OSRM)', optionsValues.osrmBikeURL, null);
}
if (optionsValues.hasOwnProperty('osrmFootURL') && optionsValues.osrmFootURL !== '') {
this.addRouter('osrmFoot', 'By foot (OSRM)', optionsValues.osrmFootURL, null);
nbRouters++;
}
if (optionsValues.hasOwnProperty('osrmDEMO') && optionsValues.osrmDEMO === '1') {
this.addRouter('osrmDEMO', 'By car (OSRM demo)', null, null);
}
else {
delete this.routers.osrmDEMO;
}
if (optionsValues.hasOwnProperty('mapboxAPIKEY') && optionsValues.mapboxAPIKEY !== '') {
this.addRouter('mapbox', 'Mapbox', null, optionsValues.mapboxAPIKEY);
}
if ((optionsValues.hasOwnProperty('graphhopperURL') && optionsValues.graphhopperURL !== '') ||
(optionsValues.hasOwnProperty('graphhopperAPIKEY') && optionsValues.graphhopperAPIKEY !== '') ){
var apikey = undefined;
if (optionsValues.hasOwnProperty('graphhopperAPIKEY') && optionsValues.graphhopperAPIKEY !== '') {
apikey = optionsValues.graphhopperAPIKEY;
}
this.addRouter('graphhopperCar', 'By car (GrahHopper)', optionsValues.graphhopperURL, apikey);
this.addRouter('graphhopperBike', 'By bike (GrahHopper)', optionsValues.graphhopperURL, apikey);
this.addRouter('graphhopperFoot', 'By Foot (GrahHopper)', optionsValues.graphhopperURL, apikey);
}
if (optionsValues.hasOwnProperty('selectedRouter') && optionsValues.selectedRouter !== '') {
this.selectedRouter = optionsValues.selectedRouter;
this.setRouter(optionsValues.selectedRouter);
}
else {
var fallback = null;
for (var type in this.routers) {
fallback = type;
break;
}
this.setRouter(fallback);
}
},
toggleRouting: function() {
var that = this;
if (this.enabled) {
$('.leaflet-routing-container').fadeOut('fast', function(e) {
that.control.remove();
//$('#search-form').fadeIn('fast');
$('#search-form').show();
$('#navigation-routing').removeClass('active');
$('#map').focus();
that.enabled = false;
});
}
else {
$('#search-form').fadeOut('fast', function(e) {
that.control.addTo(that.map);
//$('.leaflet-routing-container').fadeIn();
//$('.leaflet-routing-container').hide(0, function(e) {
//});
$('#navigation-routing').addClass('active');
that.enabled = true;
$('.leaflet-routing-geocoder input').first().focus();
// add router selector
var select = '';
var close = '';
$('.leaflet-routing-container').prepend(close);
$('.leaflet-routing-geocoders').append(select);
});
}
},
setRouter: function(routerType) {
if (this.routers.hasOwnProperty(routerType)) {
var router = this.routers[routerType].router;
this.control._router = router;
this.control.options.router = router;
}
},
// create router and make it accessible in the interface
addRouter: function(type, name, url, apikey) {
if (type === 'graphhopperBike' || type === 'graphhopperCar' || type === 'graphhopperFoot') {
var options = {};
if (type === 'graphhopperCar') {
options.urlParameters = {
vehicle: 'car' // available ones : car, foot, bike, bike2, mtb, racingbike, motorcycle
};
}
if (type === 'graphhopperBike') {
options.urlParameters = {
vehicle: 'bike'
};
}
if (type === 'graphhopperFoot') {
options.urlParameters = {
vehicle: 'foot'
};
}
if (url) {
options.serviceUrl = url;
}
this.routers[type] = {
name: name,
router: L.Routing.graphHopper(apikey, options)
};
}
else if (type === 'osrmBike' || type === 'osrmCar' || type === 'osrmFoot') {
var options = {
serviceUrl: url,
suppressDemoServerWarning: true,
// this makes OSRM use our local translations
// otherwise it uses osrm-text-instructions which requires to import another lib
stepToText: function(e) {
}
};
if (type === 'osrmCar') {
options.profile = 'car';
}
else if (type === 'osrmBike') {
options.profile = 'bicycle';
}
else if (type === 'osrmFoot') {
options.profile = 'foot';
}
this.routers[type] = {
name: name,
router: L.Routing.osrmv1(options)
};
}
else if (type === 'mapbox') {
this.routers.mapbox = {
name: name,
router: L.Routing.mapbox(apikey)
};
}
else if (type === 'osrmDEMO') {
}
},
onRoutingError: function(e) {
var msg = e.error.target.responseText
try {
var json = $.parseJSON(e.error.target.responseText);
if (json.message) {
msg = json.message;
}
}
catch (e) {
}
OC.Notification.showTemporary(t('maps', 'Routing error:') + ' ' + msg);
routingController.onRoutingEnd();
},
onRoutingStart: function(e) {
$('#navigation-routing').addClass('icon-loading-small');
$('.leaflet-routing-reverse-waypoints').addClass('icon-loading-small');
},
onRoutingEnd: function(e) {
$('#navigation-routing').removeClass('icon-loading-small');
$('.leaflet-routing-reverse-waypoints').removeClass('icon-loading-small');
// TODO understand why routingstart is sometimes triggered after routesfound
// just in case routingstart is triggered again (weird):
setTimeout(function() {
$('#navigation-routing').removeClass('icon-loading-small');
$('.leaflet-routing-reverse-waypoints').removeClass('icon-loading-small');
}, 5000);
},
//// this has been tested with graphhopper
//setRouterVehicle: function(vehicle) {
// if (this.selectedRouter === 'graphhopper') {
// this.control.getRouter().options.urlParameters.vehicle = vehicle;
// }
// else if (this.selectedRouter === 'osrm') {
// this.control.getRouter().options.profile = vehicle.replace('bike', 'bicycle');
// }
// this.control.route();
//},
createMarker: function(i, wpt, n) {
var icon;
if (i === 0) {
icon = routingController.beginIcon;
}
else if (i === n - 1) {
icon = routingController.endIcon;
}
else {
icon = routingController.middleIcon;
}
var marker = L.marker(wpt.latLng, {icon: icon, draggable: true});
return marker;
},
exportRoute: function() {
if (this.control.hasOwnProperty('_selectedRoute')
&& this.control._selectedRoute.hasOwnProperty('coordinates')
&& this.control._selectedRoute.coordinates.length > 0
) {
var latLngCoords = this.control._selectedRoute.coordinates;
var gpxRteCoords = '';
for (var i=0; i < latLngCoords.length; i++) {
gpxRteCoords = gpxRteCoords + '
' + day + ' | '; var startTime = from.toLocaleTimeString(); var endTime =to.toLocaleTimeString(); desc += '' + startTime + ' - ' + endTime + ' | '; desc += '