1 if (Garmin == undefined) var Garmin = {}; 2 /** 3 * Copyright � 2007 Garmin Ltd. or its subsidiaries. 4 * 5 * Licensed under the Apache License, Version 2.0 (the 'License') 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an 'AS IS' BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 * @fileoverview Garmin.GpxActivityFactory - A factory for producing gpx activity and data. 18 * 19 * @author Bobby Yang bobby.yang.at.garmin.com 20 * @version 1.0 21 */ 22 /**A factory that can produce an array activity given gpx xml and produce gps xml given an 23 * array of activity. 24 * many other types of data. 25 * @class Garmin.GpxActivityFactory 26 * @constructor 27 */ 28 Garmin.GpxActivityFactory = function(){}; 29 Garmin.GpxActivityFactory = { 30 31 parseString: function(gpxString) { 32 var gpxDocument = Garmin.XmlConverter.toDocument(gpxString); 33 return Garmin.GpxActivityFactory.parseDocument(gpxDocument); 34 }, 35 36 parseDocument: function(gpxDocument) { 37 return this.parseDocumentByType(gpxDocument, Garmin.GpxActivityFactory.GPX_TYPE.all); 38 }, 39 40 parseDocumentByType: function(gpxDocument, type) { 41 var activities = new Array(); 42 var routes = new Array(); 43 var tracks = new Array(); 44 var waypoints = new Array(); 45 46 switch(type) { 47 case Garmin.GpxActivityFactory.GPX_TYPE.routes: 48 activities = Garmin.GpxActivityFactory._parseGpxRoutes(gpxDocument); 49 break; 50 case Garmin.GpxActivityFactory.GPX_TYPE.waypoints: 51 activities = Garmin.GpxActivityFactory._parseGpxWaypoints(gpxDocument); 52 break; 53 case Garmin.GpxActivityFactory.GPX_TYPE.tracks: 54 activities = Garmin.GpxActivityFactory._parseGpxTracks(gpxDocument); 55 break; 56 case Garmin.GpxActivityFactory.GPX_TYPE.all: 57 routes = Garmin.GpxActivityFactory._parseGpxRoutes(gpxDocument); 58 tracks = Garmin.GpxActivityFactory._parseGpxTracks(gpxDocument); 59 waypoints = Garmin.GpxActivityFactory._parseGpxWaypoints(gpxDocument); 60 activities = waypoints.concat(routes).concat(tracks); 61 break; 62 } 63 64 return activities; 65 }, 66 67 produceString: function(activities) { 68 var gpxString = ""; 69 70 // default creator information incase we can't find the creator info in the dom 71 var creator = Garmin.GpxActivityFactory.DETAIL.creator; 72 73 // default metadata information incase we can't find the metadata node in the dom 74 var metadata = "\n <metadata>"; 75 metadata += "\n <link href=\"http://www.garmin.com\">"; 76 metadata += "\n <text>Garmin International</text>"; 77 metadata += "\n </link>"; 78 metadata += "\n </metadata>"; 79 80 // try to find creator and metadata info in the dom 81 if (activities != null && activities.length > 0) { 82 var activityDom = activities[0].getAttribute(Garmin.Activity.ATTRIBUTE_KEYS.dom); 83 var gpxNode = activityDom.ownerDocument.getElementsByTagName(Garmin.GpxActivityFactory.SCHEMA_TAGS.gpx); 84 if (gpxNode.length > 0) { 85 // grab creator information from the dom if possible 86 var creatorStr = gpxNode[0].getAttribute(Garmin.GpxActivityFactory.SCHEMA_TAGS.creator); 87 if (creatorStr != null && creatorStr != "") { 88 creator = creatorStr; 89 } 90 // grab metadata info 91 var metadataNode = gpxNode[0].getElementsByTagName(Garmin.GpxActivityFactory.SCHEMA_TAGS.metadata); 92 if (metadataNode.length > 0) { 93 metadata = Garmin.XmlConverter.toString(metadataNode[0]); 94 } 95 } 96 } 97 98 // header tags 99 gpxString += "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>"; 100 gpxString += "\n<gpx xmlns=\"http://www.topografix.com/GPX/1/1\" creator=\"" + creator + "\" version=\"1.1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensions/v3/GpxExtensionsv3.xsd\">"; 101 102 //metadata tag 103 gpxString += "\n " + metadata; 104 105 if (activities != null) { 106 // waypoint and track tags 107 for(var i = 0; i < activities.length; i++) { 108 gpxString += "\n " + Garmin.GpxActivityFactory._produceActivityString(activities[i]); 109 } 110 } 111 112 // footer tags 113 gpxString += "\n</gpx>"; 114 115 return gpxString; 116 }, 117 118 /** Fully load the sample, assume sample was previously lazy-loaded 119 */ 120 finishLoadingSample: function(domNode, sample) { 121 if (domNode.nodeName == Garmin.GpxActivityFactory.SCHEMA_TAGS.routePoint) { 122 Garmin.GpxActivityFactory._parseGpxRoutePoint(domNode, sample); 123 sample.isLazyLoaded = false; 124 } else if (domNode.nodeName == Garmin.GpxActivityFactory.SCHEMA_TAGS.trackPoint) { 125 Garmin.GpxActivityFactory._parseGpxTrackPoint(domNode, sample); 126 sample.isLazyLoaded = false; 127 } 128 }, 129 130 _produceActivityString: function(activity) { 131 var activityString = ""; 132 if (activity != null) { 133 var series = activity.getSeries(); 134 for (var i = 0; i < series.length; i++) { 135 var currentSeries = series[i]; 136 if (currentSeries.getSeriesType() == Garmin.Series.TYPES.history) { 137 // converting the dom back into string 138 // this is the lazy way, this will not work if 139 // converting between file types or activity data 140 // has been modified. 141 var activityDom = activity.getAttribute(Garmin.Activity.ATTRIBUTE_KEYS.dom); 142 if (activityDom != null) { 143 activityString = Garmin.XmlConverter.toString(activityDom); 144 } 145 } else if (currentSeries.getSeriesType() == Garmin.Series.TYPES.waypoint) { 146 // converting the dom back into string 147 // this is the lazy way, this will not work if 148 // converting between file types or activity data 149 // has been modified. 150 var activityDom = activity.getAttribute(Garmin.Activity.ATTRIBUTE_KEYS.dom); 151 if (activityDom != null) { 152 activityString = Garmin.XmlConverter.toString(activityDom); 153 } 154 } 155 } 156 } 157 return activityString; 158 }, 159 160 _parseGpxRoutes: function(gpxDocument) { 161 var routes = new Array(); 162 var routeNodes = gpxDocument.getElementsByTagName(Garmin.GpxActivityFactory.SCHEMA_TAGS.route); 163 164 for( var i=0; i < routeNodes.length; i++ ) { 165 var route = new Garmin.Activity(); 166 167 var routeName = Garmin.GpxActivityFactory._tagValue(routeNodes[i], Garmin.GpxActivityFactory.SCHEMA_TAGS.routeName); 168 if (routeName == null) { 169 routeName = ""; 170 } 171 172 route.setAttribute(Garmin.Activity.ATTRIBUTE_KEYS.dom, routeNodes[i]); 173 route.setAttribute(Garmin.Activity.ATTRIBUTE_KEYS.activityName, routeName); 174 175 var series = new Garmin.Series(Garmin.Series.TYPES.route); 176 route.addSeries(series); 177 178 var routePoints = routeNodes[i].getElementsByTagName(Garmin.GpxActivityFactory.SCHEMA_TAGS.routePoint); 179 if (routePoints.length > 0) { 180 for( var j=0; j < routePoints.length; j++ ) { 181 var routePoint = new Garmin.Sample(); 182 routePoint.setLazyLoading(true, Garmin.GpxActivityFactory, routePoints[j]); 183 series.addSample(routePoint); 184 } 185 } 186 187 if (series.getSamplesLength() > 0) { 188 routes.push(route); 189 } 190 } 191 192 return routes; 193 }, 194 195 _parseGpxRoutePoint: function(routePointNode, routePointSample) { 196 if (routePointSample == null) { 197 routePointSample = new Garmin.Sample(); 198 } 199 200 routePointSample.setMeasurement(Garmin.Sample.MEASUREMENT_KEYS.latitude, routePointNode.getAttribute(Garmin.GpxActivityFactory.SCHEMA_TAGS.waypointLatitude)); 201 routePointSample.setMeasurement(Garmin.Sample.MEASUREMENT_KEYS.longitude, routePointNode.getAttribute(Garmin.GpxActivityFactory.SCHEMA_TAGS.waypointLongitude)); 202 203 var elevation = Garmin.GpxActivityFactory._tagValue(routePointNode,Garmin.GpxActivityFactory.SCHEMA_TAGS.waypointElevation); 204 if (elevation != null) { 205 routePointSample.setMeasurement(Garmin.Sample.MEASUREMENT_KEYS.elevation, elevation); 206 } 207 208 return routePointSample; 209 }, 210 211 _parseGpxTracks: function(gpxDocument) { 212 var tracks = new Array(); 213 214 var trackNodes = gpxDocument.getElementsByTagName(Garmin.GpxActivityFactory.SCHEMA_TAGS.track); 215 for( var i=0; i < trackNodes.length; i++ ) { 216 var track = new Garmin.Activity(); 217 218 var trackName = Garmin.GpxActivityFactory._tagValue(trackNodes[i], Garmin.GpxActivityFactory.SCHEMA_TAGS.trackName); 219 if (trackName == null) { 220 trackName = ""; 221 } 222 223 track.setAttribute(Garmin.Activity.ATTRIBUTE_KEYS.dom, trackNodes[i]); 224 track.setAttribute(Garmin.Activity.ATTRIBUTE_KEYS.activityName, trackName); 225 226 var series = new Garmin.Series(Garmin.Series.TYPES.history); 227 track.addSeries(series); 228 229 var trackSegments = trackNodes[i].getElementsByTagName(Garmin.GpxActivityFactory.SCHEMA_TAGS.trackSegment); 230 for( var j=0; j < trackSegments.length; j++ ) { 231 232 // grab all the trackpoints 233 var trackPoints = trackSegments[j].getElementsByTagName(Garmin.GpxActivityFactory.SCHEMA_TAGS.trackPoint); 234 if (trackPoints.length > 0) { 235 236 // set the start and end time summary values 237 var startTime = Garmin.GpxActivityFactory._tagValue(trackPoints[0], Garmin.GpxActivityFactory.SCHEMA_TAGS.waypointTime); 238 var endTime = Garmin.GpxActivityFactory._tagValue(trackPoints[trackPoints.length - 1], Garmin.GpxActivityFactory.SCHEMA_TAGS.waypointTime); 239 if (startTime != null && endTime != null) { 240 track.setSummaryValue(Garmin.Activity.SUMMARY_KEYS.startTime, (new Garmin.DateTimeFormat()).parseXsdDateTime(startTime)); 241 track.setSummaryValue(Garmin.Activity.SUMMARY_KEYS.endTime, (new Garmin.DateTimeFormat()).parseXsdDateTime(endTime)); 242 } else { 243 // can't find timestamps, must be a route reported as a track (GPSMap does this) 244 series.setSeriesType(Garmin.Series.TYPES.route); 245 } 246 247 // loop through all the trackpoints in this segment 248 for( var k=0; k < trackPoints.length; k++ ) { 249 var trackPoint = new Garmin.Sample(); 250 trackPoint.setLazyLoading(true, Garmin.GpxActivityFactory, trackPoints[k]); 251 series.addSample(trackPoint); 252 } 253 254 // add the track to the list of tracks 255 tracks.push(track); 256 } 257 } 258 } 259 260 return tracks; 261 }, 262 263 _parseGpxTrackPoint: function(trackPointNode, trackPointSample) { 264 if (trackPointSample == null) { 265 trackPointSample = new Garmin.Sample(); 266 } 267 268 trackPointSample.setMeasurement(Garmin.Sample.MEASUREMENT_KEYS.latitude, trackPointNode.getAttribute(Garmin.GpxActivityFactory.SCHEMA_TAGS.waypointLatitude)); 269 trackPointSample.setMeasurement(Garmin.Sample.MEASUREMENT_KEYS.longitude, trackPointNode.getAttribute(Garmin.GpxActivityFactory.SCHEMA_TAGS.waypointLongitude)); 270 271 var elevation = Garmin.GpxActivityFactory._tagValue(trackPointNode,Garmin.GpxActivityFactory.SCHEMA_TAGS.waypointElevation); 272 if (elevation != null) { 273 trackPointSample.setMeasurement(Garmin.Sample.MEASUREMENT_KEYS.elevation, elevation); 274 } 275 276 var time = Garmin.GpxActivityFactory._tagValue(trackPointNode, Garmin.GpxActivityFactory.SCHEMA_TAGS.waypointTime); 277 if (time != null) { 278 trackPointSample.setMeasurement(Garmin.Sample.MEASUREMENT_KEYS.time, (new Garmin.DateTimeFormat()).parseXsdDateTime(time)); 279 } 280 281 return trackPointSample; 282 }, 283 284 _parseGpxWaypoints: function(gpxDocument) { 285 var waypoints = new Array(); 286 var waypointNodes = gpxDocument.getElementsByTagName(Garmin.GpxActivityFactory.SCHEMA_TAGS.waypoint); 287 288 for( var i=0; i < waypointNodes.length; i++ ) { 289 waypoints.push(Garmin.GpxActivityFactory._parseGpxWaypoint(waypointNodes[i])); 290 } 291 292 return waypoints; 293 }, 294 295 _parseGpxWaypoint: function(waypointNode) { 296 var waypoint = new Garmin.Activity(); 297 var waypointSeries = new Garmin.Series(Garmin.Series.TYPES.waypoint); 298 var waypointSample = new Garmin.Sample(); 299 300 waypoint.setAttribute(Garmin.Activity.ATTRIBUTE_KEYS.dom, waypointNode); 301 302 waypointSample.setMeasurement(Garmin.Sample.MEASUREMENT_KEYS.latitude, waypointNode.getAttribute(Garmin.GpxActivityFactory.SCHEMA_TAGS.waypointLatitude)); 303 waypointSample.setMeasurement(Garmin.Sample.MEASUREMENT_KEYS.longitude, waypointNode.getAttribute(Garmin.GpxActivityFactory.SCHEMA_TAGS.waypointLongitude)); 304 305 var elevation = Garmin.GpxActivityFactory._tagValue(waypointNode,Garmin.GpxActivityFactory.SCHEMA_TAGS.waypointElevation); 306 if (elevation != null) { 307 waypointSample.setMeasurement(Garmin.Sample.MEASUREMENT_KEYS.elevation, elevation); 308 } 309 310 var wptName = Garmin.GpxActivityFactory._tagValue(waypointNode,Garmin.GpxActivityFactory.SCHEMA_TAGS.waypointName); 311 if (wptName != null) { 312 waypoint.setAttribute(Garmin.Activity.ATTRIBUTE_KEYS.activityName, wptName); 313 } 314 315 waypointSeries.addSample(waypointSample); 316 waypoint.addSeries(waypointSeries); 317 return waypoint; 318 }, 319 320 _tagValue: function(parentNode, tagName) { 321 var subNode = parentNode.getElementsByTagName(tagName); 322 return subNode.length > 0 ? subNode[0].childNodes[0].nodeValue : null; 323 }, 324 325 toString: function() { 326 return "[GpxActivityFactory]"; 327 } 328 }; 329 330 /** Constants defining GPX type 331 */ 332 Garmin.GpxActivityFactory.GPX_TYPE = { 333 routes: "routes", 334 waypoints: "waypoints", 335 tracks: "tracks", 336 all: "all" 337 } 338 339 /** Constants defining details about the factory 340 */ 341 Garmin.GpxActivityFactory.DETAIL = { 342 creator: "Garmin Communicator Plug-In API" 343 }; 344 345 /** Constants defining tags used by the gpx schema. This is used 346 * by the factory when converting between the xml and datastructure. 347 */ 348 Garmin.GpxActivityFactory.SCHEMA_TAGS = { 349 creator: "creator", 350 gpx: "gpx", 351 metadata: "metadata", 352 route: "rte", 353 routeName: "name", 354 routePoint: "rtept", 355 track: "trk", 356 trackName: "name", 357 trackPoint: "trkpt", 358 trackSegment: "trkseg", 359 waypoint: "wpt", 360 waypointComment: "cmt", 361 waypointDGPSAge: "ageofdgpsdata", 362 waypointDGPSID: "dgpsid", 363 waypointDescription: "desc", 364 waypointGeoIdHeight: "geoidheight", 365 waypointHDOP: "hdop", 366 waypointMagVar: "magvar", 367 waypointName: "name", 368 waypointLatitude: "lat", 369 waypointLink: "link", 370 waypointLongitude: "lon", 371 waypointElevation: "ele", 372 waypointPDOP: "pdop", 373 waypointSatellites: "sat", 374 waypointSource: "src", 375 waypointSymbol: "sym", 376 waypointTime: "time", 377 waypointType: "type", 378 waypointVDOP: "vdop" 379 }; 380 /* 381 // Dynamic include of required libraries and check for Prototype 382 // Code taken from scriptaculous 383 // TODO: put this code in a library and reuse is instead of copying it to new files 384 var GpxActivityFactory = { 385 require: function(libraryName) { 386 // inserting via DOM fails in Safari 2.0, so brute force approach 387 document.write('<script type="text/javascript" src="'+libraryName+'"></script>'); 388 }, 389 390 load: function() { 391 if((typeof Prototype=='undefined') || 392 (typeof Element == 'undefined') || 393 (typeof Element.Methods=='undefined') || 394 parseFloat(Prototype.Version.split(".")[0] + "." + 395 Prototype.Version.split(".")[1]) < 1.5) { 396 throw("GpxActivityFactory requires the Prototype JavaScript framework >= 1.5.0"); 397 } 398 399 $A(document.getElementsByTagName("script")) 400 .findAll( 401 function(s) { 402 return (s.src && s.src.match(/GpxActivityFactory\.js(\?.*)?$/)) 403 } 404 ) 405 .each( 406 function(s) { 407 var path = s.src.replace(/GpxActivityFactory\.js(\?.*)?$/,'../../'); 408 var includes = s.src.match(/\?.*load=([a-z,]*)/); 409 var dependencies = 'garmin/util/Util-XmlConverter' + 410 ',garmin/util/Util-DateTimeFormat' + 411 ',garmin/activity/GarminMeasurement' + 412 ',garmin/activity/GarminSample' + 413 ',garmin/activity/GarminSeries' + 414 ',garmin/activity/GarminActivity'; 415 (includes ? includes[1] : dependencies).split(',').each( 416 function(include) { 417 GpxActivityFactory.require(path+include+'.js') 418 } 419 ); 420 } 421 ); 422 } 423 } 424 425 GpxActivityFactory.load();*/ 426