/docs/MyDocs

To get this branch, use:
bzr branch http://darksoft.org/webbzr/docs/MyDocs

« back to all changes in this revision

Viewing changes to Methods/Mapping/jsservices/gmaptogpx.js

  • Committer: Suren A. Chilingaryan
  • Date: 2009-04-09 03:21:08 UTC
  • Revision ID: csa@dside.dyndns.org-20090409032108-w4edamdh4adrgdu3
import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  GMapToGPX 6.2
 
3
  Originally based in part on the "Improved MSN and Google GPS GPX Waypoint 
 
4
  Extraction" bookmarklet described at http://badsegue.org/archives/2005/04/21/
 
5
 
 
6
  Josh Larios <hades@elsewhere.org>
 
7
  August 3, 2005 - September 30, 2008
 
8
 
 
9
  WARNING: Highly dependent on internal formats that aren't part of
 
10
  the API, so subject to complete breakdown at any time, outside my
 
11
  control.
 
12
 
 
13
  Gmap-pedometer elevation code courtesy of Mathew O'Brien.
 
14
 
 
15
  3/05/2007 - HeyWhatsThat.com code by mk -at- heywhatsthat.com
 
16
  10/09/2007 - Allpoints speed improvement by Kyle Yost
 
17
 
 
18
  TO DO: Separate out gpx writing and point/track extraction, so I can load
 
19
  some array up front regardless of whether it's a google map, a pedometer, 
 
20
  heywhatsthat, or whatever, and then just print the damn gpx once.
 
21
*/
 
22
 
 
23
var error = 0;
 
24
var version = '6.2';
 
25
var googledoc = ""; // will hold retrieved google info
 
26
var googleurl = "";
 
27
var gpxvar = ""; // will hold gHomeVPage structure, even for IE
 
28
var routes = new Array();
 
29
var polylines = new Array();
 
30
var milestones = new Array();
 
31
var yelp = new Array();
 
32
var googlepage; // Will hold the page element that gets toggled. May change.
 
33
var charset;
 
