//-----------------------------------------------------------------------
// GPX2GM
// Darstellung von GPS-Daten aus einer GPX-Datei in Google Maps
// Version 3.6
// 21. 8. 2009 Jürgen Berkemeier
// www.j-berkemeier.de
//-----------------------------------------------------------------------
// Modifikationen peter@danninger.eu vom 11.11.2009:
//  1. Fotogröße begrenzen
//  2. Höhenmeter und Abfahrtsmeter ergänzen (mit wahlweisem Filter)
//  3. anderes Kamera Icon
//  4. wählbares Wegepunkt Icon
//  5. Einbettung in eigenes Seiten Layout
//  6. OSM Track & Home
//  7. TAH-Map und Open Cycle Map !
//  8. Nach Foto bzw. Wegepunkt Karte wieder in Grundstellung
//  9. Tooltip bei Kamerasymbol
// 10. onresize event
// 11. Button-Event auf Div-Event geändert, ich mag keine Buttons, daher auch 12.
// 12. gpxview: getrennt auf gpxview1: (onload) bzw. gpxview2: (click)
// 13. "bitte warten" Hintergrundbild
//-----------------------------------------------------------------------

if (typeof(LargeMapControl) == "undefined")    var LargeMapControl = true;
if (typeof(OverviewMapControl) == "undefined") var OverviewMapControl = true;
if (typeof(Legende) == "undefined")            var Legende = true;
if (typeof(Legende_trk) == "undefined")        var Legende_trk = true;
if (typeof(Legende_rte) == "undefined")        var Legende_rte = true;
if (typeof(Legende_wpt) == "undefined")        var Legende_wpt = true;
if (typeof(HP_verbinde) == "undefined")        var HP_verbinde = true;                                        // Profile mehrerer Tracks verbinden
if (typeof(HoehenFilter) == "undefined")       var HoehenFilter = parseFloat(16);                             // Meter die gezählt werden
if (typeof(FotoWidth) == "undefined")          var FotoWidth = 400;                                           // pixel
if (typeof(FotoHeight) == "undefined")         var FotoHeight = 300;                                          // pixel
if (typeof(CameraSymb) == "undefined")         var CameraSymb = new Array("camera.png",32,32,10,32);          // file,width,height,hoff,voff
if (typeof(CameraShadow) == "undefined")       var CameraShadow = new Array("camera_s.png",59,32);            // file,width,height
if (typeof(WayPointSymb) == "undefined")       var WayPointSymb = new Array("bubble_gelb.png",12,24,6,24);    // file,width,height,hoff,voff
if (typeof(WayPointShadow) == "undefined")     var WayPointShadow = new Array("bubble_shadow.png",22,20);     // file,width,height
var actTrack = "";
var actMap = "Karte";

document.write('<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key='+key+'" type="text/javascript"><\/script>');

