(function ($, OC) { 'use strict'; var gpxedit = { map: {}, baseLayers: null, restoredTileLayer: null, drawControl: null, id: 0, // indexed by gpxedit_id layersData: {}, currentAjax: null }; var symbolSelectClasses = { 'unknown': 'unknown-select', 'marker': 'marker-select', 'Dot, White': 'dot-select', 'Pin, Blue': 'pin-blue-select', 'Pin, Green': 'pin-green-select', 'Pin, Red': 'pin-red-select', 'Flag, Green': 'flag-green-select', 'Flag, Red': 'flag-red-select', 'Flag, Blue': 'flag-blue-select', 'Block, Blue': 'block-blue-select', 'Block, Green': 'block-green-select', 'Block, Red': 'block-red-select', 'Blue Diamond': 'diamond-blue-select', 'Green Diamond': 'diamond-green-select', 'Red Diamond': 'diamond-red-select', 'Residence': 'residence-select', 'Drinking Water': 'drinking-water-select', 'Trail Head': 'hike-select', 'Bike Trail': 'bike-trail-select', 'Campground': 'campground-select', 'Bar': 'bar-select', 'Skull and Crossbones': 'skullcross-select', 'Geocache': 'geocache-select', 'Geocache Found': 'geocache-open-select', 'Medical Facility': 'medical-select', 'Contact, Alien': 'contact-alien-select', 'Contact, Big Ears': 'contact-bigears-select', 'Contact, Female3': 'contact-female3-select', 'Contact, Cat': 'contact-cat-select', 'Contact, Dog': 'contact-dog-select', }; var symbolIcons = { 'marker': L.divIcon({ className: 'leaflet-marker-blue', iconAnchor: [12, 41] }), 'Dot, White': L.divIcon({ iconSize: L.point(7,7), }), 'Pin, Blue': L.divIcon({ className: 'pin-blue', iconAnchor: [5, 30] }), 'Pin, Green': L.divIcon({ className: 'pin-green', iconAnchor: [5, 30] }), 'Pin, Red': L.divIcon({ className: 'pin-red', iconAnchor: [5, 30] }), 'Flag, Green': L.divIcon({ className: 'flag-green', iconAnchor: [1, 25] }), 'Flag, Red': L.divIcon({ className: 'flag-red', iconAnchor: [1, 25] }), 'Flag, Blue': L.divIcon({ className: 'flag-blue', iconAnchor: [1, 25] }), 'Block, Blue': L.divIcon({ className: 'block-blue', iconAnchor: [8, 8] }), 'Block, Green': L.divIcon({ className: 'block-green', iconAnchor: [8, 8] }), 'Block, Red': L.divIcon({ className: 'block-red', iconAnchor: [8, 8] }), 'Blue Diamond': L.divIcon({ className: 'diamond-blue', iconAnchor: [9, 9] }), 'Green Diamond': L.divIcon({ className: 'diamond-green', iconAnchor: [9, 9] }), 'Red Diamond': L.divIcon({ className: 'diamond-red', iconAnchor: [9, 9] }), 'Residence': L.divIcon({ className: 'residence', iconAnchor: [12, 12] }), 'Drinking Water': L.divIcon({ className: 'drinking-water', iconAnchor: [12, 12] }), 'Trail Head': L.divIcon({ className: 'hike', iconAnchor: [12, 12] }), 'Bike Trail': L.divIcon({ className: 'bike-trail', iconAnchor: [12, 12] }), 'Campground': L.divIcon({ className: 'campground', iconAnchor: [12, 12] }), 'Bar': L.divIcon({ className: 'bar', iconAnchor: [10, 12] }), 'Skull and Crossbones': L.divIcon({ className: 'skullcross', iconAnchor: [12, 12] }), 'Geocache': L.divIcon({ className: 'geocache', iconAnchor: [11, 10] }), 'Geocache Found': L.divIcon({ className: 'geocache-open', iconAnchor: [11, 10] }), 'Medical Facility': L.divIcon({ className: 'medical', iconAnchor: [13, 11] }), 'Contact, Alien': L.divIcon({ className: 'contact-alien', iconAnchor: [12, 12] }), 'Contact, Big Ears': L.divIcon({ className: 'contact-bigears', iconAnchor: [12, 12] }), 'Contact, Female3': L.divIcon({ className: 'contact-female3', iconAnchor: [12, 12] }), 'Contact, Cat': L.divIcon({ className: 'contact-cat', iconAnchor: [12, 12] }), 'Contact, Dog': L.divIcon({ className: 'contact-dog', iconAnchor: [12, 12] }), }; var hoverStyle = { weight: 12, opacity: 0.7, color: 'black' }; var defaultStyle = { opacity: 0.9, color: '#f357a1', weight: 7 }; function endsWith(str, suffix) { return str.indexOf(suffix, str.length - suffix.length) !== -1; } function load_map() { // change meta to send referrer // usefull for IGN tiles authentication ! $('meta[name=referrer]').attr('content', 'origin'); var layer = getUrlParameter('layer'); var default_layer = 'OpenStreetMap'; if (gpxedit.restoredTileLayer !== null) { default_layer = gpxedit.restoredTileLayer; } else if (typeof layer !== 'undefined') { default_layer = decodeURIComponent(layer); } // get url from key and layer type function geopUrl(key, layer, format) { return 'http://wxs.ign.fr/' + key + '/wmts?LAYER=' + layer + '&EXCEPTIONS=text/xml&FORMAT=' + (format?format:'image/jpeg') + '&SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&STYLE=normal' + '&TILEMATRIXSET=PM&TILEMATRIX={z}&TILECOL={x}&TILEROW={y}' ; } // change it if you deploy GPXEDIT var API_KEY = 'ljthe66m795pr2v2g8p7faxt'; var ign = new L.tileLayer ( geopUrl(API_KEY,'GEOGRAPHICALGRIDSYSTEMS.MAPS'), { attribution: '© IGN-France', maxZoom: 18 }); var osmUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'; var osmAttribution = 'Map data © 2013 OpenStreetMap contributors'; var osm = new L.TileLayer(osmUrl, {maxZoom: 18, attribution: osmAttribution}); var osmfrUrl = 'http://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png'; var osmfr = new L.TileLayer(osmfrUrl, {maxZoom: 20, attribution: osmAttribution}); var osmfr2 = new L.TileLayer(osmfrUrl, {minZoom: 0, maxZoom: 13, attribution: osmAttribution}); var openmapsurferUrl = 'http://openmapsurfer.uni-hd.de/tiles/roads/' + 'x={x}&y={y}&z={z}'; var openmapsurferAttribution = 'Imagery from GIScience Research Group @ University of Heidelberg — ' + 'Map data © ' + 'OpenStreetMap'; var openmapsurfer = new L.TileLayer(openmapsurferUrl, {maxZoom: 18, attribution: openmapsurferAttribution}); var transportUrl = 'http://a.tile2.opencyclemap.org/transport/{z}/{x}/{y}.' + 'png'; var transport = new L.TileLayer(transportUrl, {maxZoom: 18, attribution: osmAttribution}); var pisteUrl = 'http://tiles.openpistemap.org/nocontours/{z}/{x}/{y}.png'; var piste = new L.TileLayer(pisteUrl, {maxZoom: 18, attribution: osmAttribution}); var hikebikeUrl = 'http://toolserver.org/tiles/hikebike/{z}/{x}/{y}.png'; var hikebike = new L.TileLayer(hikebikeUrl, {maxZoom: 18, attribution: osmAttribution}); var osmCycleUrl = 'http://{s}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png'; var osmCycleAttrib = '© ' + 'OpenCycleMap, © ' + 'OpenStreetMap'; var osmCycle = new L.TileLayer(osmCycleUrl, {maxZoom: 18, attribution: osmCycleAttrib}); var darkUrl = 'http://a.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png'; var darkAttrib = '© Map tiles by CartoDB, under CC BY 3.0. Data by' + ' OpenStreetMap, under ODbL.'; var dark = new L.TileLayer(darkUrl, {maxZoom: 18, attribution: darkAttrib}); var esriTopoUrl = 'https://server.arcgisonline.com/ArcGIS/rest/services/World' + '_Topo_Map/MapServer/tile/{z}/{y}/{x}'; var esriTopoAttrib = 'Tiles © Esri — Esri, DeLorme, NAVTEQ, ' + 'TomTom, Intermap, iPC, USGS, FAO, NPS, NRCAN, GeoBase, Kadaster NL, Ord' + 'nance Survey, Esri Japan, METI, Esri China (Hong Kong), and the GIS User' + ' Community'; var esriTopo = new L.TileLayer(esriTopoUrl, {maxZoom: 18, attribution: esriTopoAttrib}); var esriAerialUrl = 'https://server.arcgisonline.com/ArcGIS/rest/services' + '/World_Imagery/MapServer/tile/{z}/{y}/{x}'; var esriAerialAttrib = 'Tiles © Esri — Source: Esri, i-cubed, ' + 'USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the' + ' GIS User Community'; var esriAerial = new L.TileLayer(esriAerialUrl, {maxZoom: 18, attribution: esriAerialAttrib}); var tonerUrl = 'http://{s}.tile.stamen.com/toner/{z}/{x}/{y}.jpg'; var stamenAttribution = 'Leaflet | © Map tiles by Stamen Design, under CC BY 3.0, Data by OpenSt' + 'reetMap, under CC BY SA.'; var toner = new L.TileLayer(tonerUrl, {maxZoom: 18, attribution: stamenAttribution}); var watercolorUrl = 'http://{s}.tile.stamen.com/watercolor/{z}/{x}/{y}.jpg'; var watercolor = new L.TileLayer(watercolorUrl, {maxZoom: 18, attribution: stamenAttribution}); var routeUrl = 'http://{s}.tile.openstreetmap.fr/route500/{z}/{x}/{y}.png'; var routeAttrib = '©, Tiles © O' + 'penStreetMap France'; var route = new L.TileLayer(routeUrl, {minZoom: 1, maxZoom: 20, attribution: routeAttrib}); var baseLayers = { 'OpenStreetMap': osm, 'OpenCycleMap': osmCycle, 'IGN France': ign, 'OpenMapSurfer Roads': openmapsurfer, 'Hike & bike': hikebike, 'OSM Transport': transport, 'ESRI Aerial': esriAerial, 'ESRI Topo with relief': esriTopo, 'Dark': dark, 'Toner': toner, 'Watercolor': watercolor, 'OpenStreetMap France': osmfr }; // add custom layers $('#tileserverlist li').each(function() { var sname = $(this).attr('name'); var surl = $(this).attr('title'); baseLayers[sname] = new L.TileLayer(surl, {maxZoom: 18, attribution: 'custom tile server'}); }); gpxedit.baseLayers = baseLayers; var baseOverlays = { 'OsmFr Route500': route, 'OpenPisteMap Relief': L.tileLayer('http://tiles2.openpistemap.org/landshaded/{z}/{x}/{y}.png', { attribution: '©, Tiles © OpenStreetMap France', minZoom: 1, maxZoom: 15 } ), 'OpenPisteMap pistes': piste }; var layerlist = []; gpxedit.map = new L.Map('map', { zoomControl: true, layers: layerlist, }); L.control.scale({metric: true, imperial: true, position: 'topleft'}) .addTo(gpxedit.map); L.control.mousePosition().addTo(gpxedit.map); gpxedit.searchControl = L.Control.geocoder({position: 'topleft'}); gpxedit.searchControl.addTo(gpxedit.map); gpxedit.locateControl = L.control.locate({follow: true}); gpxedit.locateControl.addTo(gpxedit.map); L.Control.measureControl().addTo(gpxedit.map); L.control.sidebar('sidebar').addTo(gpxedit.map); gpxedit.map.setView(new L.LatLng(27, 5), 3); if (! baseLayers.hasOwnProperty(default_layer)) { default_layer = 'OpenStreetMap'; } gpxedit.map.addLayer(baseLayers[default_layer]); gpxedit.activeLayers = L.control.activeLayers(baseLayers, baseOverlays); gpxedit.activeLayers.addTo(gpxedit.map); gpxedit.minimapControl = new L.Control.MiniMap( osmfr2, { toggleDisplay: true, position: 'bottomright' } ).addTo(gpxedit.map); gpxedit.minimapControl._toggleDisplayButtonClicked(); gpxedit.editableLayers = new L.FeatureGroup(); gpxedit.map.addLayer(gpxedit.editableLayers); var options = { position: 'bottomleft', draw: { polyline: { shapeOptions: { color: '#f357a1', weight: 7 } }, polygon: false, circle: false, rectangle: false, marker: { icon: symbolIcons.marker } }, edit: { featureGroup: gpxedit.editableLayers, //REQUIRED!! } }; L.drawLocal.draw.toolbar.buttons.polyline = t('gpxedit', 'Draw a track'); L.drawLocal.draw.toolbar.buttons.marker = t('gpxedit', 'Add a waypoint'); L.drawLocal.edit.toolbar.buttons.edit = t('gpxedit', 'Edit'); L.drawLocal.edit.toolbar.buttons.editDisabled = t('gpxedit', 'Nothing to edit'); L.drawLocal.edit.toolbar.buttons.remove = t('gpxedit', 'Delete'); L.drawLocal.edit.toolbar.buttons.removeDisabled = t('gpxedit', 'Nothing to delete'); L.drawLocal.edit.toolbar.actions.save.title = t('gpxedit', 'Validate changes'); L.drawLocal.edit.toolbar.actions.save.text = t('gpxedit', 'Ok'); L.drawLocal.edit.toolbar.actions.cancel.title = t('gpxedit', 'Discard all changes'); L.drawLocal.edit.toolbar.actions.cancel.text = t('gpxedit', 'Cancel'); L.drawLocal.edit.handlers.edit.tooltip.text = t('gpxedit', 'Drag to move elements,
click to remove a point'); L.drawLocal.edit.handlers.edit.tooltip.subtext = t('gpxedit', 'Click cancel to undo changes'); L.drawLocal.edit.handlers.remove.tooltip.text = t('gpxedit', 'Click on an element to delete it'); L.drawLocal.draw.handlers.marker.tooltip.start = t('gpxedit', 'Click map to add waypoint'); L.drawLocal.draw.handlers.polyline.tooltip.start = t('gpxedit', 'Click to start drawing track'); L.drawLocal.draw.handlers.polyline.tooltip.cont = t('gpxedit', 'Click to continue drawing track'); L.drawLocal.draw.handlers.polyline.tooltip.end = t('gpxedit', 'Click last point to finish track'); L.drawLocal.draw.toolbar.actions.text = t('gpxedit', 'Cancel'); L.drawLocal.draw.toolbar.actions.title = t('gpxedit', 'Cancel drawing'); L.drawLocal.draw.toolbar.finish.text = t('gpxedit', 'Finish'); L.drawLocal.draw.toolbar.finish.title = t('gpxedit', 'Finish drawing'); L.drawLocal.draw.toolbar.undo.text = t('gpxedit', 'Delete last point'); L.drawLocal.draw.toolbar.undo.title = t('gpxedit', 'Delete last point drawn'); var drawControl = new L.Control.Draw(options); gpxedit.drawControl = drawControl; gpxedit.map.addControl(drawControl); // when something is created, we generate popup content // and initialize layer data gpxedit.map.on(L.Draw.Event.CREATED, function (e) { onCreated(e.layerType, e.layer); }); // not used for the moment gpxedit.map.on('draw:edited', function (e) { var layers = e.layers; layers.eachLayer(function (layer) { }); }); // remove data associated with the deleted layer gpxedit.map.on('draw:deleted', function (e) { var layers = e.layers; layers.eachLayer(function (layer) { delete gpxedit.layersData[layer.gpxedit_id]; }); }); // load data into popup when it opens // this is needed because popup content is created each time we open one // so, the content is lost when it's closed gpxedit.map.on('popupopen', function(e) { var id = e.popup._source.gpxedit_id; //var id = parseInt(e.popup.getContent().match(/layerid="(\d+)"/)[1]); var buttonParent = $('button.popupOkButton[layerid=' + id + ']').parent(); buttonParent.find('input.layerName').val(gpxedit.layersData[id].name); buttonParent.find('textarea.layerDesc').val(gpxedit.layersData[id].description); buttonParent.find('textarea.layerCmt').val(gpxedit.layersData[id].comment); if (gpxedit.layersData[id].layer.type === 'marker') { if (symbolIcons.hasOwnProperty(gpxedit.layersData[id].symbol)) { buttonParent.find('select[role=symbol]').val(gpxedit.layersData[id].symbol); } else if(gpxedit.layersData[id].symbol === '') { buttonParent.find('select[role=symbol]').val(''); } else{ buttonParent.find('select[role=symbol]').val('unknown'); } buttonParent.find('select[role=symbol]').change(); var latlng = gpxedit.layersData[id].layer.getLatLng(); buttonParent.find('input.layerLat').val(latlng.lat.toFixed(6)); buttonParent.find('input.layerLon').val(latlng.lng.toFixed(6)); } }); gpxedit.map.on('baselayerchange',saveOptions); } // called when something is drawn by hand or when a gpx is loaded // it generates the popup content and initializes the layer's data // it returns the layer in case we want to set the layer's data manually (when loading a gpx) function onCreated(type, layer) { var popupTitle; var layerType; if (type === 'polyline' || type === 'track') { popupTitle = t('gpxedit', 'Track'); layerType = 'track'; } else if (type === 'route') { popupTitle = t('gpxedit', 'Route'); layerType = 'route'; } else if (type === 'marker') { popupTitle = t('gpxedit', 'Waypoint'); layerType = 'marker'; } var popupTxt = '

' + popupTitle + '

' + '' + '' + ''; if (type === 'marker') { popupTxt = popupTxt + ''; popupTxt = popupTxt + ''; popupTxt = popupTxt + ''; } popupTxt = popupTxt + '
' + t('gpxedit', 'Name') + '
' + t('gpxedit', 'Description') + '
' + t('gpxedit', 'Comment') + '
' + t('gpxedit', 'Lat') + '
' + t('gpxedit', 'Lon') + '
' + t('gpxedit', 'Symbol') + '
'; popupTxt = popupTxt + ''; layer.bindPopup(popupTxt); if (type !== 'marker') { layer.on('mouseover', function() { layer.setStyle(hoverStyle); }); layer.on('mouseout', function() { layer.setStyle(defaultStyle); }); } layer.gpxedit_id = gpxedit.id; layer.type = layerType; gpxedit.layersData[gpxedit.id] = { name: '', description: '', comment: '', symbol: '', time: '', layer: layer }; gpxedit.editableLayers.addLayer(layer); gpxedit.id++; return layer; } function getUrlParameter(sParam) { var sPageURL = window.location.search.substring(1); var sURLVariables = sPageURL.split('&'); for (var i = 0; i < sURLVariables.length; i++) { var sParameterName = sURLVariables[i].split('='); if (sParameterName[0] === sParam) { return decodeURIComponent(sParameterName[1]); } } } // generate gpx text from current map elements function generateGpx() { var lat, lng, alt, time, i, ia; var gpxText = '\n'; var now = new Date(); var now_utc_str = now.getUTCFullYear() + '-' + ("0" + now.getUTCMonth()).slice(-2) + '-' + ("0" + now.getUTCDate()).slice(-2) + 'T' + ("0" + now.getUTCHours()).slice(-2) + ':' + ("0" + now.getUTCMinutes()).slice(-2) + ':' + ("0" + now.getUTCSeconds()).slice(-2) + 'Z'; gpxText = gpxText + '\n'; gpxText = gpxText + '\n \n'; var fileDesc = $('#desctext').val(); if (fileDesc) { gpxText = gpxText + ' ' + fileDesc + '\n'; } gpxText = gpxText + '\n'; var layerArray = []; gpxedit.editableLayers.eachLayer(function(layer) { layerArray.push(layer); }); // sort var sortedLayerArray = layerArray.sort(function (layer1, layer2) { var res; var id1 = layer1.gpxedit_id; var id2 = layer2.gpxedit_id; var name1 = gpxedit.layersData[id1].name; var name2 = gpxedit.layersData[id2].name; var numname1 = parseInt(name1); var numname2 = parseInt(name2); // special cases : at least one of them does not begin by a number // number is always inferior than string if (isNaN(numname1) && !isNaN(numname2)) { res = 1; } else if (!isNaN(numname1) && isNaN(numname2)) { res = -1; } // if both are not begining with a number : compare strings else if (isNaN(numname1) && isNaN(numname2)) { if (name1 < name2) { res = -1; } else if (name1 === name2) { res = 0; } else { res = 1; } } // normal case : both begin with a number else{ if (numname1 < numname2) { res = -1; } // if numbers are identical : compare strings else if(numname1 === numname2) { if (name1 < name2) { res = -1; } else if (name1 === name2) { res = 0; } else { res = 1; } } else{ res = 1; } } return res; }); for (ia = 0; ia < sortedLayerArray.length; ia++){ var layer = sortedLayerArray[ia]; var id = layer.gpxedit_id; var name = gpxedit.layersData[id].name; var comment = gpxedit.layersData[id].comment; var description = gpxedit.layersData[id].description; var time = gpxedit.layersData[id].time; if (layer.type === 'marker') { var symbol = gpxedit.layersData[id].symbol; lat = layer._latlng.lat; lng = layer._latlng.lng; alt = layer._latlng.alt; gpxText = gpxText + ' \n'; if (name) { gpxText = gpxText + ' ' + name + '\n'; } else{ gpxText = gpxText + ' \n'; } if (alt !== undefined) { gpxText = gpxText + ' ' + alt + '\n'; } if (comment) { gpxText = gpxText + ' ' + comment + '\n'; } if (symbol) { gpxText = gpxText + ' ' + symbol + '\n'; } if (description) { gpxText = gpxText + ' ' + description + '\n'; } if (time) { gpxText = gpxText + ' \n'; } gpxText = gpxText + ' \n'; } else if(layer.type === 'track') { gpxText = gpxText + ' \n'; if (name) { gpxText = gpxText + ' ' + name + '\n'; } else{ gpxText = gpxText + ' \n'; } if (comment) { gpxText = gpxText + ' ' + comment + '\n'; } if (description) { gpxText = gpxText + ' ' + description + '\n'; } gpxText = gpxText + ' \n'; for (i = 0; i < layer._latlngs.length; i++) { lat = layer._latlngs[i].lat; lng = layer._latlngs[i].lng; alt = layer._latlngs[i].alt; time = layer._latlngs[i].time; gpxText = gpxText + ' \n'; if (time) { gpxText = gpxText + ' \n'; } if (alt !== undefined) { gpxText = gpxText + ' ' + alt + '\n'; } gpxText = gpxText + ' \n'; } gpxText = gpxText + ' \n \n'; } else if(layer.type === 'route') { gpxText = gpxText + ' \n'; if (name) { gpxText = gpxText + ' ' + name + '\n'; } else{ gpxText = gpxText + ' \n'; } if (comment) { gpxText = gpxText + ' ' + comment + '\n'; } if (description) { gpxText = gpxText + ' ' + description + '\n'; } for (i = 0; i < layer._latlngs.length; i++) { lat = layer._latlngs[i].lat; lng = layer._latlngs[i].lng; alt = layer._latlngs[i].alt; time = layer._latlngs[i].time; gpxText = gpxText + ' \n'; if (time !== undefined) { gpxText = gpxText + ' \n'; } if (alt !== undefined) { gpxText = gpxText + ' ' + alt + '\n'; } gpxText = gpxText + ' \n'; } gpxText = gpxText + ' \n'; } } gpxText = gpxText + ' \n'; return gpxText; } // adds a marker and initialize its data function drawMarker(latlng, name, desc, cmt, sym, time) { var wst = $('#markerstyleselect').val(); var tst = $('#tooltipstyleselect').val(); var symboo = $('#symboloverwrite').is(':checked'); var m = L.marker(latlng); if (symboo && sym !== '' && symbolIcons.hasOwnProperty(sym)) { m.setIcon(symbolIcons[sym]); } else if(symboo && sym !== '') { m.setIcon(L.divIcon({ className: 'unknown', iconAnchor: [12, 12] })); } else{ m.setIcon(symbolIcons[wst]); } var layer = onCreated('marker', m); if (name !== '') { if (tst === 'p') { m.bindTooltip(name, {permanent: true}); } else{ m.bindTooltip(name, {sticky: true}); } } gpxedit.layersData[layer.gpxedit_id].name = name; gpxedit.layersData[layer.gpxedit_id].comment = cmt; gpxedit.layersData[layer.gpxedit_id].description = desc; gpxedit.layersData[layer.gpxedit_id].symbol = sym; gpxedit.layersData[layer.gpxedit_id].time = time; } // adds a polyline and initialize its data function drawLine(latlngs, name, desc, cmt, gpxtype, times) { var wst = $('#markerstyleselect').val(); var tst = $('#tooltipstyleselect').val(); var p = L.polyline(latlngs, { color: '#f357a1', weight: 7 }); if (times.length === p._latlngs.length) { for (var i=0; imetadata>desc').text(); $('#desctext').val(fileDesc); dom.find('wpt').each(function() { var lat = $(this).attr('lat'); var lon = $(this).attr('lon'); var name = $(this).find('name').text(); var cmt = $(this).find('cmt').text(); var desc = $(this).find('desc').text(); var sym = $(this).find('sym').text(); var ele = $(this).find('ele').text(); var time = $(this).find('time').text(); if (ele !== '') { drawMarker([lat, lon, ele], name, desc, cmt, sym, time); } else{ drawMarker([lat, lon], name, desc, cmt, sym, time); } }); dom.find('trk').each(function() { var latlngs = []; var name = $(this).find('>name').text(); var cmt = $(this).find('>cmt').text(); var desc = $(this).find('>desc').text(); var times = []; $(this).find('trkseg').each(function() { $(this).find('trkpt').each(function() { var lat = $(this).attr('lat'); var lon = $(this).attr('lon'); var ele = $(this).find('ele').text(); var time = $(this).find('time').text(); times.push(time); if (ele !== '') { latlngs.push([lat, lon, ele]); } else{ latlngs.push([lat, lon]); } }); }); drawLine(latlngs, name, desc, cmt, 'track', times); }); dom.find('rte').each(function() { var latlngs = []; var name = $(this).find('>name').text(); var cmt = $(this).find('>cmt').text(); var desc = $(this).find('>desc').text(); var times = []; $(this).find('rtept').each(function() { var lat = $(this).attr('lat'); var lon = $(this).attr('lon'); var ele = $(this).find('ele').text(); var time = $(this).find('time').text(); times.push(time); if (ele !== '') { latlngs.push([lat, lon, ele]); } else{ latlngs.push([lat, lon]); } }); drawLine(latlngs, name, desc, cmt, 'route', times); }); } // remove layers from map and delete all layers data function clear() { var i; var layersToRemove = []; gpxedit.editableLayers.eachLayer(function (layer) { layer.unbindTooltip(); delete gpxedit.layersData[layer.gpxedit_id]; layersToRemove.push(layer); }); for(i = 0; i < layersToRemove.length; i++) { gpxedit.editableLayers.removeLayer(layersToRemove[i]); } } /* * get key events */ function checkKey(e) { e = e || window.event; var kc = e.keyCode; console.log(kc); if (kc === 161 || kc === 223) { e.preventDefault(); gpxedit.minimapControl._toggleDisplayButtonClicked(); } if (kc === 60 || kc === 220) { e.preventDefault(); $('#sidebar').toggleClass('collapsed'); } } function showSaveFailAnimation(path, message) { $('#failed').find('b#content').html( t('gpxedit', 'Failed to save file') + ' ' + path + '
' + message ); $('#failed').fadeIn(); setTimeout(hideFailedAnimation, 4000); } function showFailAnimation(message) { $('#failed').find('b#content').html(message); $('#failed').fadeIn(); setTimeout(hideFailedAnimation, 4000); } function hideFailedAnimation() { $('#failed').fadeOut(); } function showSaveSuccessAnimation(path) { $('#saved').find('b#content').html( t('gpxedit', 'File successfully saved as') + '
' + path ); $('#saved').fadeIn(); setTimeout(hideSaveSuccessAnimation, 4000); } function hideSaveSuccessAnimation() { $('#saved').fadeOut(); } function showLoadingAnimation() { $('#loading').show(); } function hideLoadingAnimation() { $('#loading').hide(); } function showExportingAnimation() { $('#exporting').show(); } function hideExportingAnimation() { $('#exporting').hide(); } function showSavingAnimation() { $('#saving').show(); } function hideSavingAnimation() { $('#saving').hide(); } function loadAction(file) { if ( !endsWith(file, '.gpx') && !endsWith(file, '.kml') && !endsWith(file, '.jpg') && !endsWith(file, '.csv') ) { OC.dialogs.alert( t('gpxedit', 'Impossible to load this file. ') + t('gpxedit', 'Supported formats are gpx, kml, csv (unicsv) and jpg.'), t('gpxedit', 'Load error') ); return; } loadFile(file); // set save name var spl = file.split('/'); var basename = spl[spl.length - 1]; $('input#saveName').val( basename.replace(/\.jpg$/, '.gpx') .replace(/\.kml$/, '.gpx') .replace(/\.csv$/, '.gpx') ); } function loadFile(file) { var req = { path: file }; var url = OC.generateUrl('/apps/gpxedit/getgpx'); $('#loadingpc').text('0'); showLoadingAnimation(); gpxedit.currentAjax = $.ajax({ type: 'POST', async: true, url: url, data: req, xhr: function() { var xhr = new window.XMLHttpRequest(); xhr.addEventListener('progress', function(evt) { if (evt.lengthComputable) { var percentComplete = evt.loaded / evt.total * 100; $('#loadingpc').text(parseInt(percentComplete)); } }, false); return xhr; } }).done(function (response) { if ($('#clearbeforeload').is(':checked')) { clear(); } if (response.gpx === '') { OC.dialogs.alert('The file does not exist or it is not supported', 'Load error'); } else{ parseGpx(response.gpx); var bounds = gpxedit.editableLayers.getBounds(); gpxedit.map.fitBounds( bounds, { animate: true, paddingTopLeft: [parseInt($('#sidebar').css('width')), 0] } ); hideLoadingAnimation(); } }); } function deleteTileServer(li) { var sname = li.attr('name'); var req = { servername: sname }; var url = OC.generateUrl('/apps/gpxedit/deleteTileServer'); $.ajax({ type: 'POST', url: url, data: req, async: true }).done(function (response) { //alert(response.done); if (response.done) { li.fadeOut('slow', function() { li.remove(); }); var activeLayerName = gpxedit.activeLayers.getActiveBaseLayer().name; // if we delete the active layer, first select another if (activeLayerName === sname) { $('input.leaflet-control-layers-selector').first().click(); } gpxedit.activeLayers.removeLayer(gpxedit.baseLayers[sname]); delete gpxedit.baseLayers[sname]; OC.Notification.showTemporary( t('gpxedit', 'Tile server "{ts}" has been deleted', {ts: sname}) ); } else{ OC.Notification.showTemporary( t('gpxedit', 'Failure on tile server "{ts}" deletion', {ts: sname}) ); } }).always(function() { }).fail(function() { OC.Notification.showTemporary( t('gpxedit', 'Failure on tile server "{ts}" deletion', {ts: sname}) ); }); } function addTileServer() { var sname = $('#tileservername').val(); var surl = $('#tileserverurl').val(); if (sname === '' || surl === '') { OC.dialogs.alert(t('gpxedit', 'Server name or server url should not be empty'), t('gpxedit', 'Impossible to add tile server')); return; } if ($('#tileserverlist ul li[name="' + sname + '"]').length > 0) { OC.dialogs.alert(t('gpxedit', 'A server with this name already exists'), t('gpxedit', 'Impossible to add tile server')); return; } $('#tileservername').val(''); $('#tileserverurl').val(''); var req = { servername: sname, serverurl: surl }; var url = OC.generateUrl('/apps/gpxedit/addTileServer'); $.ajax({ type: 'POST', url: url, data: req, async: true }).done(function (response) { //alert(response.done); if (response.done) { $('#tileserverlist ul').prepend( '
  • ' + sname + '
  • ' ); $('#tileserverlist ul li[name="' + sname + '"]').fadeIn('slow'); // add tile server in leaflet control var newlayer = new L.TileLayer( surl, { maxZoom: 18, attribution: 'custom tile server' } ); gpxedit.activeLayers.addBaseLayer(newlayer, sname); gpxedit.baseLayers[sname] = newlayer; OC.Notification.showTemporary( t('gpxedit', 'Tile server "{ts}" has been added', {ts: sname}) ); } else{ OC.Notification.showTemporary( t('gpxedit', 'Failure on tile server "{ts}" addition', {ts: sname}) ); } }).always(function() { }).fail(function() { OC.Notification.showTemporary( t('gpxedit', 'Failure on tile server "{ts}" addition', {ts: sname}) ); }); } // affects future markers and also existing ones function updateLeafletDrawMarkerStyle() { var wst = $('#markerstyleselect').val(); var theclass = symbolSelectClasses[wst]; $('#markerstyleselect').removeClass($('#markerstyleselect').attr('class')); $('#markerstyleselect').attr('style', ''); if (theclass) { $('#markerstyleselect').addClass(theclass); } else if (wst !== '') { var url = OC.generateUrl('/apps/gpxedit/getExtraSymbol?'); var fullurl = url + 'name=' + encodeURI(wst + '.png'); $('#markerstyleselect').attr('style', 'background: url(\'' + fullurl + '\') no-repeat ' + 'right 8px center rgba(240, 240, 240, 0.90);' + 'background-size: contain;' ); } var tst = $('#tooltipstyleselect').val(); var theicon = symbolIcons[wst]; gpxedit.drawControl.setDrawingOptions({ marker: { icon: theicon } }); var symboo = $('#symboloverwrite').is(':checked'); gpxedit.editableLayers.eachLayer(function(layer) { var id = layer.gpxedit_id; var name = gpxedit.layersData[id].name; var symbol = gpxedit.layersData[id].symbol; if (layer.type === 'marker') { if ( symboo && symbol !== '' && symbolIcons.hasOwnProperty(symbol) ) { layer.setIcon(symbolIcons[symbol]); } else{ layer.setIcon(theicon); } } if (name !== '') { layer.unbindTooltip(); if (tst === 'p') { layer.bindTooltip(name, {permanent: true}); } else{ layer.bindTooltip(name, {sticky: true}); } } }); } function restoreOptions() { var url = OC.generateUrl('/apps/gpxedit/getOptionsValues'); var req = { }; var optionsValues = '{}'; $.ajax({ type: 'POST', url: url, data: req, async: false }).done(function (response) { optionsValues = response.values; //alert('option values: '+optionsValues); }).fail(function() { OC.dialogs.alert(t('gpxedit', 'failed to restore options values'), t('gpxedit', 'Error')); }); optionsValues = $.parseJSON(optionsValues); if ( optionsValues.markerstyle !== undefined && symbolIcons.hasOwnProperty(optionsValues.markerstyle) ) { $('#markerstyleselect').val(optionsValues.markerstyle); } if (optionsValues.tooltipstyle !== undefined) { $('#tooltipstyleselect').val(optionsValues.tooltipstyle); } if (optionsValues.clearbeforeload !== undefined) { $('#clearbeforeload').prop('checked', optionsValues.clearbeforeload); } if (optionsValues.symboloverwrite !== undefined) { $('#symboloverwrite').prop('checked', optionsValues.symboloverwrite); } if (optionsValues.tilelayer !== undefined) { gpxedit.restoredTileLayer = optionsValues.tilelayer; } } function saveOptions() { var optionsValues = {}; optionsValues.markerstyle = $('#markerstyleselect').val(); optionsValues.tooltipstyle = $('#tooltipstyleselect').val(); optionsValues.clearbeforeload = $('#clearbeforeload').is(':checked'); optionsValues.symboloverwrite = $('#symboloverwrite').is(':checked'); optionsValues.tilelayer = gpxedit.activeLayers.getActiveBaseLayer().name; //alert('to save: '+JSON.stringify(optionsValues)); var req = { optionsValues: JSON.stringify(optionsValues) }; var url = OC.generateUrl('/apps/gpxedit/saveOptionsValues'); $.ajax({ type: 'POST', url: url, data: req, async: true }).done(function (response) { //alert(response); }).fail(function() { OC.dialogs.alert(t('gpxedit', 'failed to save options values'), t('gpxedit', 'Error')); }); } function fillWaypointStyles() { for (var st in symbolIcons) { $('select#markerstyleselect').append( '' ); } $('select#markerstyleselect').val('marker'); } function addExtraSymbols() { var url = OC.generateUrl('/apps/gpxedit/getExtraSymbol?'); $('ul#extrasymbols li').each(function() { var name = $(this).attr('name'); var smallname = $(this).html(); var fullurl = url + 'name=' + encodeURI(name); var d = L.icon({ iconUrl: fullurl, iconSize: L.point(24, 24), iconAnchor: [12, 12] }); symbolIcons[smallname] = d; }); } function saveAction(targetPath) { showExportingAnimation(); var saveFilePath = targetPath + '/' + $('input#saveName').val(); var gpxText = generateGpx(); hideExportingAnimation(); $('#savingpc').text('0'); showSavingAnimation(); var req = { path: saveFilePath, content: gpxText }; var url = OC.generateUrl('/apps/gpxedit/savegpx'); $.ajax({ type: 'POST', async: true, url: url, data: req, xhr: function() { var xhr = new window.XMLHttpRequest(); xhr.upload.addEventListener('progress', function(evt) { if (evt.lengthComputable) { var percentComplete = evt.loaded / evt.total * 100; //Do something with upload progress here $('#savingpc').text(parseInt(percentComplete)); } }, false); return xhr; } }).done(function (response) { hideSavingAnimation(); if (response.status === 'fiw') { showSaveFailAnimation( saveFilePath, t('gpxedit', 'Impossible to write file') + ' : ' + t('gpxedit', 'write access denied') ); } else if (response.status === 'fu') { showSaveFailAnimation( saveFilePath, t('gpxedit', 'Impossible to write file') + ' : ' + t('gpxedit', 'folder does not exist') ); } else if (response.status === 'fw') { showSaveFailAnimation( saveFilePath, t('gpxedit', 'Impossible to write file') + ' : ' + t('gpxedit', 'folder write access denied') ); } else if (response.status === 'bfn') { showSaveFailAnimation( saveFilePath, t('gpxedit', 'Bad file name, must end with ".gpx"') ); } else{ showSaveSuccessAnimation(saveFilePath); } }); } $(document).ready(function() { gpxedit.username = $('p#username').html(); document.onkeydown = checkKey; addExtraSymbols(); fillWaypointStyles(); restoreOptions(); load_map(); $('select#markerstyleselect').change(function(e) { updateLeafletDrawMarkerStyle(); saveOptions(); }); $('select#tooltipstyleselect').change(function(e) { updateLeafletDrawMarkerStyle(); saveOptions(); }); $('body').on('change', '#symboloverwrite', function() { updateLeafletDrawMarkerStyle(); saveOptions(); }); // to set the draw style updateLeafletDrawMarkerStyle(); $('body').on('change', '#clearbeforeload', function() { saveOptions(); }); $('body').on('click', 'button.popupOkButton', function(e) { var id = parseInt($(this).attr('layerid')); var name = $(this).parent().find('.layerName').val(); var description = $(this).parent().find('.layerDesc').val(); var comment = $(this).parent().find('.layerCmt').val(); var symbol = $(this).parent().find('select[role=symbol]').val(); var wst = $('#markerstyleselect').val(); var tst = $('#tooltipstyleselect').val(); var symboo = $('#symboloverwrite').is(':checked'); var type = gpxedit.layersData[id].layer.type; gpxedit.layersData[id].name = name; gpxedit.layersData[id].description = description; gpxedit.layersData[id].comment = comment; if (symbol !== 'unknown') { gpxedit.layersData[id].symbol = symbol; } gpxedit.layersData[id].layer.unbindTooltip(); if (type === 'marker') { if (symbol === 'unknown') { // pass } else if ( symboo && symbol !== '' && symbolIcons.hasOwnProperty(symbol) ) { gpxedit.layersData[id].layer.setIcon(symbolIcons[symbol]); } else{ var theicon = symbolIcons[wst]; gpxedit.layersData[id].layer.setIcon(theicon); } var lat = $(this).parent().find('.layerLat').val(); var lon = $(this).parent().find('.layerLon').val(); var latlng = L.latLng(lat, lon); gpxedit.layersData[id].layer.setLatLng(latlng); } if (name !== '') { if (tst === 'p') { gpxedit.layersData[id].layer.bindTooltip( name, {permanent: true} ); } else{ gpxedit.layersData[id].layer.bindTooltip( name, {sticky: true} ); } } gpxedit.map.closePopup(); }); $('button#clearButton').click(function(e) { clear(); }); $('button#loadButton').click(function(e) { if (gpxedit.currentAjax !== null) { gpxedit.currentAjax.abort(); hideLoadingAnimation(); } OC.dialogs.filepicker( t('gpxedit', 'Load file (gpx, kml, csv, png)'), function(targetPath) { loadAction(targetPath); }, false, null, true ); }); $('button#saveButton').click(function(e) { if (gpxedit.editableLayers.getLayers().length === 0) { showFailAnimation(t('gpxedit', 'There is nothing to save')); } else{ var filename = $('#saveName').val(); OC.dialogs.filepicker( t('gpxedit', 'Where to save') + ' ' + filename + '', function(targetPath) { saveAction(targetPath); }, false, "httpd/unix-directory", true ); } }); // Custom tile server management $('body').on('click', '#tileserverlist button', function(e) { deleteTileServer($(this).parent()); }); $('#addtileserver').click(function() { addTileServer(); }); $('body').on('change', 'select[role=symbol]', function() { $(this).removeClass($(this).attr('class')); $(this).attr('style', ''); if (symbolSelectClasses.hasOwnProperty($(this).val())) { $(this).addClass(symbolSelectClasses[$(this).val()]); } else if ($(this).val() !== '') { var url = OC.generateUrl('/apps/gpxedit/getExtraSymbol?'); var fullurl = url + 'name=' + encodeURI($(this).val() + '.png'); $(this).attr('style', 'background: url(\'' + fullurl + '\') no-repeat ' + 'right 8px center rgba(240, 240, 240, 0.90);' + 'background-size: contain;' ); } }); // load a file if 'file' GET url parameter was given var fileparam = getUrlParameter('file'); if (fileparam && fileparam !== undefined) { loadAction(fileparam); } }); })(jQuery, OC);