34
 
 
35
function fixup (foo) {
 
36
    foo = foo.replace(/\\x3e/g, '>');
 
37
    foo = foo.replace(/\\x3c/g, '<');
 
38
    foo = foo.replace(/\\x26/g, '&');
 
39
    foo = foo.replace(/\\x42/g, '"');
 
40
    foo = foo.replace(/\\x3d/g, '=');
 
41
    
 
42
    foo = foo.replace(/\\u003e/g, '>');
 
43
    foo = foo.replace(/\\u003c/g, '<');
 
44
    foo = foo.replace(/\\u0026/g, '&');
 
45
    
 
46
    foo = foo.replace(/\\042/g, '"');
 
47
 
 
48
    foo = foo.replace(/"*polylines"*:\s*/g, 'polylines:');
 
49
    foo = foo.replace(/"*markers"*:\s*/g, 'markers:');
 
50
    foo = foo.replace(/"*id"*:\s*/g, 'id:');
 
51
    foo = foo.replace(/"*lat"*:\s*/g, 'lat:');
 
52
    foo = foo.replace(/"*lng"*:\s*/g, 'lng:');
 
53
    foo = foo.replace(/"*laddr"*:\s*/g, 'laddr:');
 
54
    foo = foo.replace(/"*points"*:\s*/g, 'points:');
 
55
    foo = foo.replace(/\\"/g, '"');
 
56
    foo = foo.replace(/\"/g, '\'');
 
57
 
 
58
    return foo;
 
59
}
 
60
 
 
61
function callInProgress (xmlhttp) {
 
62
    switch (xmlhttp.readyState) {
 
63
    case 1: case 2: case 3:
 
64
        return true;
 
65
        break;
 
66
        // Case 4 and 0
 
67
    default:
 
68
        return false;
 
69
        break;
 
70
    }
 
71
}
 
72
 
 
73
// Synchronous, with an alarm to catch timeouts (30 seconds)
 
74
// No idea if this is the best way to do this, but for sure the best way I
 
75
// came up with at 3 in the morning.
 
76
function loadXMLDoc(url) {
 
77
    var req;
 
78
    var timeoutid;
 
79
    if (window.XMLHttpRequest) {
 
80
        req = new XMLHttpRequest();
 
81
        showstatusdiv('Loading...');
 
82
        timeoutid = window.setTimeout( function(){if(callInProgress(req)){req.abort();}}, 30000);
 
83
        req.open("GET", url, false);
 
84
        req.send(null);
 
85
        window.clearTimeout(timeoutid);
 
86
        hidestatusdiv();
 
87
    } else if (window.ActiveXObject) {
 
88
        req = new ActiveXObject("Microsoft.XMLHTTP");
 
89
        if (req) {
 
90
            showstatusdiv('Loading...');
 
91
            timeoutid = window.setTimeout( function(){if(callInProgress(req)){req.abort();}}, 30000);
 
92
            req.open("GET", url, false);
 
93
            req.send();
 
94
            window.clearTimeout(timeoutid);
 
95
            hidestatusdiv();
 
96
        }
 
97
    }
 
98
    
 
99
    if (req.readyState == 4) {
 
100
        // only if "OK"
 
101
        if (req.status == 200) {
 
102
            return(req.responseText);
 
103
        } else {
 
104
            showstatusdiv('Error ' + req.status + ' getting google data: ' + req.statusText);
 
105
            return('');
 
106
        }
 
107
    } else {
 
108
        showstatusdiv('Error: loadXMLDoc continued with readystate: ' + req.readyState);
 
109
        return('');
 
110
    }
 
111
}
 
112
 
 
113
 
 
114
function hidestatusdiv() { 
 
115
    var statusbox;
 
116
    if (statusbox = document.getElementById("statusbox")) {
 
117
        document.body.removeChild(statusbox);
 
118
    }
 
119
}
 
120
 
 
121
function showstatusdiv(boxcontents) {
 
122
    hidestatusdiv();
 
123
    z=document.body.appendChild(document.createElement("div"));
 
124
    z.id = "statusbox";
 
125
    z.style.position = "absolute";      
 
126
    if (self.pageYOffset != null) {     
 
127
        z.style.top = self.pageYOffset + "px";  
 
128
    } else if (document.documentElement.scrollTop != null) {
 
129
        z.style.top = document.documentElement.scrollTop + "px";        
 
130
    }
 
131
    z.style.width = "50%";
 
132
    z.style.left = "0px";
 
133
    z.style.background = "#ffffff";
 
134
    z.style.border = ".3em solid #ff0000";
 
135
    z.style.padding = ".3em 1.3em .3em .3em";
 
136
    z.style.zIndex = "1000";
 
137
    
 
138
    z.innerHTML = '<div style="position: absolute; border: 1px solid black; top: 0px; right: 0px;"><span style="padding: .3em; font-weight: bold;"><a style="text-decoration: none;" title="Close status box" href="#" onclick="javascript:hidestatusdiv();">X</a></span></div>';
 
139
    z.innerHTML += boxcontents;
 
140
}
 
141
 
 
142
// This function is from Google's polyline utility.
 
143
function decodeLine (encoded) {
 
144
    var len = encoded.length;
 
145
    var index = 0;
 
146
    var array = [];
 
147
    var lat = 0;
 
148
    var lng = 0;
 
149
    
 
150
    while (index < len) {
 
151
        var b;
 
152
        var shift = 0;
 
153
        var result = 0;
 
154
        do {
 
155
            b = encoded.charCodeAt(index++) - 63;
 
156
            result |= (b & 0x1f) << shift;
 
157
            shift += 5;
 
158
        } while (b >= 0x20);
 
159
        var dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
 
160
        lat += dlat;
 
161
        
 
162
        shift = 0;
 
163
        result = 0;
 
164
        do {
 
165
            b = encoded.charCodeAt(index++) - 63;
 
166
            result |= (b & 0x1f) << shift;
 
167
            shift += 5;
 
168
        } while (b >= 0x20);
 
169
        var dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
 
170
        lng += dlng;
 
171
 
 
172
        array.push({"lat": round(lat * 1e-5), "lon": round(lng * 1e-5)});
 
173
    }
 
174
    
 
175
    return array;
 
176
}
 
177
 
 
178
function StringBuffer() {
 
179
   this.buffer = [];
 
180
 }
 
181
 
 
182
StringBuffer.prototype.append = function append(string) {
 
183
   this.buffer.push(string);
 
184
   return this;
 
185
 };
 
186
 
 
187
StringBuffer.prototype.toString = function toString() {
 
188
   return this.buffer.join("");
 
189
 };
 
190
 
 
191
 
 
192
 
 
193
function gmaptogpxdiv(dtype) { 
 
194
    var mypoints = null;
 
195
    
 
196
    var qtype = 0;
 
197
    var subtype = 0;
 
198
    
 
199
    /* 
 
200
       Determine which type of data we're extracting -- a route, or points of
 
201
       interest. (Or gmap-pedometer/heywhatsthat.) 
 
202
    */
 
203
    
 
204
    if (gpxvar && gpxvar.overlays && gpxvar.overlays.polylines) {
 
205
        qtype = 2;
 
206
        
 
207
        /* FIXME 
 
208
           errorbox('<p>2008.05.07 - GMapToGPX is currently unable to process driving directions, due to a change in the underlying Google Maps code. I\'m working on it.</p>');
 
209
           closebox();
 
210
           return(0);
 
211
           END FIXME */
 
212
 
 
213
 
 
214
        // Load "polylines" up with the decoded polyline segments
 
215
        for (i = 0; i < gpxvar.overlays.polylines.length; i++) {
 
216
            polylines[i] = decodeLine(gpxvar.overlays.polylines[i].points);
 
217
        }
 
218
        
 
219
        // Stuff the descriptions into the "polylines" array
 
220
        if (segmatch = googledoc.match(/<td class=.?dirsegtext.*?id=.?dirsegtext.*?<\/tr>/g)) {
 
221
            for (var s = 0; s < segmatch.length; s++) {
 
222
                var route = segmatch[s].replace(/.*dirsegtext_([0-9]+)_([0-9]+).*/, "$1");
 
223
                var step = segmatch[s].replace(/.*dirsegtext_([0-9]+)_([0-9]+).*/, "$2");
 
224
                var desc = deamp(segmatch[s].replace(/.*dirsegtext[^>]+>(.*?)<\/td>.*/, "$1"));
 
225
                
 
226
                var polyline = gpxvar.drive.routes[route].steps[step].polyline;
 
227
                var ppt = gpxvar.drive.routes[route].steps[step].ppt;
 
228
                polylines[polyline][ppt].desc = deamp(desc);
 
229
            }
 
230
        }
 
231
    
 
232
        // Figure out which polylines go into which routes
 
233
        for (i = 0; i < gpxvar.drive.routes.length; i++) {
 
234
            var start = gpxvar.drive.routes[i].steps[0].polyline;
 
235
            var end = gpxvar.drive.routes[i].steps[gpxvar.drive.routes[i].steps.length - 1].polyline;
 
236
            var route = "route" + i;
 
237
            routes[route] = new Array();
 
238
            for (n = start; n <= end; n++) {
 
239
                routes[route] = routes[route].concat(polylines[n]);
 
240
            }
 
241
        }
 
242
        
 
243
        // Get the milestone descriptions
 
244
        var msaddrmatch;
 
245
        if (msaddrmatch = gpxvar.panel.match(/<div id=.?sxaddr.*?>.*?<\/div>/g)) {
 
246
            for (var i = 0; i < msaddrmatch.length; i++) {
 
247
                milestones[parseInt(i)] = deamp(msaddrmatch[i].replace(/<div id=.?sxaddr.?><div[^>]+>(.*?)<\/div>/, "$1"));
 
248
            }
 
249
        }
 
250
        
 
251
 
 
252
    } else  if (googledoc.match(/id:'(A|addr)'/)) {
 
253
        qtype = 1;
 
254
        routes['poi'] = new Array();
 
255
        
 
256
        var markers=googledoc.slice(googledoc.indexOf('markers:['));
 
257
        /*      markers=markers.slice(0, markers.indexOf('polylines: [')); */
 
258
        
 
259
        var pois = markers.match(/{id:'([A-Z]|addr|loc\d+)'.*?\}/g);
 
260
        for (var i = 0; i < pois.length; i++) { 
 
261
            var lat = pois[i].replace(/.*lat:(.*?),.*/, "$1");
 
262
            var lon = pois[i].replace(/.*lng:(.*?),.*/, "$1");
 
263
            var desc = pois[i].replace(/.*laddr:'(.*?)',.*/, "$1");
 
264
            desc = desc.replace(/ @.*/, "");
 
265
            desc = desc.replace(/(.*) \((.*)\)/, "$2 ($1)");
 
266
            routes['poi'].push({"lat": round(lat), "lon": round(lon), "desc": deamp(desc)});
 
267
        }
 
268
    }
 
269
    
 
270
    /* gmap-pedometer.com */
 
271
    if ( (qtype==0) && (self.gLatLngArray) && (self.gLatLngArray[0]) ) { 
 
272
        qtype = 3; 
 
273
    }
 
274
 
 
275
    
 
276
    /* HeyWhatsThat.com list of peaks visible from given location */
 
277
    if (qtype == 0 && location.href.match(/heywhatsthat.com/i) && peaks && peaks.length) {
 
278
        qtype = 4;      
 
279
        subtype = 1;
 
280
    }
 
281
 
 
282
    /* Yelp.com search */
 
283
    if (qtype == 0 && location.href.match(/yelp.com/i) && document.body.innerHTML.match('result_plot_obj.map.addOverlay')) {
 
284
        qtype = 4;
 
285
        subtype = 2;
 
286
        var yelpmatch = document.body.innerHTML.match(/result_plot_obj.map.addOverlay.*?\)\)/g);
 
287
        for (var i = 0; i < yelpmatch.length; i++) {    
 
288
            yelp[i] = new Array();
 
289
            yelp[i].name = deamp(yelpmatch[i].replace(/.*<h3>(.*?)<\/h3>.*/, "$1"));
 
290
            yelp[i].addr = deamp(yelpmatch[i].replace(/.*<address[^>]*>(.*?)<\/address>.*/, "$1"));
 
291
            yelp[i].lon = yelpmatch[i].replace(/.*Yelp.TSRUrl.*?,.*?,.*?, (.*?),.*/, "$1");
 
292
            yelp[i].lat = yelpmatch[i].replace(/.*Yelp.TSRUrl.*?,.*?,.*?,.*?, (.*?),.*/, "$1");
 
293
        }
 
294
    }
 
295
    /* Yelp.com single location */
 
296
    //    var json_biz = {"city":"Seattle","zip":"98102","review_count":6,"name":"Tacos Guaymas - CLOSED","neighborhoods":["Capitol Hill"],"photos":[],"address1":"213 Broadway East","avg_rating":4.000000,"longitude":-122.320999,"address2":null,"phone":"(206) 860-7345","state":"WA","latitude":47.620201,"id":"PidHplYWockrwJpijqUwsg","categories":{}};
 
297
    if (qtype == 0 && location.href.match(/yelp.com/i) && json_biz) {
 
298
        qtype = 4;
 
299
        subtype = 2;
 
300
        yelp[0] = new Array();
 
301
        yelp[0].name = json_biz.name;
 
302
        yelp[0].lat = json_biz.latitude;
 
303
        yelp[0].lon = json_biz.longitude;
 
304
        yelp[0].addr = json_biz.address1 + ", ";
 
305
        if (json_biz.address2 != null) {
 
306
            yelp[0].addr += json_biz.address2 + ", ";
 
307
        }
 
308
        yelp[0].addr += json_biz.city + ", " + json_biz.state + " " + json_biz.zip;
 
309
    }
 
310
 
 
311
    /* findmespot.com */
 
312
    if (qtype == 0 && location.href.match(/findmespot.com/i) && document.getElementsByTagName('iframe')[1] && document.getElementsByTagName('iframe')[1].contentDocument.getElementById('mapForm:inputHidden1').value) {
 
313
        qtype = 4;
 
314
        subtype = 3;
 
315
    }
 
316
 
 
317
   /* logyourrun.com */
 
318
   if (qtype == 0 && location.href.match(/logyourrun.com/i) && route_polyline) {
 
319
        qtype = 4;
 
320
        subtype =  4;
 
321
   }
 
322
 
 
323
    if (qtype==0) {
 
324
        errorbox('<p>There doesn\'t seem to be any extractable data on this page.</p><p>If there is, but it\'s not detected, please visit the <a href="http://www.elsewhere.org/GMapToGPX/">project homepage</a> and leave a bug report, including a link to the page you\'re on right now.</p><p><strong>Note:</strong> Google Maps mashups (that is, a page with a Google Map on it, but not at google.com) do not automatically work with this utility. If you would like to see GMapToGPX work with your Google Maps mashup site, please leave a comment on the project page.</p>');
 
325
        closebox();
 
326
        return(0); 
 
327
    }
 
328
 
 
329
 
 
330
    /* t contains the text that will be injected into a <div> overlay */
 
331
    var t="<div style='border:3px dotted orange;padding:2px;background-color:#FFFFFF;margin-left:auto;margin-right:auto;'>";
 
332
    
 
333
    if (navigator.userAgent.match(/Safari/)) {
 
334
        t+='\
 
335
<style type="text/css">\
 
336
.menubar ul {\
 
337
        margin:0; \
 
338
}\
 
339
.menubar li {\
 
340
        display:inline;\
 
341
        list-style:none;\
 
342
        margin:0 5px 0 5px;\
 
343
}\
 
344
\
 
345
.menubar a , .menubar a:visited {\
 
346
        padding: 1px 10px 1px 10px;\
 
347
        text-decoration:none;\
 
348
        background-color: #3399CC;\
 
349
        color:white;\
 
350
        font-family:Verdana, Sans-Serif;\
 
351
        font-size:9pt;\
 
352
        -moz-border-radius:10px;\
 
353
        border:2px inset black;\
 
354
        font-weight: bolder;\
 
355
}\
 
356
\
 
357
.menubar select {\
 
358
    background-color: transparent;\
 
359
    color: #333333;\
 
360
    margin-top: 2px;\
 
361
    border: 1px solid #efefef;\
 
362
}\
 
363
\
 
364
.menubar a:hover , .menubar select:hover {\
 
365
        border:2px outset black;\
 
366
        background-color:white;\
 
367
        color:blue;\
 
368
        text-decoration:none;\
 
369
}\
 
370
</style>\
 
371
';
 
372
    }
 
373
        
 
374
    
 
375
    t+="<div style='background-color:gray;'>";
 
376
    t+='<ul class="menubar">';
 
377
    t+='<li class="menubar">GMapToGPX v' + version + '</li>';
 
378
    if ((qtype > 1) && (qtype != 4)) {
 
379
        if (dtype != "route") {
 
380
            t+='<li class="menubar"><a href="javascript:reload(0)" title="Turn points as a route">Route</a></li>'; 
 
381
        } 
 
382
        if (dtype != "track") {
 
383
            t+='<li class="menubar"><a href="javascript:reload(1)" title="Turn points as a track">Track</a></li>';
 
384
        }
 
385
        if (dtype != "points") {
 
386
            t+='<li class="menubar"><a href="javascript:reload(2)" title="Turn points as waypoints">Points</a></li>';
 
387
        }
 
388
        if ((qtype ==2) && (dtype != "allpoints")) {
 
389
            t+='<li class="menubar"><a href="javascript:reload(3)" title="ALL points as a track (potentially very large)">Full</a></li>';
 
390
        }
 
391
    }
 
392
    t+='<li class="menubar"><a href="javascript:loadabout()">About</a></li>';
 
393
    t+='<li class="menubar"><a href="javascript:closebox()">CLOSE [X]</a></li></ul></div>';
 
394
    t+='<textarea rows="20" cols="60">';
 
395
    
 
396
    /* This part of the GPX is going to be the same no matter what. */
 
397
    t+= '<?xml version="1.0" encoding="' + charset + '"?>\n' + 
 
398
        '<gpx version="1.1"\n' + 
 
399
        '     creator="GMapToGPX ' + version + ' - http://www.elsewhere.org/GMapToGPX/"\n' + 
 
400
        '     xmlns="http://www.topografix.com/GPX/1/1"\n' + 
 
401
        '     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n' + 
 
402
        '     xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">\n';
 
403
 
 
404
    if ((qtype==2) && (dtype=="allpoints")) {
 
405
        var title = "Driving directions";
 
406
        t+= '   <trk>\n';
 
407
        t+= '      <name>Google Driving Directions Track</name>\n';
 
408
        var buf = new StringBuffer;
 
409
        for (var key in routes) {
 
410
            var route = routes[key];
 
411
            buf.append("      <trkseg>\n");
 
412
            for(i=0;i<route.length;i++) {
 
413
                if (i == route.length - 1) {
 
414
                    route[i].desc = milestones[1 + parseInt(key.replace(/route/,''))];
 
415
                } else if ((route[i].lat == route[i+1].lat) && (route[i].lon ==
 
416
                                                                route[i+1].lon)) {
 
417
                    continue;
 
418
                }
 
419
                buf.append("      <trkpt lat=\"");
 
420
                buf.append(route[i].lat);
 
421
                buf.append("\" lon=\"");
 
422
                buf.append(route[i].lon);
 
423
                buf.append("\">");
 
424
                if (route[i].desc) {
 
425
                    buf.append("<cmt>");
 
426
                    buf.append(deamp(route[i].desc));
 
427
                    buf.append("</cmt>");
 
428
                }
 
429
                buf.append("</trkpt>\n");
 
430
            }
 
431
            buf.append("      </trkseg>\n");
 
432
        }
 
433
        buf.append("   </trk>\n");
 
434
        t+= buf.toString();
 
435
 
 
436
    } else if (qtype == 3) {
 
437
//      var pl = location.href + returnPermalinkString();
 
438
        var pl = "Permalink temporarily unavailable.";
 
439
        var elevationArrayTested = true;                
 
440
        // 1st make sure that the gmap elevation array is the same length as 
 
441
        // the LatLng array
 
442
        if ( (typeof(elevationArray) != 'undefined') && (gLatLngArray.length == elevationArray.length) ) {
 
443
            // Next test all of the elevation data in the array, looking for 
 
444
            // bad elevation data
 
445
            // -1.79769313486231E+308 means no valid elevation value was 
 
446
            // found at that point
 
447
            for (var e =0;e<elevationArray.length;e++){
 
448
                if (self.elevationArray[e] == "-1.79769313486231E+308") 
 
449
                    {
 
450
                        elevationArrayTested = false;
 
451
                    }
 
452
            }
 
453
        } else {
 
454
            elevationArrayTested = false;
 
455
        }
 
456
 
 
457
        if (dtype == "track") {
 
458
            t+= '   <trk>\n';
 
459
            t+= '      <name>Gmaps Pedometer Track</name>\n' +
 
460
                '      <cmt>Permalink: &lt;![CDATA[\n' + pl + '\n]]>\n</cmt>\n';
 
461
            t+= '      <trkseg>\n';
 
462
        } else if (dtype == "route") {
 
463
            t+= '   <rte>\n';
 
464
            t+= '      <name>Gmaps Pedometer Route</name>\n' +
 
465
                '      <cmt>Permalink: &lt;![CDATA[\n' + pl + '\n]]>\n</cmt>\n';
 
466
        }
 
467
        for(var i=0;i<self.gLatLngArray.length;i++){
 
468
            if (dtype == "track") {
 
469
                t+= '      <trkpt ';
 
470
            } else if (dtype == "route") {
 
471
                t+= '      <rtept ';
 
472
            } else if (dtype == "points") {
 
473
                t+= '      <wpt ';
 
474
            }
 
475
            t+= 'lat="' + round(self.gLatLngArray[i].y) + '" ' +
 
476
                'lon="' + round(self.gLatLngArray[i].x) + '">\n';
 
477
 
 
478
 
 
479
            if ( elevationArrayTested == true ) {
 
480
                var currentElevation = 0;
 
481
                currentElevation = self.elevationArray[i];              
 
482
                currentElevation = round(currentElevation * 0.3048)     
 
483
                    t+= '         <ele>' + currentElevation  + '</ele>\n';
 
484
            }
 
485
 
 
486
            t+= '         <name>' + (i ? 'Turn ' + i : 'Start') + '</name>\n';
 
487
 
 
488
            if (dtype == "track") {
 
489
                t+= '      </trkpt>\n';
 
490
            } else if (dtype == "route") {
 
491
                t+= '      </rtept>\n';
 
492
            } else if (dtype == "points") {
 
493
                t+= '      </wpt>\n';
 
494
            }
 
495
        }
 
496
        if (dtype == "track") {
 
497
            t+= '      </trkseg>\n';
 
498
            t+= '   </trk>\n';
 
499
        } else if (dtype == "route") {
 
500
            t+= '   </rte>\n';
 
501
        }
 
502
    } else if (qtype == 4 && subtype == 1) {
 
503
        /* HeyWhatsThat.com list of peaks */
 
504
        for (var i = 0; i < peaks.length; i++) {
 
505
            var p = peaks[i];
 
506
            t+= '   <wpt lat="' + p.lat + '" lon="' + p.lon + '">\n' +
 
507
                '      <ele>' + p.elev + '</ele>\n' +
 
508
                '      <name>' + p.name + '</name>\n' +
 
509
                '      <cmt>' + p.name + '</cmt>\n' +
 
510
                '   </wpt>\n';
 
511
        }
 
512
    } else if (qtype == 4 && subtype == 2) {
 
513
        for (var i = 0; i < yelp.length; i++) {
 
514
            var p = yelp[i];
 
515
            t+= '   <wpt lat="' + p.lat + '" lon="' + p.lon + '">\n' +
 
516
                '      <name>' + p.name + '</name>\n' +
 
517
                '      <cmt>' + p.addr + '</cmt>\n' +
 
518
                '   </wpt>\n';
 
519
        }
 
520
    } else if (qtype == 4 && subtype == 3) {
 
521
          var spotdata = document.getElementsByTagName('iframe')[1].contentDocument.getElementById('mapForm:inputHidden1').value;
 
522
          var loc_array = spotdata.split(",");
 
523
          var loc_length = loc_array.length - 1;
 
524
          t += '  <trk><trkseg>\n';
 
525
          for(var i=0;i<loc_length;i++){
 
526
            var loc_point = loc_array[i].split("||");
 
527
            var esn = loc_point[0];
 
528
            var lat = loc_point[1];
 
529
            var lon = loc_point[2];
 
530
            var type = loc_point[3];
 
531
            var dtime = loc_point[4];
 
532
            t+= '   <trkpt lat="' + lat + '" lon="' + lon + '">\n' +
 
533
                '      <name>' + i + '-' + type + '</name>\n' +
 
534
                '      <cmt>' + type + ' ' + esn +  ' @ ' + dtime + '</cmt>\n' +
 
535
                '      <desc>' + type + ' ' + esn + ' @ ' + dtime + '</desc>\n' +
 
536
                '   </trkpt>\n';
 
537
          }
 
538
          t += '  </trkseg></trk>\n';
 
539
    } else if (qtype == 4 && subtype == 4) {
 
540
        var lyr = decodeLine(route_polyline);
 
541
        t += '  <trk><trkseg>\n';
 
542
        for (var i = 0; i < lyr.length; i++) {
 
543
            t+= '   <trkpt lat="' + lyr[i].lat + '" lon="' + lyr[i].lon + '">\n' ;
 
544
            t+= '      <name>LYR' + i + '</name>\n' + '   </trkpt>\n';
 
545
        }
 
546
        t += '  </trkseg></trk>\n';
 
547
        
 
548
    } else if (qtype == 2) {
 
549
        /* If we're on a page with driving directions, spit out a route. */
 
550
        var title = "Driving directions";
 
551
        
 
552
        if (dtype == "track") {
 
553
            t+= '   <trk>\n';
 
554
        } 
 
555
        
 
556
        var turn = 1;
 
557
        var milestone = 1;
 
558
        
 
559
        for (var key in routes) {
 
560
            var route = routes[key];
 
561
            var routeno = key.replace(/route/, '');
 
562
            routeno = parseInt(routeno);
 
563
            if (dtype == "track") {
 
564
                t+= '   <trkseg>\n';
 
565
            } else if (dtype == "route") {
 
566
                t+= '   <rte>\n';
 
567
            }
 
568
            
 
569
            if ((dtype=="track") || (dtype=="route")) {
 
570
                t+= '      <name>' + key + '</name>\n';
 
571
                t+= '      <cmt>' + milestones[routeno] + " to " + milestones[routeno + 1] + '</cmt>\n'; 
 
572
                t+= '      <desc>' + milestones[routeno] + " to " + milestones[routeno + 1] + '</desc>\n'; 
 
573
            }
 
574
 
 
575
            for(i=0;i<route.length;i++){        
 
576
                if ((i != route.length - 1) && (route[i].desc == undefined)) {
 
577
                    continue;
 
578
                } 
 
579
                // Only print turn points and milestones (last point is an
 
580
                // undescribed milestone; first point should always have a
 
581
                // description).
 
582
                switch(dtype) {
 
583
                case 'track':
 
584
                    t+= '      <trkpt ';
 
585
                    break;
 
586
                case 'route':
 
587
                    t+= '      <rtept ';
 
588
                    break;
 
589
                case 'points':
 
590
                    t+= '      <wpt ';
 
591
                    break;
 
592
                }
 
593
                t+= 'lat="' + route[i].lat + '" ' +
 
594
                    'lon="' + route[i].lon + '">\n' +
 
595
                    '         <name>';
 
596
                if (i == route.length - 1) {
 
597
                    route[i].desc = milestones[routeno+1];
 
598
 
 
599
                    t += 'GMLS-' + ((milestone < 100) ? '0' : '') + 
 
600
                        ((milestone < 10) ? '0' : '') + milestone;
 
601
                    milestone += 1;
 
602
                    turn -= 1;
 
603
                } else {
 
604
                    t += 'GRTP-' + ((turn < 100) ? '0' : '') + 
 
605
                        ((turn < 10) ? '0' : '') + turn;
 
606
                }
 
607
                t += '</name>\n' +
 
608
                    '         <cmt>' + route[i].desc + '</cmt>\n' +
 
609
                    '         <desc>' + route[i].desc + '</desc>\n';
 
610
 
 
611
                switch(dtype) {
 
612
                case 'track':
 
613
                    t+= '      </trkpt>\n';
 
614
                    break;
 
615
                case 'route':
 
616
                    t+= '      </rtept>\n';
 
617
                    break;
 
618
                case 'points':
 
619
                    t+= '      </wpt>\n';
 
620
                    break;
 
621
                }
 
622
                turn++;
 
623
            }
 
624
            if (dtype == "track") {
 
625
                t+= '   </trkseg>\n';
 
626
            } else if (dtype == "route") {
 
627
                t+= '   </rte>\n';
 
628
            }
 
629
        }
 
630
        
 
631
        if (dtype == "track") {
 
632
            t+= '   </trk>\n';
 
633
        } 
 
634
        
 
635
    } else if (qtype == 1) {
 
636
        /* This is a page with points of interest - spit out waypoints. */
 
637
        for(i=0;i<routes['poi'].length;i++){
 
638
            var point = routes['poi'][i];
 
639
            t+= '   <wpt lat="' + point.lat + '" lon="' + point.lon + '">\n' +
 
640
                '      <name>' + point.desc + '</name>\n' +
 
641
                '      <cmt>' + point.desc.replace(/(.*) \((.*)\)/, "$2 ($1)") + '</cmt>\n' +
 
642
                '      <desc>' + point.desc.replace(/(.*) \((.*)\)/, "$2 ($1)") + '</desc>\n' +
 
643
                '   </wpt>\n';
 
644
        }
 
645
    } else {
 
646
        errorbox('An unknown error occurred. Please leave a bug report at the <a href="http://www.elsewhere.org/GMapToGPX/">project homepage</a> and include a link to the page you\'re on right now.');
 
647
        error = 1;
 
648
    }
 
649
    
 
650
    t+='</gpx>\n';
 
651
    t+='</textarea>';
 
652
    t+="<div style='background-color:gray;'>";
 
653
    t+='<ul class="menubar">';
 
654
    t+='<li class="menubar"><a href="javascript:loadabout()">About</a></li>';
 
655
    t+='<li class="menubar"><a href="javascript:closebox()">CLOSE [X]</a></li></ul></div></div>';
 
656
    displaybox(t);
 
657
}
 