Array.prototype.sum = function() {
 for (var s=0,i=0; i<this.length; i++)      s += this[i];
 return s;
}
//
// wird durch onLoad aufgerufen ----------------------------------------------
//
function makeMap(ID) {
  var dieses = this;
  var id = ID;
  var id_hp = id + hpsuffix;
  var load = false
  var latmin = 1000;
  var latmax = -1000;
  var lonmin = 1000;
  var lonmax = -1000;
  var zoom = 1;
  var osm_map;      // Standard Open Street Map
  var tah_map;      // Tiles and Home Renderer
  var ocm_map;      // Open Cycle Map (mit Höhenlinien, Rattouren, ... )
  var bilder;
  var fname,maptype;
  var tcols = new Array("#ff00ff","#ff0000","#0000ff","#00ff00","#00ffff");   // Trackfarben
  var rcols = new Array("#800080","#800000","#000080","#008000","#008080");   // Routenfarben
  var tracks,waypoints,routes;
  var tracklens,routlens;
  var profile;
  var trackraufs,trackrunts;
  var routeNames,trackNames;
  var GPX2GM_Path = "";                                           // Pfad dieser Scriptdatei ermitteln
  var scr = document.getElementsByTagName("script");
  for (var i=0; i<scr.length; i++) {
    if (scr[i].src && scr[i].src.length) {
      var path = scr[i].src;
      var pos = path.search("GPX2GM.js");
      if (pos != -1) {
        GPX2GM_Path = path.substring(0,pos);
        break;
      }
    }
  }
  var cameraIcon = new GIcon();                                   // GoogleMaps Icon
  cameraIcon.image = GPX2GM_Path+CameraSymb[0];                   // Kamera Marker (Wegepunkt ist Bildposition)
  cameraIcon.iconSize = new GSize(CameraSymb[1],CameraSymb[2]);
  cameraIcon.iconAnchor = new GPoint(CameraSymb[3],CameraSymb[4]);
  cameraIcon.shadow = GPX2GM_Path+CameraShadow[0];
  cameraIcon.shadowSize = new GSize(CameraShadow[1],CameraShadow[2]);
  cameraIcon.infoWindowAnchor = new GPoint(10.0,5.0);

  var textIcon = new GIcon(G_DEFAULT_ICON);
  textIcon.image = GPX2GM_Path+WayPointSymb[0];                   // Text Marker (Normaler Wegepunkt)
  textIcon.shadow = GPX2GM_Path+WayPointShadow[0];
  textIcon.iconSize = new GSize(WayPointSymb[1],WayPointSymb[2]);
  textIcon.shadowSize = new GSize(WayPointShadow[1],WayPointShadow[2]);
  textIcon.iconAnchor = new GPoint(WayPointSymb[3],WayPointSymb[4]);
  textIcon.infoWindowAnchor = new GPoint(5,1);

  var markerIcon = new GIcon();
  var movemarker;                                                 // Move Marker (Anzeige Cursorposition über Höhenprofil)
  markerIcon.image = GPX2GM_Path + "marker.gif";
  markerIcon.iconSize = new GSize(11.0,11.0);                     // GoogleMaps Größe in Pixel
  markerIcon.iconAnchor = new GPoint(5.0,5.0);
  var markerinfo = document.createElement("div");
  markerinfo.style.position = "absolute";
  markerinfo.style.visibility = "hidden";
  markerinfo.style.border = "1px solid black";
  markerinfo.style.backgroundColor = "white";

  var div = document.getElementById(id);                          // DIV Element für Header und Karte, aus Haupt-Seite
  var w = div.offsetWidth;
  var h = div.offsetHeight;
  var MapHead = document.createElement("div");                    // Kopfbereich
  MapHead.id = "map_head"+id;
  MapHead.style.margin = "0px";
  MapHead.style.padding = "1px";
  MapHead.style.lineHeight = MapHeadHeight + "px";                // von Layout.js
  MapHead.appendChild(document.createTextNode(": "));
  var mapdiv = document.createElement("div");                     // Kartenbereich
  mapdiv.id = "map_"+id;
  mapdiv.style.width = w + "px";
  while (div.hasChildNodes())     div.removeChild(div.firstChild);
  if (!Legende)           MapHead.style.display = "none";
  div.appendChild(MapHead);
  div.appendChild(mapdiv);
  if (Legende)            mapdiv.style.height = h-mapdiv.offsetTop + MapHead.offsetTop + "px";
  else                    mapdiv.style.height = h+"px";
  var gmob = document.getElementById("map_"+id);
  var map = new GMap2(gmob);                                      // GoogleMaps DIV zuweisen
  gmob.style.backgroundPosition = "center";
  gmob.style.backgroundRepeat = "no-repeat";
  gmob.style.backgroundImage = "url(" + GPX2GM_Path + "warten.png)";
  if (LargeMapControl)    map.addControl(new GLargeMapControl()); // GoogleMaps Kontroll Element zuweisen
  else                    map.addControl(new GSmallMapControl());
  if (OverviewMapControl) map.addControl(new GOverviewMapControl());
  map.addMapType(G_PHYSICAL_MAP);
  //
  // -------------------------------------- Open Street Map
  var copyrightCollection = new GCopyrightCollection('Kartendaten &copy; 2009 <a href="http://www.openstreetmap.org/">OpenStreetMap</a> Contributors');
  copyrightCollection.addCopyright(new GCopyright(1,new GLatLngBounds(new GLatLng(-90,-180),new GLatLng(90,180)),0,
                                    '(<a rel="license" href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>)'));
  var tilelayers_mapnik = new Array();
  tilelayers_mapnik[0] = new GTileLayer(copyrightCollection,0,18); // GoogleMaps Layer definieren
  tilelayers_mapnik[0].getTileUrl = function(a,z) { return "http://tile.openstreetmap.org/" + z + "/" + a.x + "/" + a.y + ".png"; };
  tilelayers_mapnik[0].isPng = function() { return true; }
  tilelayers_mapnik[0].getOpacity = function() { return 1.0; }
  osm_map = new GMapType(tilelayers_mapnik,new GMercatorProjection(19),"OSM",{ urlArg: 'mapnik',linkColor: '#000000' });
  map.addMapType(osm_map);
  //
  // -------------------------------------- Tile & Home
  var copyrightCollection = new GCopyrightCollection('Kartendaten &copy; 2009 <a href="http://www.openstreetmap.org/">OpenStreetMap</a> Contributors');
  copyrightCollection.addCopyright(new GCopyright(1,new GLatLngBounds(new GLatLng(-90,-180),new GLatLng(90,180)),0,
                                    '(<a rel="license" href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>)'));
  var tilelayers_tah = new Array();
  tilelayers_tah[0] = new GTileLayer(copyrightCollection,0,18);    // GoogleMaps Layer definieren
  tilelayers_tah[0].getTileUrl = function(a,z) { return "http://tah.openstreetmap.org/Tiles/tile/" + z + "/" + a.x + "/" + a.y + ".png"; };
  tilelayers_tah[0].isPng = function()      { return true; }
  tilelayers_tah[0].getOpacity = function() { return 1.0; }
  tah_map = new GMapType(tilelayers_tah,new GMercatorProjection(19),"OSM T&H",{ urlArg: 'tah',linkColor: '#000000',minResolution:0,maxResolution:17 });
  map.addMapType(tah_map);
  //
  // -------------------------------------- Open Cycle Map
  var copyrightCollection = new GCopyrightCollection('Kartendaten &copy; 2009 <a href="http://www.openstreetmap.org/">OpenStreetMap</a> Contributors');
  copyrightCollection.addCopyright(new GCopyright(1,new GLatLngBounds(new GLatLng(-90,-180),new GLatLng(90,180)),0,
                                    '(<a rel="license" href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>)'));
  var tilelayers_ocm = new Array();
  tilelayers_ocm[0] = new GTileLayer(copyrightCollection,0,18);     // GoogleMaps Layer definieren
  tilelayers_ocm[0].getTileUrl = function(a,z)  { return "http://andy.sandbox.cloudmade.com/tiles/cycle/" + z + "/" + a.x + "/" + a.y + ".png"; };
  tilelayers_ocm[0].isPng = function()          { return true; }
  tilelayers_ocm[0].getOpacity = function()     { return 1.0; }
  ocm_map = new GMapType(tilelayers_ocm,new GMercatorProjection(19),"OSMcycle",{ urlArg: 'ocm',linkColor: '#000000',minResolution:7,maxResolution:15 });
  map.addMapType(ocm_map);
//
// "auto","crosshair","default","help","move","pointer","text","wait","hand","progress","not-allowed","no-drop","vertical-text","all-scroll"
  map.getDragObject().setDraggableCursor("auto");
//
  map.addControl(new GMenuMapTypeControl());
//  map.addControl(new GMapTypeControl());
//  map.addControl(new GHierarchicalMapTypeControl());
//  map.addMapType(G_SATELLITE_3D_MAP);                         // derzeit deaktiviert (benötigt Plugin)
  map.addControl(new GScaleControl());
  map.enableScrollWheelZoom();
  map.getPane(G_MAP_FLOAT_PANE).appendChild(markerinfo);
//  GEvent.addListener(map,"maptypechanged",function()  {dieses.rescale()});
  var hp = document.getElementById(id_hp);                      // DIV des Höhenprofils
  var hp_diag;
  if (hp)     hp_diag = new plot(id_hp);
  //
  // ------------------------------------------ resized
  this.resized = function() {
    actMap = map.getCurrentMapType().getName();
    map.checkResize();
  }
  //
  // Höheninformation abrufen
/*
  GEvent.addListener(map, "click", function(overlay,point) {
    if (point) {
//alert ("lat: "+point.lat()+"   lon: "+point.lng());
      // === call the altitude proxy server ===
      window.open("test.php","testwin");
      //GDownloadUrl('test.php', function(data) {
      GDownloadUrl('altitude.php?lat=' +point.lat()+ '&lng=' +point.lng(), function(data) {
        // === Decode the reply ===
alert ("data: "+data);
        var doc = GXml.parse(data);
        var altitude = parseInt(GXml.value(doc));
        // === Display the result ===
        map.openInfoWindow(point, "H&ouml;he: " +altitude+ " m");
      });
    }
  });
*/
  //
  // ------------------------------------------  Spur
  this.Spur = function(fn,mpt) {
    //var mc = map.getContainer();
    if      (mpt == "osm_map")    maptype = osm_map;
    else if (mpt == "tah_map")    maptype = tah_map;
    else if (mpt == "ocm_map")    maptype = ocm_map;
    else                          maptype = mpt;
    if (fname != fn) {
      fname = fn;
      GDownloadUrl(fname,function(data,responseCode) {
        if (responseCode != 200 && responseCode != 0 ) {      // 0 wenn lokal (Test)
          alert("Beim Oeffnen der Datei "+fname+" ist der Fehler "+responseCode+" aufgetreten!");
          return;
        }
        dieses.parseGPX(data);
        dieses.setMapHead();
        zoom = map.getBoundsZoomLevel(new GLatLngBounds(new GLatLng(latmin,lonmin),new GLatLng(latmax,lonmax)));  // sw,ne
        dieses.rescale();                 // GoogleMaps GLatLngBounds: Rechteck auf Karte
        map.setMapType(maptype);          // GoogleMaps Kartentyp festlegen
//        dieses.show("wtr");             // ???
        dieses.checkBoxes();
      } );
    }
    else {
//      dieses.show("wtr");               // ???
      dieses.rescale();                   // rescale bei Click auf angezeigte Karte
      dieses.checkBoxes();
    }
  } // Spur

  var chkwpt,chktrk,chkrt;
  //
  // ------------------------------------------  setMapHead
  this.setMapHead = function() {
    var name = fname.replace(/.+\//,"");
    MapHead.innerHTML = "<span style='font-Size:"+FSizeHV+"px;color:#0000ff;cursor:default'>" + name + ":&nbsp;&nbsp;&nbsp;</span>";
    if (waypoints.length) {
      if (waypoints.length == 1)       var texte=new Array("Wegpunkt" + String.fromCharCode(160));
      else if (waypoints.length > 1)   var texte=new Array("Wegpunkte" + String.fromCharCode(160));
      chkwpt = new JB_CheckBoxGroup(MapHead.id,texte,ID+"_wpt",["black"],Legende_wpt,dieses.checkBoxes);
    }
    if (tracks.length) {
      var texte = new Array();
      if (tracks.length == 1)
        texte[0] = "Track("+Number(tracklens[0].toPrecision(10).toString(10))+"km, "
                  + Number(trackraufs[0].toPrecision(10).toString(10))+"m "+String.fromCharCode(8593)+", "
                  + Number(trackrunts[0].toPrecision(10).toString(10))+"m "+String.fromCharCode(8595)+") "+String.fromCharCode(160);
      else if (tracks.length > 1) {
        texte[0] = "Track("+Number(tracklens.sum().toPrecision(10).toString(10))+"km, "
                  + Number(trackraufs.sum().toPrecision(10).toString(10))+"m "+String.fromCharCode(8593)+", "
                  + Number(trackrunts.sum().toPrecision(10).toString(10))+"m "+String.fromCharCode(8595)+") "+String.fromCharCode(160);
        for (var i=0;i<tracks.length;i++) {
          texte[i+1] = trackNames[i]+"("+Number(tracklens[i].toPrecision(10).toString(10))+"km, "
                      + Number(trackraufs[i].toPrecision(10).toString(10))+"m "+String.fromCharCode(8593)+", "
                      + Number(trackrunts[i].toPrecision(10).toString(10))+"m "+String.fromCharCode(8595)+") "+String.fromCharCode(160);
        }
      }
      chktrk = new JB_CheckBoxGroup(MapHead.id,texte,ID+"_trk",tcols,Legende_trk,dieses.checkBoxes);
    }
    if (routes.length) {
      var texte = new Array()
      if (routes.length == 1)
        texte[0] = "Route("+Number(routlens[0].toPrecision(10).toString(10))+"km) "+String.fromCharCode(160);
      else if (routes.length > 1) {
        texte[0] = "Routen("+Number(routlens.sum().toPrecision(10).toString(10))+"km) "+String.fromCharCode(160);
        for (var i=0;i<routes.length;i++)     texte[i+1] = routeNames[i]+"("+Number(routlens[i].toPrecision(10).toString(10))+"km)";
      }
      chkrt = new JB_CheckBoxGroup(MapHead.id,texte,ID+"_rt",rcols,Legende_rte,dieses.checkBoxes);
    }
  } // setMapHead
  //
  // ------------------------------------------  checkBoxes
  this.checkBoxes = function(obj,ele) {
    var what = "";
    if (chkwpt && chkwpt.status[0])     what += "w";
    if (chktrk && chktrk.status[0])     what += "t";
    if (chkrt  && chkrt.status[0] )     what += "r";
    dieses.show(what);
  }
  //
  // ------------------------------------------  parseGPX
  this.parseGPX = function(data) {
    var entf = new this.Entfernung();
    tracks = new Array();
    trackNames = new Array();
    tracklens = new Array() ;
    profile = new Array();
    var hoeh = new this.Hoehenmeter();
    trackraufs = new Array();
    trackrunts = new Array();
    load = false;
    latmin = 1000;
    latmax = -1000;
    lonmin = 1000;
    lonmax = -1000;
    var xml = GXml.parse(data);
    var trk = xml.documentElement.getElementsByTagName("trk");  // Tracks
    //
    for (var k=0; k<trk.length; k++) {                          // Tracks - Loop
      var trkseg = trk[k].getElementsByTagName("trkseg");       // Trackssegmente
      var name = trk[k].getElementsByTagName("name");
      var desc = trk[k].getElementsByTagName("desc");
      if (name.length && name[0].firstChild && name[0].firstChild.length)
        trackNames[k] = name[0].firstChild.data;
      else if (desc.length && desc[0].firstChild && desc[0].firstChild.length)
        trackNames[k] = desc[0].firstChild.data;
      else
        trackNames[k] = "Track "+k;
      var track = new Array();
      var profil = new Array();
      var tracklen = 0;
      //
      for (var j=0; j<trkseg.length; j++) {                     // Tracksegmente - Loop
        var trkpts = trkseg[j].getElementsByTagName("trkpt");   // Trackpunkte
        var hp_x0 = 0;
        if (HP_verbinde && k > 0)       hp_x0 = tracklens.sum() ;
        hoeh.init(NaN);
        //
        for (var i=0; i<trkpts.length; i++) {                   // Trackpunkte - Loop
          var lat = parseFloat(trkpts[i].getAttribute("lat"));
          var lon = parseFloat(trkpts[i].getAttribute("lon"));
          if (i == 0)           entf.init(lat,lon);
          tracklen += entf.rechne(lat,lon);
          if (lat < latmin)     latmin = lat;
          if (lat > latmax)     latmax = lat;
          if (lon < lonmin)     lonmin = lon;
          if (lon > lonmax)     lonmax = lon;
          track.push(new GLatLng(lat,lon));                     // GoogleMaps Punkt auf Karte
          if (trkpts[i].getElementsByTagName("ele").length && trkpts[i].getElementsByTagName("ele")[0].hasChildNodes()) {
            var h = parseFloat(trkpts[i].getElementsByTagName("ele")[0].firstChild.data);
            if (i == 0)         hoeh.init(h);
            else                hoeh.rechne(h);
            profil.push({x:tracklen+hp_x0,y:h,lat:lat,lon:lon});
          }
        }
      }
      tracks.push(track);
      trackraufs.push(Math.round(hoeh.hm()*10)/10);
      trackrunts.push(Math.round(hoeh.tm()*10)/10);
      tracklens.push(Math.round(tracklen*10)/10);
      profile.push(profil);
    }
    var rte = xml.documentElement.getElementsByTagName("rte");  // Routen
    routes = new Array();
    routeNames = new Array();
    routlens = new Array();
    for (var j=0; j<rte.length; j++) {
      var rtepts = rte[j].getElementsByTagName("rtept");
      var route = new Array();
      var routlen = 0;
      var name = rte[j].getElementsByTagName("name");
      if (name.length && name[0].firstChild && name[0].firstChild.length)
        routeNames[j] = name[0].firstChild.data;
      else
        routeNames[j] = "Route "+j;
      for (var i=0; i<rtepts.length; i++) { // Zwischenziele
        var lat = parseFloat(rtepts[i].getAttribute("lat"));
        var lon = parseFloat(rtepts[i].getAttribute("lon"));
        if (i == 0) entf.init(lat,lon) ;
        routlen += entf.rechne(lat,lon);
        if (lat < latmin)     latmin = lat;
        if (lat > latmax)     latmax = lat;
        if (lon < lonmin)     lonmin = lon;
        if (lon > lonmax)     lonmax = lon;
        route.push(new GLatLng(lat,lon));                             // GoogleMaps Punkt auf Karte
        var ext = rtepts[i].getElementsByTagName("extensions");
        if (ext.length) {
          var rpts = JB_GetElementsByTagNameNS(ext[0],"gpxx","rpt");  // Routenpunkte
          for (var k=0; k<rpts.length; k++) {
            var lat = parseFloat(rpts[k].getAttribute("lat"));
            var lon = parseFloat(rpts[k].getAttribute("lon"));
            routlen += entf.rechne(lat,lon);
            if (lat < latmin)       latmin = lat;
            else if (lat > latmax)  latmax = lat;
            if (lon < lonmin)       lonmin = lon;
            else if (lon > lonmax)  lonmax = lon;
            route.push(new GLatLng(lat,lon));
          }
        }
      }
      routes.push(route);
      routlens.push(Math.round(routlen*10)/10);
    }
    var wpts = xml.documentElement.getElementsByTagName("wpt");   // Waypoints
    waypoints = new Array();
    for (var i=0; i<wpts.length; i++) {                           // Wegpunktdaten
      var wpt = wpts[i];
      var lat = parseFloat(wpt.getAttribute("lat"));
      var lon = parseFloat(wpt.getAttribute("lon"));
      if (lat < latmin)     latmin = lat;
      if (lat > latmax)     latmax = lat;
      if (lon < lonmin)     lonmin = lon;
      if (lon > lonmax)     lonmax = lon;
      var waypoint = new Object();
      waypoint.lat = lat;
      waypoint.lon = lon;
      waypoint.name = "";
      waypoint.cmt = "";
      waypoint.desc = "";
      var name = wpt.getElementsByTagName("name");              // Wegepunkt Name
      var cmt = wpt.getElementsByTagName("cmt");                // Wegepunkt Kommentar (für GPS)
      var desc = wpt.getElementsByTagName("desc");              // Wegepunkt Beschreibung (für Software)
      if (name.length && name[0].firstChild && name[0].firstChild.length)
        waypoint.name = name[0].firstChild.data;
      if (cmt.length && cmt[0].firstChild && cmt[0].firstChild.length)
        waypoint.cmt = cmt[0].firstChild.data;
      if (desc.length && desc[0].firstChild && desc[0].firstChild.length)
        waypoint.desc = desc[0].firstChild.data;
      waypoints.push(waypoint);
    }
    load = true;
  } // parseGPX
  //
  // ------------------------------------------  showWpts
  this.showWpts = function() {
    if (load) {
      delete bilder;
      bilder = new Array();
      for (var i=0; i<waypoints.length; i++) {
        var waypoint = waypoints[i];
        if (checkImageName(waypoint.name)) {
          bilder[i] = new Image();
          bilder[i].src = trackPath(fname) + waypoint.name;
          map.addOverlay(createImgMarker(waypoint, false));       // lokales Bild
        }
        else if (checkImageUrl(waypoint.name, waypoint.desc)) {
          bilder[i] = new Image();
          bilder[i].src = waypoint.desc;                          // Bild aus WWW
          map.addOverlay(createImgMarker(waypoint, true));        // Konvention: URL in <desc>
        }
        //else if (waypoint.name.length || waypoint.cmt.length)
        else if (waypoint.name.length)
          map.addOverlay(createTxtMarker(waypoint));
        else
          map.addOverlay(new GMarker(new GLatLng(waypoint.lat,waypoint.lon)));    // GoogleMaps GMarker: Markierungs Overlay
      }
    }
  } // showWpts
  //
  // ------------------------------------------  showTracks
  this.showTracks = function() {
    if (load) {
      if (hp) {
        if (tracks.length > 1) {
          for (var i=0; i<profile.length; i++) {
            if (profile[i].length && chktrk.status[i+1])   hp_diag.scale(profile[i]);
          }
        }
        else if (tracks.length == 1) {
          if (profile[0].length)            hp_diag.scale(profile[0]);
        }
        hp_diag.frame(50,35,"Strecke in km","&nbsp;<br />M<br />e<br />t<br />e<br />r");
      }
      if (tracks.length > 1) {
        for (var i=0; i<tracks.length; i++) {
          if (chktrk.status[i+1]) {
            map.addOverlay(new GPolyline(tracks[i],tcols[i%tcols.length],2,0.8));
            if (hp && profile[i].length)    hp_diag.plot(profile[i],tcols[i%tcols.length]);
          }
        }
        if (HP_verbinde) {
          var hp_t = new Array();
          for (var i=0; i<profile.length; i++) {
            if (chktrk.status[i+1])         hp_t = hp_t.concat(profile[i]);
          }
          if (hp_t.length)   hp_diag.markeron(hp_t,dieses.markertstart,dieses.markerstop,dieses.markermove,"Linie") ;
        }
      }
      else if (tracks.length == 1) {
        if (chktrk.status[0]) {
          map.addOverlay(new GPolyline(tracks[0],tcols[0],2,0.8));
          if (hp && profile[0].length) {
            hp_diag.plot(profile[0],tcols[0]);
            hp_diag.markeron(profile[0],dieses.markertstart,dieses.markerstop,dieses.markermove,"Linie") ;
          }
        }
      }
    }
  } // showTracks
  //
  // ------------------------------------------  showRoutes
  this.showRoutes = function() {
    if (load) {
      if (routes.length > 1) {
        for (var i=0; i<routes.length; i++) {
          if (chkrt.status[i+1])      map.addOverlay(new GPolyline(routes[i],rcols[i%tcols.length],2,0.8));
        }
      }
      else if (routes.length == 1) {
        if (chkrt.status[0])          map.addOverlay(new GPolyline(routes[0],rcols[0],2,0.8));
      }
    }
  } // showRoutes
  //
  // ------------------------------------------  show
  this.show = function(what) {
    map.clearOverlays() ;
    if (hp)     hp_diag.clear();
//    dieses.rescaleF();
    if (what.search("w") != -1 )    dieses.showWpts();
    if (what.search("t") != -1 )    dieses.showTracks();
    if (what.search("r") != -1 )    dieses.showRoutes();
  } // show
  //
  // ------------------------------------------  rescale
  this.rescale  =  function() {
    if (load) {
      map.setCenter(new GLatLng((latmax+latmin)/2,(lonmax+lonmin)/2),zoom);    // GoogleMaps Initialisieren
    }
  } // rescale
  //
  // ------------------------------------------  Hoehenmeter
  this.Hoehenmeter  =  function() {
    var anf = NaN;      // Starthoehe
    var akt = NaN;      // aktuelle Hoehe
    var alt = NaN;      // vorheriger Wert
    var med = NaN;      // Mittelwert alt | akt
    var low = NaN;      // min Hoehenwert
    var high = NaN;     // max Hoehenwert
    var rauf = NaN;     // Anstieg
    var runter = NaN;   // Gefälle
    var filter = NaN;   // Mindestgefaelle
    this.init = function(a) {
      high = rauf = runter = NaN;
      alt = akt = med = low = anf = parseFloat(a);
      filter = HoehenFilter;
      if (isNaN(filter))      filter = parseFloat(10);
    }
    this.rechne = function(a) {
      akt = parseFloat(a);
      if (! isNaN(alt))       med = (alt+akt)/2;
      else                    med = akt;
      alt = akt;
      if (isNaN(high)) {
        if (med > low)        high = med;   // neue Steigung
      } else if ((high-med) >= filter) {    // Steigung bewerten
        if (isNaN(rauf))      rauf = parseFloat(0);
        rauf += (high-low);
        low = med;
        high = NaN;
        return;
      }
      if (med < low)          low = high = med;
      if (med > high)         high = med;
    }
    this.hm = function() {          // Hoehenmeter
      if (isNaN(rauf))        rauf = parseFloat(0);
      if (! isNaN(high) && ((high-low) >= filter))    rauf += (high-low);   // evtl. letzter Höhenwert
      return(rauf);
    }
    this.tm = function() {          // Tiefenmeter
      if (isNaN(rauf))        rauf = parseFloat(0);
      runter = rauf - alt + anf;
      akt = (alt > anf) ? alt-anf : anf-akt;
      if (akt < filter)   		runter = rauf;
      if (isNaN(runter))  		runter = parseFloat(0);
      return(runter);
    }
  } // Hoehenmeter
  //
  // ------------------------------------------  Entfernung
  this.Entfernung = function() {
    var ls,bs;
    this.init = function(b,l) {
      ls = l;
      bs = b;
    }
    this.rechne = function(b,l) {
      var e = new GLatLng(bs,ls).distanceFrom(new GLatLng(b,l));      // GoogleMaps GLatLng: Punkt auf Karte
      ls = l;
      bs = b;
      return e/1000;
    }
  } // Entfernung
  //
  // ------------------------------------------  markertstart
  this.markertstart = function() {
    movemarker = new GMarker(new GLatLng(profile[0][0].lat,profile[0][0].lon),markerIcon);
    map.addOverlay(movemarker);
    markerinfo.style.visibility = "visible";
  } // markerstart
  //
  // ------------------------------------------  markerstop
  this.markerstop = function() {
    map.removeOverlay(movemarker);
    markerinfo.style.visibility = "hidden";
  } // markerstop
  //
  // ------------------------------------------  markermove
  this.markermove = function(p,a) {
    markerinfo.innerHTML = "Strecke:&nbsp;"+a.x.toFixed(1)+"km<br />H&ouml;he:&nbsp;"+Math.round(a.y)+"m";
    map.removeOverlay(movemarker);
    movemarker = new GMarker(new GLatLng(a.lat,a.lon),markerIcon);
    map.addOverlay(movemarker);         // GoogleMaps getZoom: Zoomstufe der Karte
    var point = map.getCurrentMapType().getProjection().fromLatLngToPixel(map.fromDivPixelToLatLng(new GPoint(0,0),true),map.getZoom());
    var offset = map.getCurrentMapType().getProjection().fromLatLngToPixel(movemarker.getPoint(),map.getZoom());
    var anchor = movemarker.getIcon().iconAnchor;
    var width = movemarker.getIcon().iconSize.width;
    var height = markerinfo.clientHeight;               // GoogleMaps GControlPosition: Position definieren
    var pos = new GControlPosition(G_ANCHOR_TOP_LEFT,new GSize(offset.x - point.x - anchor.x + width,offset.y - point.y -anchor.y -height));
    pos.apply(markerinfo);                            // GoogleMaps GSize: Größe definieren
  } // markermove
  //
  // ------------------------------------------  createImgMarker
  var createImgMarker = function(waypoint,uri) {
    var MarkerOptions = { icon:cameraIcon,title:waypoint.name };
    var MarkerImage = "";
    var MarkerText = "<br\/><strong>" + waypoint.name + "<\/strong>";       // Default Anzeige Name (wenn kein Kommentar)
    if (waypoint.cmt.length > 0)
      MarkerText = "<br\/><strong>" + waypoint.cmt + "<\/strong>";
    if (waypoint.desc.length > 0 && waypoint.cmt != waypoint.desc)
      MarkerText += ("<br\/>" + waypoint.desc);
    var marker = new GMarker(new GLatLng(waypoint.lat,waypoint.lon),MarkerOptions);
    GEvent.addListener(marker,"infowindowopen",function() {
      map.savePosition();
    } );
    GEvent.addListener(marker,"infowindowclose",function() {
      map.returnToSavedPosition();
    } );
//    GEvent.addListener(marker,"mouseover",function() {
//      marker.openInfoWindowHtml(waypoint.cmt);
//    } );
//    GEvent.addListener(marker,"mouseout",function() {
//      marker.closeInfoWindow();
//    } );
    var foto = new Image();
    foto.src = (uri) ? waypoint.desc : trackPath(fname) + waypoint.name;
    var width = foto.width;
    var height = foto.height;
    if (width > FotoWidth) {
      height = Math.floor(height*(FotoWidth/width));
      width = FotoWidth;
    }
    if (height > FotoHeight) {
      width = Math.floor(width*(FotoHeight/height));
      height = FotoHeight;
    }
    foto.onload = function() {
      width = foto.width;
      height = foto.height;
      if (width > FotoWidth) {
        height = Math.floor(height*(FotoWidth/width));
        width = FotoWidth;
      }
      if (height > FotoHeight) {
        width = Math.floor(width*(FotoHeight/height));
        height = FotoHeight;
      }
      MarkerImage = "<img width='"+width+"' height='"+height+"' src='"+foto.src+" '\/>";
      GEvent.addListener(marker,"click",function() {                    // GoogleMaps Event Listener
        marker.openInfoWindowHtml(MarkerImage + MarkerText);
      } );                                                              // GoogleMaps openInfoWindowHtml: Info Fenster mit HTML Inhalt
      return marker;
    }
    if (width > 10 && height > 10)    MarkerImage = "<img width='"+width+"' height='"+height+"' src='"+foto.src+"' \/>";
    else                              MarkerImage = "<img src='"+foto.src+"' \/>";
    GEvent.addListener(marker,"click",function() {                      // GoogleMaps Event Listener
      marker.openInfoWindowHtml(MarkerImage + MarkerText);
    } );
    return marker;
  } // createImgMarker
  //
  // ------------------------------------------  createTxtMarker
  var createTxtMarker = function(waypoint) {                            // GoogleMaps GIcon: Icon
    var MarkerOptions = { icon:textIcon,title:waypoint.name };
    var MarkerText = "<h2>" + waypoint.name + "<\/h2>";
    if (waypoint.cmt.length > 0 && waypoint.cmt != waypoint.name)     MarkerText += ("<strong>" + waypoint.cmt + "<\/strong>");
    if (waypoint.desc.length > 0 && waypoint.cmt != waypoint.desc)    MarkerText += ("<br\/>" + waypoint.desc);
    var marker = new GMarker(new GLatLng(waypoint.lat,waypoint.lon),MarkerOptions);
    GEvent.addListener(marker,"infowindowopen",function() {
      map.savePosition();
    } );
    GEvent.addListener(marker,"infowindowclose",function() {
      map.returnToSavedPosition();
    } );
    GEvent.addListener(marker,"click",function() {                      // GoogleMaps Event Listener
      marker.openInfoWindowHtml(MarkerText);
    });
    return marker;
  } // createTxtMarker
  //
  // ------------------------------------------  checkImageName
  var checkImageName = function(nam) {
    var ext = nam.substr(nam.lastIndexOf(".")+1).toLowerCase();               // Konvention:
    return(ext == "jpg" || ext == "jpeg" || ext == "png" || ext == "gif") ;   // wenn wpt name ist Bildname --> Bild anzeigen bei Click
  } //  checkImageName
  // ------------------------------------------  checkImageUrl
  var checkImageUrl = function(nam,desc) {
    var ext = nam.substr(nam.lastIndexOf(".")+1).toLowerCase();
    var uri = desc.substr(0,7).toLowerCase();                     // Konvention:
    return(ext == "url" && uri == "http://") ;                    // wenn wpt name ist Bild.url --> URL in <desc> anzeigen bei Click
  } //  checkImageUrl
} // makeMap
//
// -------------------------------------------- some functions
//
function JB_GetElementsByTagNameNS(ele,namespace,name) {
  var alltags = ele.getElementsByTagName("*");
  var tagname = namespace.toLowerCase()+":"+name.toLowerCase()
  var tags = new Array();
  for (var i=0; i<alltags.length; i++) {
    if (alltags[i].nodeName.toLowerCase() == tagname)     tags.push(alltags[i]);
  }
  return tags;
} // JB_GetElementsByTagNameNS(ele,namespace,name)
//
function JB_CheckBoxGroup(id,Texte,Label,Farbe,def_stat,clickFunc) {
  var dieses = this;
  var nbx = Texte.length;
  this.nboxen = nbx;
  this.status = new Array(nbx);
  for (var i=0; i<nbx; i++)     this.status[i] = def_stat;
  var ele;
  var box = document.createElement("div");
  box.style.cursor = "default";
  box.style.position = "absolute";
  box.style.display = "inline";
  box.style.height = "1.8em";
  box.style.overflow = "hidden";
  box.style.backgroundColor = "";
  box.style.zIndex = 1000;
  box.style.margin = "0";
  box.style.padding = "0";
  box.onmouseover = function() {
    this.style.height = "";
    this.style.overflow = "";
    this.style.backgroundColor = "#ffffff";
    this.style.paddingRight = "0.3em";
    this.style.paddingBottom = "0.2em";
  };
  box.onmouseout  = function() {
    this.style.height = "1.4em";
    this.style.overflow = "hidden";
    this.style.backgroundColor = "";
    this.style.paddingRight = "";
    this.style.paddingBottom = "";
  };
  for (var i=0; i<nbx; i++) {
    ele = document.createElement("input");
    ele.type = "checkbox";
    ele.id = Label + i;
    ele.nr = i;
    if (i == 0)     ele.onclick = function() {
      var l = nbx;
      var n = Label;
      var status = this.checked;
      dieses.status[this.nr] = status;
      for (var j=1; j<l; j++) {
        document.getElementById(n+j).checked = status;
        dieses.status[j] = status;
      }
      clickFunc(dieses,this);
    };
    else     ele.onclick = function() {
      var l = nbx;
      var n = Label;
      var status = false;
      for (var j=1; j<l; j++)     status |= document.getElementById(n+j).checked;
      document.getElementById(n+"0").checked = status;
      dieses.status[0] = (status == true);
      dieses.status[this.nr] = this.checked;
      clickFunc(dieses,this);
    };
    box.appendChild(ele);
    ele.checked = def_stat;
    ele = document.createElement("span");
    if (i == 0 && nbx == 1)     ele.style.color = Farbe[0];
    else if (i)                 ele.style.color = Farbe[(i-1)%Farbe.length];
    ele.appendChild(document.createTextNode(Texte[i]));
    box.appendChild(ele);
    if (i < Texte.length-1) box.appendChild(document.createElement("br"));
  }
  ele = document.getElementById(id);
  ele.appendChild(box);
  var spn = document.createElement("span"); // Platzhalter
  spn.appendChild(document.createTextNode(" X "+Texte[0]+" "));
  spn.style.visibility = "hidden";
  ele.appendChild(spn);
} // JB_CheckBoxGroup
//
function JB_addEvent(oTarget,sType,fpDest) {
  var oOldEvent = oTarget[sType];
  if (typeof oOldEvent != "function") {
    oTarget[sType] = fpDest;
  } else {
    oTarget[sType] = function(e) {
      oOldEvent(e);
      fpDest(e);
    }
  }
} // addEvent

// gra
// Version vom 28.5.09
// Jürgen Berkemeier
// www.j-berkemeier.de
function gra(ID) {
  var feld = document.getElementById(ID);
  var dv = document.createElement("div");
  var cont = feld.appendChild(dv);
  var buf = document.createElement("div");
  this.w = parseInt(feld.offsetWidth-1);
  this.h = parseInt(feld.offsetHeight-1);
  var maxbuf = 1;
  var bufsize = 1;
  var sp = document.createElement("div");
  var col = "#000000";
  sp.style.position = "absolute";
  sp.style.width = "1px";
  sp.style.height = "1px";
  sp.style.overflow = "hidden";
  sp.style.left = "0px";
  sp.style.top = "0px";
  sp.style.backgroundColor = col;
  this.setbuf = function(siz) {
    bufsize = maxbuf = Math.max(1,siz);
  }
  this.flush = function() {
    cont.appendChild(buf);
    buf = document.createElement("div");
    bufsize = maxbuf;
  }
  this.punkt = function(x,y,c) {
    if (x<0 || y<0 || x>this.w || y>this.h)             return;
    if (c != col) {
      col = c;
      sp.style.backgroundColor = col;
    }
    var pkt = sp.cloneNode(true);
    pkt.style.left = Math.round(x)+"px";
    pkt.style.top = Math.round(this.h-y)+"px";
    buf.appendChild(pkt);
    bufsize--;
    if (!bufsize)     this.flush();
  } // punkt
  this.ver_linie = function(x,y1,y2,c) {
    if (x < 0 || x > this.w)    return;
    if ((y1<0 && y2<0) || (y1>this.h && y2>this.h))     return;
    if (c != col) {
      col = c;
      sp.style.backgroundColor = col;
    }
    y1 = Math.max(0,Math.min(this.h,y1));
    y2 = Math.max(0,Math.min(this.h,y2));
    var vl = sp.cloneNode(true);
    vl.style.left = Math.round(x)+"px";
    vl.style.top = Math.round(this.h-Math.max(y1,y2))+"px";
    vl.style.height = Math.round(Math.abs(y2-y1)+1)+"px";
    buf.appendChild(vl);
    bufsize--;
    if (!bufsize)     this.flush();
  } // ver_linie
  this.hor_linie = function(x1,x2,y,c) {
    if (y < 0 || y > this.h)        return;
    if ((x1<0 && x2<0) || (x1>this.w && x2>this.w))     return;
    if (c != col) {
      col = c;
      sp.style.backgroundColor = col;
    }
    x1 = Math.max(0,Math.min(this.w,x1));
    x2 = Math.max(0,Math.min(this.w,x2));
    var hl = sp.cloneNode(true);
    hl.style.left = Math.round(Math.min(x1,x2))+"px";
    hl.style.top = Math.round(this.h-y)+"px";
    hl.style.width = Math.round(Math.abs(x2-x1)+1)+"px";
    buf.appendChild(hl);
    bufsize--;
    if (!bufsize)           this.flush();
  } // hor_linie
  this.linie = function(xs,ys,xe,ye,c) {
//  var flag = (maxbuf == 1);
//  if (flag) maxbuf = 1000;
    xs = Math.round(xs);
    xe = Math.round(xe);
    ys = Math.round(ys);
    ye = Math.round(ye);
    var dx = xe-xs;
    var dy = ye-ys;
    if (dx == 0 && dy == 0)     this.punkt(xs,ys,c)
    else if (dx == 0)           this.ver_linie(xs,ys,ye,c);
    else if (dy == 0)           this.hor_linie(xs,xe,ys,c);
    else {
      var adx = Math.abs(dx);
      var ady = Math.abs(dy);
      var d = Math.min(adx,ady);
      dx = dx/d;
      dy = dy/d;
      if (adx == ady) {
        for (var x=xs,y=ys,i=0; i<=d; x+=dx,y+=dy,i++)          this.punkt(x,y,c);
      }
      else if (adx < ady) {
        var dd = dy/Math.abs(dy);
        this.ver_linie(xs,ys,ys+dy/2-dd,c);
        for (var x=xs+dx,y=ys+dy/2,i=1; i<d; x+=dx,y+=dy,i++)   this.ver_linie(x,y,y+dy-dd,c);
        this.ver_linie(xe,ye-(dy+dd)/2,ye,c);
      }
      else {
        var dd=dx/Math.abs(dx);
        this.hor_linie(xs,xs+dx/2-dd,ys,c);
        for (var x=xs+dx/2,y=ys+dy,i=1; i<d; x+=dx,y+=dy,i++)   this.hor_linie(x,x+dx-dd,y,c);
        this.hor_linie(xe-(dx+dd)/2,xe,ye,c);
      }
    }
  //  if (flag) {maxbuf=1;this.flush();}
  } // linie
  //
  this.text = function(x,y,size,color,text,align) {
    var align_h = "m";
    var align_v = "m";
    if (align && align.length) {
      align_h = align.substr(0,1);
      if (align.length > 1) align_v = align.substr(1,1);
    }
    var pkt = document.createElement("div");
    pkt.style.position = "absolute";
    pkt.style.fontSize = size+"px";
    pkt.style.color = color;
    pkt.style.textAlign = "center";
    pkt.innerHTML = text;
    cont.appendChild(pkt);
    switch(align_h) {
      case "l": default: pkt.style.left = Math.round(x) + "px"; break;
      case "m": pkt.style.left = Math.round(x) - pkt.offsetWidth/2 + "px"; break
      case "r": pkt.style.left = Math.round(x) - pkt.offsetWidth + "px"; break
    }
    switch(align_v) {
      case "o": default: pkt.style.top = Math.round(this.h-y) + "px"; break;
      case "m": pkt.style.top = Math.round(this.h-y) - pkt.offsetHeight/2 + "px"; break;
      case "u": pkt.style.top = Math.round(this.h-y) - pkt.offsetHeight + "px"; break;
    }
  } // text
  //
  this.del = function() {
    feld.removeChild(cont);
    delete cont;
    delete buf;
    var dv = document.createElement("div");
    cont = feld.appendChild(dv);
    buf = document.createElement("div");
    bufsize = maxbuf;
  } // del
} // gra

// plot
// Version vom 12. 2. 2009
// Jürgen Berkemeier
// www.j-berkemeier.de
var plot = function(id) {
  var JB_log10 = function(x) { return Math.log(x)/Math.LN10; }
  var JB_toString = function(n) { return Number(n.toPrecision(15)).toString(10); }
  var JB_makediv = function(parentnode,id,x0,y0,width,height) {
    var ele = document.createElement("div");
    ele.id = id;
    ele.style.position = "absolute";
    ele.style.left = x0 + "px";
    ele.style.top = y0 + "px";
    ele.style.width = width + "px";
    ele.style.height = height + "px";
    parentnode.appendChild(ele);
    return ele;
  }
  var plotid = id+"plot";
  var plotidm = id+"plotm";
  var idxlabel = id+"xlabel";
  var idylabel = id+"ylabel";
  var xmin = 0,xmax = 0,ymin = 0,ymax = 0;
  var xfak = 0,yfak = 0;
  var dx,dy,fx,fy;
  var gr = null;
  var xlabel = null;
  var ylabel = null;
  var feld = document.getElementById(id) ;
  var w = parseInt(feld.offsetWidth-1);
  var h = parseInt(feld.offsetHeight-1);
  var ifeld = document.createElement("div");
  ifeld.style.position = "absolute";
  ifeld.style.width = w + "px";
  ifeld.style.height = h + "px";
  feld.appendChild(ifeld);
  //
  this.scale = function(a) {
    if (xmin == xmax) {
      xmax = xmin = a[0].x;
      ymax = ymin = a[0].y;
    }
    for (var i=0; i<a.length; i++) {
      var t = a[i];
      if (t.x < xmin)   xmin = t.x;
      if (t.x > xmax)   xmax = t.x;
      if (t.y < ymin)   ymin = t.y;
      if (t.y > ymax)   ymax = t.y;
    }
    if (xmax == xmin) {
      xmin -= 0.5;
      xmax += 0.5;
    }
    dx = xmax - xmin ;
    fx = Math.pow(10,Math.floor(JB_log10(dx))-1);
    xmin = Math.floor(xmin/fx)*fx;
    xmax = Math.ceil(xmax/fx)*fx;
    if (ymax == ymin) {
      ymin -= 0.5;
      ymax += 0.5;
    }
    dy = ymax - ymin ;
    if (dy < 100)   dy = 100;           // Peter
//    fy = Math.pow(10,Math.floor(JB_log10(dy))-1);
    fy = Math.pow(20,Math.floor(JB_log10(dy))-1);
//    ymin = Math.floor(ymin/fy)*fy;
//    ymax = Math.ceil(ymax/fy)*fy;
    ymin = Math.floor(ymin/fy*0.9)*fy; // Peter
    ymax = Math.ceil(ymax/fy*1.07)*fy;  // Peter
  } // plot.scale
  //
  this.clear = function() {
    ifeld.innerHTML = "";
    xmax = xmin = ymax = ymin = xfak = yfak = 0;
  } // plot.clear
  //
  this.frame = function(x0,y0,xl,yl) {
    ifeld.innerHTML = "";
    JB_makediv(ifeld,plotid,x0,0,w-x0,h-y0);
    JB_makediv(ifeld,idxlabel,x0,h-y0,w-x0,y0);
    JB_makediv(ifeld,idylabel,0,0,x0,h-y0);
    JB_makediv(ifeld,plotidm,x0,0,w-x0,h-y0);
    xlabel = new gra(idxlabel);
    ylabel = new gra(idylabel);
    gr = new gra(plotid);
    gr.setbuf(1000);
    xfak = gr.w/(xmax-xmin);
    yfak = gr.h/(ymax-ymin);
    xlabel.text(xlabel.w/2,0,16,"black",xl,"mu");
    ylabel.text(5,ylabel.h/2,16,"black",yl,"mm");
    var tx = 100*dx/gr.w;
    var ty = (gr.h < 250) ?  50*dy/gr.h : 100*dy/gr.h;
    var tx10 = Math.pow(10,Math.floor(JB_log10(tx)));
    tx = Math.round(tx/tx10);
    var ty10 = Math.pow(10,Math.floor(JB_log10(ty)));
    ty = Math.round(ty/ty10);
    tx = Number(String(tx).replace(/3/,"2").replace(/[4567]/,"5").replace(/[89]/,"10"));
    ty = Number(String(ty).replace(/3/,"2").replace(/[4567]/,"5").replace(/[89]/,"10"));
    tx *= tx10;
    ty *= ty10;
    var mxmin = Math.ceil(xmin/tx)*tx;
    var mymin = Math.ceil(ymin/ty)*ty;
    for (var x=mxmin; x<=xmax; x+=tx) {
      gr.linie((x-xmin)*xfak,0,(x-xmin)*xfak,gr.h,"gray");
      xlabel.text((x-xmin)*xfak,xlabel.h,14,"black",JB_toString(x),"mo");
    }
    for (var y=mymin; y<=ymax; y+=ty) {
      gr.linie(0,(y-ymin)*yfak,gr.w,(y-ymin)*yfak,"gray");
      ylabel.text(ylabel.w,(y-ymin)*yfak,14,"black",JB_toString(y),"rm");
    }
    var rahmen = new gra(plotid);
    rahmen.linie(       0,       0,rahmen.w,       0,"black");
    rahmen.linie(rahmen.w,       0,rahmen.w,rahmen.h,"black");
    rahmen.linie(rahmen.w,rahmen.h,       0,rahmen.h,"black");
    rahmen.linie(       0,rahmen.h,       0,       0,"black");
  } // plot.frame
  //
  this.plot = function(a,col) {
    for (var i=0; i<a.length-1; i++) {
      gr.linie(
       (a[i].x-xmin)*xfak,
       (a[i].y-ymin)*yfak,
       (a[i+1].x-xmin)*xfak,
       (a[i+1].y-ymin)*yfak,
       col);
     }
    gr.flush();
  } // plot.plot)
  //
  this.markeron = function(a,callback_over,callback_out,callback_move,markertype) {
    var dieses = this;
    var posx = 0;
    var mele = document.getElementById(plotidm);
    var pele = document.getElementById(plotid);
    var marker = document.createElement("div");
    marker.style.position = "absolute";
    marker.style.display = "none";
    if (markertype == "Punkt") {
      marker.style.fontSize = "32px";
      var txt = document.createTextNode(String.fromCharCode(8226)) ; // Kreis als Zeichen: &bull; oder &#8226; evtl auch 8729
      marker.appendChild(txt);
    }
    else {
      marker.style.top = "0";
      marker.style.height = gr.h + "px" ;
      marker.style.width = "1px";
      marker.style.backgroundColor = "black";
    }
    pele.appendChild(marker);
    mele.onmouseover = function(e) {
      if (!e)     e = window.event;
      e.cancelBubble = true;
      if (e.stopPropagation)        e.stopPropagation();
      marker.style.display = "";
      mele.onmousemove = function(e) {
        if (!e)   e = window.event;
        e.cancelBubble = true;
        if (e.stopPropagation)      e.stopPropagation();
        posx = e.layerX ? e.layerX : e.offsetX;
        var x = posx/xfak+xmin;
        var al = a.length;
        var p,pi;
        if (x <= a[0].x)            pi = 0;
        else if (x >= a[al-1].x)    pi = al-1;
        else {
          p = al/2;
          pi = Math.floor(p);
          var dp = Math.ceil(p/2);
          do {
            var apx = a[pi].x;
            if (x < apx) {
              p -= dp;
              if (p < 0)      p = 0;
            }
            else if (x > apx) {
              p += dp;
              if (p > al-1)   p = al-1;
            }
            else break;
            pi = Math.floor(p);
            dp = dp/2;
          } while (dp >= 0.5) ;
        }
        if (markertype == "Punkt") {
          marker.style.left = Math.round((a[pi].x-xmin)*xfak) - marker.offsetWidth/2 + "px";
          marker.style.top = Math.round(gr.h - (a[pi].y-ymin)*yfak) - marker.offsetHeight/2 + "px";
        }
        else {
          marker.style.left = Math.round((a[pi].x-xmin)*xfak) + "px";
        }
        if (callback_move && typeof(callback_move) == "function")   callback_move(pi,a[pi]);
        return false;
      }
      if (callback_over && typeof(callback_over) == "function")     callback_over();
      return false;
    }
    mele.onmouseout = function(e) {
      if (!e)     e = window.event;
      marker.style.display = "none";
      mele.onmousemove = null;
      if (callback_out && typeof(callback_out) == "function") callback_out();
      return false;
    }
  } // plot.markeron
  //
  this.markeroff = function() {
    var ele = document.getElementById(plotid);
    ele.onmousemove = null;
    ele.onmouseout = null;
  } // plot.markeroff
} // plot
//
JB_addEvent(window,"onresize",function() {
  var divs = document.getElementsByTagName("div");
  for (var i=0; i<divs.length; i++) {
    var div = divs[i];
    if (div.className) {
      var Klasse = div.className;
      var CN = Klasse.toLowerCase().indexOf("gpxview1");
      if (CN > -1) {
        if (div.id)     var Id = div.id;
        else {
          var Id = "map"+(Map_Nr++);
          div.id = Id;
        }
        window["Karte_"+Id].resized();
      }
    }
  }
  Layout(true);
} );
//
JB_addEvent(window,"onload",function() {
  Layout(false);
  if (document.getElementsByTagName && GBrowserIsCompatible()) {
    var Map_Nr = 0;
    var chkTyp = function(typString) {
      if (typString == kartenArr[0])      return G_NORMAL_MAP;
      if (typString == kartenArr[1])      return G_SATELLITE_MAP;
      if (typString == kartenArr[2])      return G_HYBRID_MAP;
      if (typString == kartenArr[3])      return G_PHYSICAL_MAP;
      if (typString == kartenArr[4])      return G_SATELLITE_3D_MAP;
      if (typString == kartenArr[5])      return "osm_map";
      if (typString == kartenArr[6])      return "tah_map";
      if (typString == kartenArr[7])      return "ocm_map";
      return G_HYBRID_MAP;
    } // chkTyp
    var divs = document.getElementsByTagName("div");
    var typ = G_HYBRID_MAP;
    var Id;
    for (var i=0; i<divs.length; i++) {
      var div = divs[i];
      if (div.className) {
        var Klasse = div.className;
        var CN = Klasse.toLowerCase().indexOf("gpxview1");
        if (CN > -1) {
          if (div.id)    Id = div.id;
          else {
            Id = "map"+(Map_Nr++);
            div.id = Id;
          }
          var GPX = Klasse.substring(CN).split()[0];
          GPX = GPX.split(":") ;
          if (GPX.length == 3) {
            typ = chkTyp(GPX[2]);
          }
          if (GPX[1].length) {
            actTrack = GPX[1];
            window["Karte_"+Id] = new makeMap(Id);
            window["Karte_"+Id].Spur(GPX[1],typ);
          }
        }
      }
    }
    // var buttons = document.getElementsByName("button");    // das kann der Internet Explorer nicht :-(
    var buttons = document.getElementsByTagName("div");
    for (var i=0; i<buttons.length; i++) {
      var button = buttons[i];
      if (button.className) {
        var Klasse = button.className;
        var CN = Klasse.toLowerCase().indexOf("gpxview2");
        if (CN > -1) {
          var cmd = Klasse.substring(CN).split()[0];
          cmd = cmd.split(":") ;
          if (cmd.length > 2) {
            var Id = cmd[1];
            switch(cmd[2]) {
              case "skaliere":
                ( function() {
                  var mapid = "Karte_"+Id;
                  button.onclick = function() {
                    window[mapid].rescale()
                  };
                } )();
                break;
              case "lade":
                if (cmd.length > 3) {
                  var mapName = defMap;
                  if (cmd.length > 4) {
                    typ = chkTyp(cmd[4]);
                    mapName = cmd[4];
                  } else {
                    typ = G_HYBRID_MAP;
                  }
                  ( function() {
                    var fn = cmd[3];
                    var mapid = "Karte_"+Id;
                    var tp = typ;
                    button.onclick = function() {
                      actTrack = fn;
                      actMap = mapName;
                      mClick();
                      window[mapid].Spur(fn,tp)
                    };
                  } )();
                }
                break;
              default:
                break;
            }
          }
        }
      }
    }
    JB_addEvent(window,"onunload",GUnload);
  }
  else alert("Ihr Browser unterstützt nicht die benötigten Methoden!");
});
//
// the end
//

