Gaia GPS Upload Greasemonkey Script
This commit is contained in:
545
script/gaia_upload.js
Normal file
545
script/gaia_upload.js
Normal file
@@ -0,0 +1,545 @@
|
||||
// ==UserScript==
|
||||
// @name GaiaGps Uploader v2
|
||||
// @version 2.0
|
||||
// @grant none
|
||||
// @match https://www.gaiagps.com/upload/
|
||||
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.5.0/jquery.min.js
|
||||
// ==/UserScript==
|
||||
|
||||
var gpxParser = function () {
|
||||
this.xmlSource = "";
|
||||
this.metadata = {};
|
||||
this.waypoints = [];
|
||||
this.tracks = [];
|
||||
this.routes = [];
|
||||
};
|
||||
|
||||
gpxParser.prototype.parse = function (gpxstring) {
|
||||
var keepThis = this;
|
||||
var domParser = new window.DOMParser();
|
||||
this.xmlSource = domParser.parseFromString(gpxstring, 'text/xml');
|
||||
|
||||
metadata = this.xmlSource.querySelector('metadata');
|
||||
if(metadata != null){
|
||||
this.metadata.name = this.getElementValue(metadata, "name");
|
||||
this.metadata.desc = this.getElementValue(metadata, "desc");
|
||||
this.metadata.time = this.getElementValue(metadata, "time");
|
||||
|
||||
let author = {};
|
||||
let authorElem = metadata.querySelector('author');
|
||||
if(authorElem != null){
|
||||
author.name = this.getElementValue(authorElem, "name");
|
||||
author.email = {};
|
||||
let emailElem = authorElem.querySelector('email');
|
||||
if(emailElem != null){
|
||||
author.email.id = emailElem.getAttribute("id");
|
||||
author.email.domain = emailElem.getAttribute("domain");
|
||||
}
|
||||
|
||||
let link = {};
|
||||
let linkElem = authorElem.querySelector('link');
|
||||
if(linkElem != null){
|
||||
link.href = linkElem.getAttribute('href');
|
||||
link.text = this.getElementValue(linkElem, "text");
|
||||
link.type = this.getElementValue(linkElem, "type");
|
||||
}
|
||||
author.link = link;
|
||||
}
|
||||
this.metadata.author = author;
|
||||
|
||||
let link = {};
|
||||
let linkElem = this.queryDirectSelector(metadata, 'link');
|
||||
if(linkElem != null){
|
||||
link.href = linkElem.getAttribute('href');
|
||||
link.text = this.getElementValue(linkElem, "text");
|
||||
link.type = this.getElementValue(linkElem, "type");
|
||||
this.metadata.link = link;
|
||||
}
|
||||
}
|
||||
|
||||
var wpts = [].slice.call(this.xmlSource.querySelectorAll('wpt'));
|
||||
for (let idx in wpts){
|
||||
var wpt = wpts[idx];
|
||||
let pt = {};
|
||||
pt.name = keepThis.getElementValue(wpt, "name")
|
||||
pt.lat = parseFloat(wpt.getAttribute("lat"));
|
||||
pt.lon = parseFloat(wpt.getAttribute("lon"));
|
||||
pt.ele = parseFloat(keepThis.getElementValue(wpt, "ele")) || null;
|
||||
pt.cmt = keepThis.getElementValue(wpt, "cmt");
|
||||
pt.desc = keepThis.getElementValue(wpt, "desc");
|
||||
pt.sym = keepThis.getElementValue(wpt, "sym");
|
||||
keepThis.waypoints.push(pt);
|
||||
}
|
||||
|
||||
var rtes = [].slice.call(this.xmlSource.querySelectorAll('rte'));
|
||||
for (let idx in rtes){
|
||||
var rte = rtes[idx];
|
||||
let route = {};
|
||||
route.name = keepThis.getElementValue(rte, "name");
|
||||
route.cmt = keepThis.getElementValue(rte, "cmt");
|
||||
route.desc = keepThis.getElementValue(rte, "desc");
|
||||
route.src = keepThis.getElementValue(rte, "src");
|
||||
route.number = keepThis.getElementValue(rte, "number");
|
||||
|
||||
let type = keepThis.queryDirectSelector(rte, "type");
|
||||
route.type = type != null ? type.innerHTML : null;
|
||||
|
||||
let link = {};
|
||||
let linkElem = rte.querySelector('link');
|
||||
if(linkElem != null){
|
||||
link.href = linkElem.getAttribute('href');
|
||||
link.text = keepThis.getElementValue(linkElem, "text");
|
||||
link.type = keepThis.getElementValue(linkElem, "type");
|
||||
}
|
||||
route.link = link;
|
||||
|
||||
let routepoints = [];
|
||||
var rtepts = [].slice.call(rte.querySelectorAll('rtept'));
|
||||
|
||||
for (let idxIn in rtepts){
|
||||
var rtept = rtepts[idxIn];
|
||||
let pt = {};
|
||||
pt.lat = parseFloat(rtept.getAttribute("lat"));
|
||||
pt.lon = parseFloat(rtept.getAttribute("lon"));
|
||||
pt.ele = parseFloat(keepThis.getElementValue(rtept, "ele"));
|
||||
routepoints.push(pt);
|
||||
}
|
||||
|
||||
route.points = routepoints;
|
||||
keepThis.routes.push(route);
|
||||
}
|
||||
|
||||
var trks = [].slice.call(this.xmlSource.querySelectorAll('trk'));
|
||||
for (let idx in trks){
|
||||
var trk = trks[idx];
|
||||
let track = {};
|
||||
|
||||
track.name = keepThis.getElementValue(trk, "name");
|
||||
track.cmt = keepThis.getElementValue(trk, "cmt");
|
||||
track.desc = keepThis.getElementValue(trk, "desc");
|
||||
track.src = keepThis.getElementValue(trk, "src");
|
||||
track.number = keepThis.getElementValue(trk, "number");
|
||||
track.color = keepThis.getElementValue(trk, "DisplayColor");
|
||||
|
||||
let type = keepThis.queryDirectSelector(trk, "type");
|
||||
|
||||
let link = {};
|
||||
let linkElem = trk.querySelector('link');
|
||||
if(linkElem != null){
|
||||
link.href = linkElem.getAttribute('href');
|
||||
link.text = keepThis.getElementValue(linkElem, "text");
|
||||
link.type = keepThis.getElementValue(linkElem, "type");
|
||||
}
|
||||
track.link = link;
|
||||
|
||||
let trackpoints = [];
|
||||
var trkpts = [].slice.call(trk.querySelectorAll('trkpt'));
|
||||
for (let idxIn in trkpts){
|
||||
var trkpt = trkpts[idxIn];
|
||||
let pt = {};
|
||||
pt.lat = parseFloat(trkpt.getAttribute("lat"));
|
||||
pt.lon = parseFloat(trkpt.getAttribute("lon"));
|
||||
pt.ele = parseFloat(keepThis.getElementValue(trkpt, "ele")) || null;
|
||||
trackpoints.push(pt);
|
||||
}
|
||||
track.points = trackpoints;
|
||||
|
||||
keepThis.tracks.push(track);
|
||||
}
|
||||
};
|
||||
|
||||
gpxParser.prototype.getElementValue = function(parent, needle){
|
||||
let elem = parent.querySelector(needle);
|
||||
if(elem != null){
|
||||
return elem.innerHTML != undefined ? elem.innerHTML : elem.childNodes[0].data;
|
||||
}
|
||||
return elem;
|
||||
}
|
||||
|
||||
gpxParser.prototype.queryDirectSelector = function(parent, needle) {
|
||||
|
||||
let elements = parent.querySelectorAll(needle);
|
||||
let finalElem = elements[0];
|
||||
|
||||
if(elements.length > 1) {
|
||||
let directChilds = parent.childNodes;
|
||||
|
||||
for(idx in directChilds) {
|
||||
elem = directChilds[idx];
|
||||
if(elem.tagName === needle) {
|
||||
finalElem = elem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return finalElem;
|
||||
}
|
||||
|
||||
gpxParser.prototype.getGPX = function(sName) {
|
||||
var sTrack = '';
|
||||
|
||||
for(var i=0 ; i < this.tracks.length ; i++) {
|
||||
var sTrkSeg = '';
|
||||
for(var j=0 ; j < this.tracks[i].points.length ; j++) {
|
||||
sTrkSeg += '<trkpt lat="'+this.tracks[i].points[j].lat+'" lon="'+this.tracks[i].points[j].lon+'">'+
|
||||
'<ele>'+(this.tracks[i].points[j].ele || '')+'</ele>'+
|
||||
'</trkpt>';
|
||||
}
|
||||
sTrack += '<trk>'+
|
||||
'<name>'+(this.tracks[i].name || '')+'</name>'+
|
||||
'<desc>'+(this.tracks[i].desc || '')+'</desc>'+
|
||||
'<src>'+(this.tracks[i].src || '')+'</src>'+
|
||||
'<trkseg>'+sTrkSeg+'</trkseg>'+
|
||||
'</trk>';
|
||||
}
|
||||
|
||||
var sGPX = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>'+
|
||||
'<gpx version="1.1" creator="Franzz" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">'+
|
||||
'<metadata><name>'+sName+'</name></metadata>'+
|
||||
sTrack+
|
||||
'</gpx>';
|
||||
|
||||
return sGPX;
|
||||
};
|
||||
|
||||
class Gaia {
|
||||
static get URL() { return 'https://www.gaiagps.com'; }
|
||||
static get API() { return Gaia.URL+'/api/objects'; }
|
||||
|
||||
constructor($Form) {
|
||||
this.aoWaypoints = [];
|
||||
this.aoTracks = [];
|
||||
this.sFolderId = '';
|
||||
this.sFolderName = '';
|
||||
|
||||
this.$Form = $Form;
|
||||
this.$InputName = $Form.find('input[name=name]');
|
||||
this.$InputFile = $Form.find('input[type=file]');
|
||||
this.$Feedback = $Form.after($('<div>'));
|
||||
this.setLayout();
|
||||
}
|
||||
|
||||
feedback(sType, sMsg) {
|
||||
var sFormattedMsg = sType.charAt(0).toUpperCase()+sType.slice(1)+': '+sMsg+'.';
|
||||
console.log(sFormattedMsg);
|
||||
|
||||
let sColor = 'black';
|
||||
switch(sType) {
|
||||
case 'error': sColor = 'red'; break;
|
||||
case 'warning': sColor = 'orange'; break;
|
||||
case 'info': sColor = 'green'; break;
|
||||
}
|
||||
this.$Feedback.append($('<p>', {'style': 'color: '+sColor+';'}).text(sFormattedMsg));
|
||||
}
|
||||
|
||||
//Modify Gaia DOM Interface
|
||||
setLayout() {
|
||||
//Set event on file selection
|
||||
this.$InputFile
|
||||
.attr('multiple', 'multiple')
|
||||
.attr('name', 'files[]')
|
||||
.change(() => {this.readInputFiles();});
|
||||
|
||||
//Remove submit button & edit label
|
||||
this.$Form.find('#fileuploadtext').text('Select files');
|
||||
this.$Form.find('button[type=submit]').hide();
|
||||
|
||||
//Set default Name
|
||||
this.$InputName.val('PCT');
|
||||
|
||||
//Clear all upload notifications
|
||||
this.resetNotif();
|
||||
}
|
||||
|
||||
//Parse files from input (multiple)
|
||||
readInputFiles() {
|
||||
if (!window.File || !window.FileReader || !window.FileList || !window.Blob) {
|
||||
this.feedback('error', 'File APIs are not fully supported in this browser');
|
||||
return;
|
||||
}
|
||||
else this.feedback('info', 'Parsing input files');
|
||||
|
||||
//Get Folder Name (text input)
|
||||
this.sFolderName = this.$InputName.val();
|
||||
|
||||
let aoReaders = [];
|
||||
let asFiles = this.$InputFile.prop('files');
|
||||
let asContents = [];
|
||||
for(var i=0 ; i < asFiles.length ; i++) {
|
||||
aoReaders[i] = new FileReader();
|
||||
aoReaders[i].onload = ((asResult) => {
|
||||
asContents.push(asResult.target.result);
|
||||
this.feedback('info', 'Reading file '+asContents.length+'/'+asFiles.length);
|
||||
if(asContents.length == asFiles.length) this.parseFile(asContents);
|
||||
});
|
||||
aoReaders[i].readAsText(asFiles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//Parse GPX files to consolidate tracks & waypoints
|
||||
parseFile(asContents) {
|
||||
this.feedback('info', 'Merging files');
|
||||
for(var i in asContents) {
|
||||
var oGPX = new gpxParser();
|
||||
oGPX.parse(asContents[i]);
|
||||
|
||||
//Waypoints
|
||||
for(var w in oGPX.waypoints) {
|
||||
var sWaypointName = oGPX.waypoints[w].name;
|
||||
if(sWaypointName.indexOf('Milestone - ') != -1 && sWaypointName.substr(-2) != '00') { //1 milestone every 100 miles
|
||||
this.feedback('info', 'Ignoring milestone waypoint "'+sWaypointName+'"');
|
||||
}
|
||||
else this.aoWaypoints.push(oGPX.waypoints[w]);
|
||||
}
|
||||
|
||||
//Tracks
|
||||
for(var t in oGPX.tracks) {
|
||||
this.aoTracks.push(oGPX.tracks[t]);
|
||||
}
|
||||
}
|
||||
|
||||
this.deleteFolder();
|
||||
}
|
||||
|
||||
//Delete existing folder with same name
|
||||
deleteFolder() {
|
||||
this.feedback('info', 'Looking for existing "'+this.sFolderName+'" folder...');
|
||||
|
||||
$.get(Gaia.API+'/folder/?routepoints=false&show_archived=true&show_filed=true').done((asFolders) => {
|
||||
var bCalled = false;
|
||||
for(var f in asFolders) {
|
||||
if(asFolders[f].title == this.sFolderName) {
|
||||
bCalled = true;
|
||||
this.feedback('info', 'Deleting "'+this.sFolderName+'" folder');
|
||||
$.ajax({
|
||||
url: Gaia.API+'/folder/'+asFolders[f].id+'/',
|
||||
type: 'DELETE'
|
||||
});
|
||||
}
|
||||
}
|
||||
if(!bCalled) this.feedback('info', 'No folder named "'+this.sFolderName+'" found');
|
||||
|
||||
this.uploadTrack();
|
||||
});
|
||||
}
|
||||
|
||||
//Marking all upload notifications as read
|
||||
resetNotif() {
|
||||
this.feedback('info', 'Marking all upload notifications as read');
|
||||
$.get(Gaia.URL+'/social/notifications/popup/').done((asNotifs) => {
|
||||
for(var i in asNotifs) {
|
||||
if(!asNotifs[i].isViewed && asNotifs[i].html.indexOf('has completed') != -1) {
|
||||
$.post(Gaia.URL+'/social/notifications/'+asNotifs[i].id+'/markviewed/');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//Build & Upload Track File
|
||||
uploadTrack() {
|
||||
//Build track file
|
||||
this.feedback('info', 'Building consolidated track');
|
||||
var oGPX = new gpxParser();
|
||||
oGPX.tracks = this.aoTracks;
|
||||
var sTrack = oGPX.getGPX(this.sFolderName);
|
||||
|
||||
//Send consolidated Tracks as one file
|
||||
var oForm = new FormData();
|
||||
oForm.append('name', this.sFolderName);
|
||||
oForm.append('files', new Blob([sTrack]), 'Consolidated.gpx');
|
||||
|
||||
this.feedback('info', 'Uploading consolidated track');
|
||||
$.ajax({
|
||||
url: Gaia.URL+'/upload/',
|
||||
type: 'POST',
|
||||
data: oForm,
|
||||
enctype: 'multipart/form-data',
|
||||
processData: false,
|
||||
contentType: false,
|
||||
cache: false
|
||||
}).done(() => {this.checkNotif();});
|
||||
}
|
||||
|
||||
//Wait for file to be processed by Gaia
|
||||
checkNotif() {
|
||||
this.feedback('info', 'Waiting for Gaia to process consolidated track');
|
||||
$.get(Gaia.URL+'/social/notifications/popup/').done((asNotifs) => {
|
||||
for(var i in asNotifs) {
|
||||
if(!asNotifs[i].isViewed && asNotifs[i].html.indexOf('has completed') != -1) {
|
||||
this.feedback('info', 'Notification '+asNotifs[i].id+' found. Marking as read');
|
||||
var $Notif = $('<span>').html(asNotifs[i].html);
|
||||
this.sFolderId = $Notif.find('a').attr('href').split('/')[3];
|
||||
$.post(Gaia.URL+'/social/notifications/'+asNotifs[i].id+'/markviewed/');
|
||||
}
|
||||
}
|
||||
|
||||
if(this.sFolderId != '') {
|
||||
this.setTracksColor();
|
||||
this.uploadWayPoints();
|
||||
}
|
||||
else setTimeout((() => {this.checkNotif();}), 1000);
|
||||
});
|
||||
}
|
||||
|
||||
//Convert QMapshack Track Colors into Gaia Colors
|
||||
setTracksColor() {
|
||||
this.feedback('info', 'Track Color - Matching Gaia track IDs with GPX tracks');
|
||||
var iCount = 0;
|
||||
|
||||
$.get(Gaia.API+'/folder/'+this.sFolderId+'/').done((asFolder) => {
|
||||
var self = this;
|
||||
for(var iGaiaIndex in asFolder.properties.tracks) {
|
||||
for(var iGpxIndex in this.aoTracks) {
|
||||
if(asFolder.properties.tracks[iGaiaIndex].title == this.aoTracks[iGpxIndex].name) {
|
||||
this.aoTracks[iGpxIndex].id = asFolder.properties.tracks[iGaiaIndex].id;
|
||||
this.feedback('info', 'Track Color - Track "'+this.aoTracks[iGpxIndex].name+'" found a match ('+(++iCount)+'/'+this.aoTracks.length+')');
|
||||
|
||||
$.ajax({
|
||||
url: Gaia.API+'/track/'+this.aoTracks[iGpxIndex].id+'/',
|
||||
color: this.aoTracks[iGpxIndex].color
|
||||
}).done(function(asGaiaTrackDisplay) {
|
||||
var asGaiaTrack = asGaiaTrackDisplay.features[0];
|
||||
delete asGaiaTrack.id;
|
||||
delete asGaiaTrack.style;
|
||||
|
||||
//Set color
|
||||
var sColor = '#ff0000';
|
||||
switch(this.color) {
|
||||
case 'DarkBlue': sColor = '#2D3FC7'; break;
|
||||
case 'Magenta': sColor = '#B60DC3'; break;
|
||||
}
|
||||
asGaiaTrack.properties.color = sColor;
|
||||
asGaiaTrack.properties.hexcolor = sColor;
|
||||
|
||||
self.feedback('info', 'Track Color - Setting track color "'+sColor+'" ('+this.color+') to "'+asGaiaTrack.properties.title+'"');
|
||||
$.ajax({
|
||||
url: Gaia.API+'/track/'+asGaiaTrack.properties.id+'/',
|
||||
type: 'PUT',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(asGaiaTrack)
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
uploadWayPoints(iIndex, bSecondTry) {
|
||||
iIndex = iIndex || 0;
|
||||
bSecondTry = bSecondTry || false;
|
||||
|
||||
//Upload waypoints
|
||||
if(iIndex < this.aoWaypoints.length) {
|
||||
var sWaypointName = this.aoWaypoints[iIndex].name;
|
||||
|
||||
this.feedback('info', 'Waypoints Upload - Uploading waypoint '+(iIndex + 1)+'/'+this.aoWaypoints.length+' ('+sWaypointName+')');
|
||||
var asPost = {
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [
|
||||
this.aoWaypoints[iIndex].lon,
|
||||
this.aoWaypoints[iIndex].lat,
|
||||
this.aoWaypoints[iIndex].ele
|
||||
]
|
||||
},
|
||||
properties: {
|
||||
title: sWaypointName,
|
||||
time_created: "2020-06-07T14:01:03.944Z",
|
||||
icon: Gaia.getIconName(this.aoWaypoints[iIndex].sym),
|
||||
writable: true,
|
||||
localId: iIndex+'',
|
||||
archived: false,
|
||||
isTitleLoaded: true,
|
||||
isLocallyCreated: true,
|
||||
type: 'waypoint'
|
||||
}
|
||||
};
|
||||
if(this.aoWaypoints[iIndex].desc) asPost.properties.notes = this.aoWaypoints[iIndex].desc;
|
||||
|
||||
$.ajax({
|
||||
url: Gaia.API+'/waypoint/',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(asPost)
|
||||
}).done((asWaypoint) => {
|
||||
//Update local waypoint with all server info (including ID)
|
||||
this.aoWaypoints[iIndex] = asWaypoint;
|
||||
|
||||
$.get(Gaia.URL+'/public/generate?type=waypoint&objectid='+asWaypoint.properties.id).always(() => {
|
||||
this.uploadWayPoints(++iIndex);
|
||||
});
|
||||
}).fail(function(){
|
||||
this.feedback('error', 'Waypoints Upload - Failed to upload waypoint #'+(iIndex + 1)+' ('+sWaypointName+'). Trying again...');
|
||||
this.uploadWayPoints(iIndex, true);
|
||||
});
|
||||
}
|
||||
|
||||
//Done uploading, assigning waypoints to folder
|
||||
else {
|
||||
this.feedback('info', 'Waypoints Upload - Getting folders list');
|
||||
$.get(Gaia.API+'/folder/').done((asFolders) => {
|
||||
//Find Folder
|
||||
for(var f in asFolders) {
|
||||
if(asFolders[f].id == this.sFolderId) {
|
||||
var asFolder = asFolders[f];
|
||||
}
|
||||
}
|
||||
|
||||
//Assign waypoints to folder
|
||||
for(var i in this.aoWaypoints) asFolder.waypoints.push(this.aoWaypoints[i].properties.id);
|
||||
|
||||
this.feedback('info', 'Waypoints Upload - Assigning waypoints to folder '+this.sFolderId);
|
||||
$.ajax({
|
||||
url: Gaia.API+'/folder/'+this.sFolderId+'/',
|
||||
type: 'PUT',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(asFolder)
|
||||
}).done(() => {
|
||||
this.feedback('info', 'Waypoints Upload - Finished successfully');
|
||||
}).fail(() => {
|
||||
this.feedback('error', 'Waypoints Upload - Failed to assign waypoints to folder "'+sFolderId+'"');
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static getIconName(sGarminName) {
|
||||
var asMapping = {
|
||||
'Trail Head': 'trailhead',
|
||||
'Water Source': 'water-24.png',
|
||||
'Truck': 'car-24.png',
|
||||
'Post Office': 'resupply',
|
||||
'Flag, Blue': 'blue-pin-down.png',
|
||||
'Car': 'car-24.png',
|
||||
'Flag, Red': 'red-pin-down.png',
|
||||
'Campground': 'campsite-24.png',
|
||||
'Flag, Green': 'green-pin.png',
|
||||
'Powerline': 'petroglyph',
|
||||
'Shopping Center': 'cafe-24.png',
|
||||
'Lodging': 'lodging-24.png',
|
||||
'Water Hydrant': 'red-pin-down.png',
|
||||
'Drinking Water': 'potable-water',
|
||||
'Toll Booth': 'ranger-station',
|
||||
'Summit': 'peak',
|
||||
'Park': 'park-24.png',
|
||||
'Forest': 'forest',
|
||||
'Cemetery': 'cemetery-24.png',
|
||||
'Bridge': 'dam-24.png',
|
||||
'Restaurant': 'restaurant-24.png',
|
||||
'Picnic Area': 'picnic',
|
||||
'Residence': 'city-24.png',
|
||||
'City (Capitol)': 'city-24.png',
|
||||
'Ski Resort': 'skiing-24.png',
|
||||
'Restroom': 'toilets-24.png',
|
||||
'Ground Transportation': 'car-24.png',
|
||||
'Church': 'ghost-town'
|
||||
};
|
||||
return (sGarminName in asMapping)?asMapping[sGarminName]:'red-pin-down.png';
|
||||
}
|
||||
}
|
||||
|
||||
console.log('computes');
|
||||
|
||||
let oGaia = new Gaia($('#uploadForm'));
|
||||
Reference in New Issue
Block a user