658
 
 
659
 
 
660
function displaybox(boxcontents) {
 
661
    closebox();
 
662
    if (googlepage=document.getElementById("page")) {
 
663
        googlepage.style.display='none';
 
664
    }
 
665
    var z=document.body.appendChild(document.createElement("div"));
 
666
    z.id = "gpxbox";
 
667
    /* I don't know about this stuff; it came from badsegue. */
 
668
    z.style.position = "absolute";      
 
669
    if (self.pageYOffset != null) {     
 
670
        z.style.top = self.pageYOffset + "px";  
 
671
    } else if (document.documentElement.scrollTop != null) {
 
672
        z.style.top = document.documentElement.scrollTop + "px";        
 
673
    }
 
674
    z.style.width = "99%";
 
675
    z.style.zIndex = "1000";
 
676
    z.innerHTML = boxcontents;
 
677
}
 
678
 
 
679
function closebox() { 
 
680
    var gpxbox;
 
681
    if (gpxbox = document.getElementById("gpxbox")) {
 
682
        document.body.removeChild(gpxbox);
 
683
    }
 
684
    if (googlepage != undefined) {
 
685
        googlepage.style.display='block';
 
686
    }
 
687
}
 
688
 
 
689
 
 
690
 
 
691
function loadabout() {
 
692
    var about = '<span style="font-size: x-small;"><p><a href="http://www.elsewhere.org/GMapToGPX/">GMapToGPX</a> Extractor ' + version + '<br />';
 
693
    about += 'A project of <a href="http://www.elsewhere.org/">Communications From Elsewhere</a></p>';
 
694
    about += '<p>Usage:<ul>';
 
695
    about += '<li>"Track" displays driving directions as a GPX track with one or more track segments, depending on the number of milestones in the directions.</li>';
 
696
    about += '<li>"Route" displays driving directions as one or more GPX routes.</li>';
 
697
    about += '<li>"Full" displays driving directions as a GPX track containing one or more track segments, each of which contains every single point on the line Google Maps draws to represent the segment. Use with caution, as long routes may produce huge results.</li>';
 
698
    about += '<li>"Points" displays driving directions as a list of waypoints for each turn in the route. The waypoints will be in order, but this option is mainly intended for devices which can only handle waypoints, not tracks or routes. In most cases, you should use another option.</li>';
 
699
    about += '<li>For single or multiple address searches, there are no display options. You get a list of individual waypoints.</li>';
 
700
    about += '</ul>If you have questions or comments, please visit the <a href="http://www.elsewhere.org/GMapToGPX/">project homepage</a>.</p></span>';
 
701
    showstatusdiv(about);
 
702
}
 
703
 
 
704
function errorbox(a) {
 
705
    var err = '<a href="http://www.elsewhere.org/GMapToGPX/">GMapToGPX</a> v' + version + " (ERROR)<br />" + a;
 
706
    showstatusdiv(err);
 
707
}
 
708
 
 
709
 
 
710
/* Clean up floating point math errors */
 
711
function round(a) {
 
712
    return parseInt(a*1E+5)/1E+5;
 
713
}
 
714
 
 
715
function reload(t) {
 
716
    closebox();
 
717
    if (t==0) {
 
718
        gmaptogpxdiv("route");
 
719
    } else if (t=="1") {
 
720
        gmaptogpxdiv("track");
 
721
    } else if (t=="2") {
 
722
        gmaptogpxdiv("points");
 
723
    } else if (t=="3") {
 
724
        gmaptogpxdiv("allpoints");
 
725
    }
 
726
}
 
727
 
 
728
 
 
729
 
 
730
function deamp(a) {
 
731
    a = a.replace(/<br *\/>(.+)/g, ", $1");
 
732
    a = a.replace(/<br *\/>/g, '');
 
733
    a = a.replace(/&#39;/g, '\'');
 
734
    a = a.replace(/\\047/g, '\'');
 
735
    a = a.replace(/\\042/g, '\"');
 
736
    a = a.replace(/&#160;/g, ' ');
 
737
    a = a.replace(/<\/*b>/g, '');
 
738
    a = a.replace(/<wbr\/*>/g, '');
 
739
    a = a.replace(/<div[^>]*?>.*?<\/div>/g, ' ');
 
740
    a = a.replace(/\\\'/g, '\''); 
 
741
    a = a.replace(/\\\"/g, '\"');
 
742
    a = a.replace(/\\x26/g, '&');
 
743
    a = a.replace(/&/g, '&amp;');  
 
744
    a = a.replace(/&amp;amp;amp;/g, '&amp;amp;');
 
745
    a = a.replace(/\\n/g, '');
 
746
    a = a.replace(/\\t/g, '');
 
747
    a = a.replace(/\s+/g, ' ');
 
748
    a = a.replace(/^\s+/, '');
 
749
    a = a.replace(/\s+$/, '');
 
750
    return a;
 
751
}
 
752
                  
 
753
 
 
754
/* main() */
 
755
if (document.location.hostname.indexOf('google') >= 0) {
 
756
 
 
757
    var kmlurl;
 
758
    if (kmlurl = document.getElementById('view_kml_link').href) {
 
759
        if (kmlurl.indexOf(':void') < 0) {
 
760
            kmlurl = kmlurl.replace(/output=nl/, 'output=kml');
 
761
            errorbox('This is a "My Maps" page, which means that the original KML used to create it is available. Please <a href="' + kmlurl + '">download the KML file</a> (using this link, not the one provided by Google) and convert it using <a href="http://www.gpsvisualizer.com/convert" target="_new">GPSVisualizer</a>.');
 
762
            error = 1;
 
763
        }
 
764
    }
 
765
 
 
766
    if (!error) {
 
767
    
 
768
        // bar_icon_link is the "link to this page" icon. If they change 
 
769
        // its name, I need to fix that here.
 
770
        if (googleurl=document.getElementById('link').href) {
 
771
            googleurl = googleurl.replace(/&view=text/, '');
 
772
            googledoc = loadXMLDoc(googleurl);
 
773
            
 
774
            charset=googledoc.slice(googledoc.indexOf('charset='));
 
775
            charset=charset.slice(8, charset.indexOf('"'));
 
776
            
 
777
            // Doing this as a regexp was causing firefox to stall out. bah.
 
778
            var encpointblob=googledoc.slice(googledoc.indexOf('gHomeVPage ='));
 
779
            encpointblob=encpointblob.slice(0, encpointblob.indexOf('};') + 2
 
780
                                            );
 
781
            encpointblob=encpointblob.replace(/gHomeVPage/, "gpxvar");
 
782
            eval(encpointblob);
 
783
            var panel=googledoc.slice(googledoc.indexOf('id=panel_dir'));
 
784
            panel=panel.slice(0,panel.indexOf('Map data'));
 
785
            gpxvar.panel = panel;
 
786
            googledoc=fixup(googledoc);
 
787
        }
 
788
    }
 
789
}
 
790
 
 
791
charset = charset ? charset : "UTF-8";
 
792
 
 
793
/* This bit of code was causing Safari to seriously freak out, hence the 
 
794
   stylesheet being included above in t, but only for Safari.  */
 
795
if (! navigator.userAgent.match(/Safari/)) {
 
796
    var styleObject = document.getElementsByTagName("HEAD")[0].appendChild(document.createElement("link"));
 
797
    styleObject.rel="Stylesheet";
 
798
    styleObject.type="text/css";
 
799
    styleObject.href="http://www.elsewhere.org/GMapToGPX/menubar.css";
 
800
    styleObject.id="sst_css";
 
801
}
 
802
 
 
803
if (error != 1) {
 
804
/* Default action. If it's not a route, the argument doesn't matter. */
 
805
  gmaptogpxdiv("route");
 
806
} else {
 
807
  closebox();
 
808
}
 
809