// staic code to mange mouseover events
// ------------------------------------------------------------------------
// functions for managing the movements over the profile
// ------------------------------------------------------------------------
// controlling MouseOver events for the AltProfile
var inMove = false;
// when cursor is over altitude profile
function profileOver() {
  document.getElementById('alti_line').style.visibility = 'visible';
  document.getElementById('alti_line_info').style.visibility = 'visible';
}
// when cursor is not over altitude profile
function profileOut() {
  document.getElementById('alti_line').style.visibility = 'hidden';
  document.getElementById('alti_line_info').style.visibility = 'hidden';
}

function profileClick(img) {
  //alert(img);
}
// calculate infos for the alti_line_info
function profileMove(event,pwidth) {
  if (inMove) return;
  inMove = true;
  var curr_X;         // X-position of mouse over profile
  var width = pwidth; /* width of profile 600 */
  if (typeof event.layerX == 'undefined') {    // IE explorer
    curr_X = event.offsetX;        
  } else {                                     // firefox
    curr_X = event.layerX;
  }
  // set X-position vertical line
  document.getElementById('alti_line').style.left = curr_X + 'px';
  // calculate current distance from starting point
  var dist_total = pds[pds.length-1][0];
  var dis_curr   = dist_total * curr_X/width;
  // get corresponding point
  var point_nr = findProfilePoint(dis_curr); 
  // pan GoogleMap     
  MyMap.panTo(points[point_nr]);
  if (true) {
    // set X-position info-box
    var info_offset = curr_X - Math.round((120*curr_X/width));
    document.getElementById('alti_line_info').style.visibility = 'visible';
    document.getElementById('alti_line_info').style.left = info_offset + 'px';
    // contents of popup box
    perc   = "";
    pt_avg = 1; // #points to average %age
    if ( point_nr > pt_avg) {  
                             // Alt-difference                                     distance 
      perc = Math.round( (pds[point_nr + pt_avg][1] - pds[point_nr - pt_avg][1]) / (pds[point_nr + pt_avg][0] - pds[point_nr - pt_avg][0]) * 100);
      if (        Math.abs(perc) >= 20) {
        perc =  " / " + '<span style="color: rgb(255,0,0); font-weight: bold;">' + perc + "% </span>";            
      } else if ( Math.abs(perc) >= 15) {
        perc =  " / " + '<span style="color: rgb(255,0,0)">' + perc + "% </span>";            
      } else if ( Math.abs(perc) >= 5) {
        perc =  " / " + '<span style="color: rgb(255,128,0)">' + perc + "% </span>";            
      } else if ( Math.abs(perc) >= 3) {
        perc =  " / " + '<span style="color: rgb(0,255,0)">' + perc + "% </span>";            
      } else {                         
        perc =  " / " + perc + "%";            
      }          
    }   //                                                distance                                         Altitude                 Steigung
    document.getElementById('alti_line_info').innerHTML = Math.round(pds[point_nr][0]/100)/10 + " km / " + pds[point_nr][1] + "m" + perc;
  }
  inMove = false;
  // center crosshair on map                                                                                                    
}

// find the point (with coordinates) for the dist reached
function findProfilePoint(dist) {
  var dist_total = pds[pds.length-1][0];
  var nrPoints = points.length;
  var left = 0;
  var right = nrPoints - 1;
  var x;
  do {
    x =  Math.floor((left + right) / 2);
    if (dist < pds[x][0]) {
      right = x - 1;          
    } else {
      left = x + 1;
    }
  } while (left < right);

  return left;
}            

// Subclassed VML/SVG Polyline
//
// Bill Chadwick May 2007     http://www.bdcc.co.uk/Gmaps/BdccGmapBits.htm 
//
// Free for any use
//
// Adds 
//  click, mouseover and mouseout events
//  tooltip
//  dot or dash styling
//  dynamic setting of colour, opacity, weight and dash style  

var BDCCPolylineId;//counter for unique DOM Ids

// Constructor params exactly as GPolyline then a tooltip and dash which must be one of "dot" or "dash" or "solid"

function BDCCPolyline(points, color, weight, opacity, tooltip, dash, multi, start_km, end_km) {	
    
    this.tooltip = tooltip;
    this.dash = (dash != null) ? dash : "solid";
    this.color = color;
    this.weight = weight;
    this.opacity = opacity;
    this.multi = multi;    // if multi-etappe
    this.start_km = start_km;        // km
    this.end_km = end_km;            // km
    
    
    //make a unique DOM id for this polyline
    if(BDCCPolylineId == null)
        BDCCPolylineId = 0;
    else
        BDCCPolylineId += 1;
    this.domid = "BDCCPolylineId" + BDCCPolylineId.toString();

    this.usesVml = (navigator.userAgent.indexOf("MSIE") != -1);

    GPolyline.call(this,points,color,weight,opacity,{"clickable":false});//call super class constructor 
}

BDCCPolyline.prototype = new GPolyline(new Array(new GLatLng(0,0)));//subclass from GPolyline

// According to the GMap docs, GPolyline implements the GOverlay interface
// That is it implements the functions initialize, remove, copy and redraw
// Here we add to GPolyline's own implementation of these functions
//

BDCCPolyline.prototype.initialize = function(map) {
    GPolyline.prototype.initialize.call(this,map); //super class
    //Initialise cant be used to cache the SVG path node or its parent svg node as both are recreated in redraw
    //For VML the shape node is recreated in redraw and all shapes have a common parent        
    this.map = map;   
    
}

BDCCPolyline.prototype.remove = function() {
    GPolyline.prototype.remove.call(this); //super class
}

BDCCPolyline.prototype.copy = function(map) {
    return new BDCCPolyline(this.points,this.color,this.weight,this.opacity,this.tooltip,this.dash);
}

BDCCPolyline.prototype.redraw = function(force) {
   
   GPolyline.prototype.redraw.call(this,force); //super class
   var dom = null;
   var i = 1;
   var prnt;

   if(this.usesVml){
        try{        
            var shps = document.getElementsByTagName("shape"); 
	  	    i = shps.length-1;
	  	    
	  	    //You could omit parent node checking if you only have one map per document
	  	    //Doing so will give a performance improvement	  	    
        	this.map.getPane(G_MAP_MAP_PANE).parentNode.id = "Cntnr" + this.domid;
        	
        	while((dom == null) && (i >= 0)){

            	dom = shps[i];//assume ours is the most recently added by the superclass redraw
            	prnt = dom.parentNode;
    			while(prnt != null){
                	if (prnt.id == "Cntnr" + this.domid) 
                    	break;
                	else
                    prnt = prnt.parentNode; 
            	}
            	if(prnt == null){
                	i -= 1;
				    dom = null;
			    }
            	else
                	break;
        	}

            if(dom != null){
                //we found our VML node
                if(this.tooltip != null){
                    dom.style.cursor = "pointer";//to show mouseover 
                    dom.title = this.tooltip;
                }
                dom.id = this.domid;//assign unique DOM id so we can modify attributes later   
            }
        }
        catch (ex)
        {
		    if(BDCCPolylineId == 0)
			    alert("The designer of this Google Maps web page has attempted to use VML graphics without including the necessary header material.");
        }
   }
   else{
        var shps = document.getElementsByTagName("path"); 
	    i = shps.length-1;
	    
	    //You could omit parent node checking if you only have one map per document
	  	//Doing so will give a performance improvement	  	    
        this.map.getPane(G_MAP_MAP_PANE).parentNode.setAttribute("id","Cntnr" + this.domid);

        while((dom == null) && (i >= 0)){
		
            dom = shps[i];//assume ours is the most recently added by the superclass redraw
            prnt = dom.parentNode;
		    while(prnt != null){
                if (prnt.id == "Cntnr" + this.domid)
                    break;
                else
                    prnt = prnt.parentNode; 
            }
            if(prnt == null){
                i -= 1;
		        dom = null;
		    }
            else
                break;
        }

        if(dom != null){
            //we found our SVG node

            if(this.tooltip != null){
                dom.style.cursor = "pointer";//to show mouseover 
                dom.setAttribute("title",this.tooltip);
            }
            dom.setAttribute("id",this.domid);//assign unique DOM id so we can modify attributes later
            dom.setAttribute("pointer-events","stroke");//only click on the line, not its bounding rectangle
        }
   }

   if(this.dredraw)
       window.clearTimeout(this.dredraw); 

   if(dom != null){
   
      //set up the appearance of our polyline
       this.setColor(this.color);
       this.setDash(this.dash);
       this.setOpacity(this.opacity);
       this.setWeight(this.weight);
       this.setLineStyle(this.lineStyle);
       
       //set up event handlers
       var cclick = GEvent.callback(this,this.onClick);
       var cover = GEvent.callback(this,this.onOver);
       var cout = GEvent.callback(this,this.onOut);
   
       GEvent.clearInstanceListeners(dom);//safety 
       GEvent.addDomListener(dom,"click",function(event){cclick();});
       GEvent.addDomListener(dom,"mouseover",function(){cover();});
       GEvent.addDomListener(dom,"mouseout",function(){cout();});
   }
   else {
        //we could not paint because GMaps has not done its drawing yet, try a bit later
        var credraw = GEvent.callback(this,this.redraw);
        this.dredraw = window.setTimeout(function(force){credraw(true);},200); //the true here is vital
   }
}

//event handlers
BDCCPolyline.prototype.onClick = function(){
    GEvent.trigger(this,"click");
}
BDCCPolyline.prototype.onOver = function(){
    GEvent.trigger(this,"mouseover");
}
BDCCPolyline.prototype.onOut = function(){
    GEvent.trigger(this,"mouseout");
}

//once the shape has been drawn, we can modify it with these setX functions;

BDCCPolyline.prototype.setColor = function(color) {
    this.color = color;
    var dom = document.getElementById(this.domid); 
    if(!dom)
        return;
    if(this.usesVml){
        dom.stroke.color = this.color;
    }
    else{
        dom.setAttribute("stroke",this.color);
    }
}
BDCCPolyline.prototype.getColor = function() {
    return this.color;
}
BDCCPolyline.prototype.setDash = function(dash) {
    this.dash = dash;
    var dom = document.getElementById(this.domid); 
    if(!dom)
        return;
    if(this.usesVml){
        if(this.dash == "dash")
            dom.stroke.dashstyle = "dash";       
        else if (this.dash == "dot")
            dom.stroke.dashstyle = "dot";    
        else 
            dom.stroke.dashstyle = "";    
    }
    else{
        if(this.dash == "dash")
            dom.setAttribute("stroke-dasharray","10,10");
        else if (this.dash == "dot")
            dom.setAttribute("stroke-dasharray","3,17");
        else
            dom.setAttribute("stroke-dasharray","");
    }
}
BDCCPolyline.prototype.getDash = function() {
    return this.dash;
}
//for VML only, use single, thinthin, thinthick, thickthin, thickbetweenthin
BDCCPolyline.prototype.setLineStyle = function(ls) {
    this.lineStyle = ls;
    var dom = document.getElementById(this.domid); 
    if(!dom)
        return;
    if(this.usesVml){
        dom.stroke.linestyle = ls;
    }
}
BDCCPolyline.prototype.getLineStyle = function() {
    return this.lineStyle;
}

BDCCPolyline.prototype.setWeight = function(weight) {
    this.weight = weight;
    var dom = document.getElementById(this.domid); 
    if(!dom)
        return;
    if(this.usesVml){
        dom.stroke.weight = this.weight.toString()+"px";   
    }
    else{
        dom.setAttribute("stroke-width",this.weight.toString()+"px");
    }
}
BDCCPolyline.prototype.getWeight = function() {
    return this.weight;
}
BDCCPolyline.prototype.setOpacity = function(opacity) {
    this.opacity = opacity;
    var dom = document.getElementById(this.domid); 
    if(!dom)
        return;
    if(this.usesVml){
        dom.stroke.opacity = this.opacity;
    }
    else{
        dom.setAttribute("stroke-opacity",this.opacity);
    }
}
BDCCPolyline.prototype.getOpacity = function() {
    return this.opacity;
}
BDCCPolyline.prototype.setMulti = function(multi) {
    this.multi = multi;
}
BDCCPolyline.prototype.getMulti = function() {
    return this.multi;
}

//====================================================================================================================
// Subclassed filled VML/SVG GPolygon if you want it unfilled - use BDCCPolyline
//
// Free for any use
//
// Bill Chadwick May 2007
//
// Adds 
//  click, mouseover and mouseout events
//  tooltip
//  dot or dash styling for stroke
//  dynamic setting of stroke colour, opacity, weight and dash style and fill color and opacity

var BDCCPolygonId;//counter for unique DOM Ids

// Constructor params exactly as GPolygon then a tooltip and dash which must be one of "dot" or "dash" or "solid"

function BDCCPolygon(points, strokeColor, strokeWeight, strokeOpacity, fillColor, fillOpacity, tooltip, dash) {	
    
    this.tooltip = tooltip;
    this.dash = (dash != null) ? dash : "solid";
    this.strokeColor = strokeColor;
    this.strokeWeight = strokeWeight;
    this.strokeOpacity = strokeOpacity;
    this.fillColor = fillColor;
    this.fillOpacity = ((fillOpacity >= 0.005)&&(fillOpacity <= 0.015))?0.02:fillOpacity;//don't use our special value;
    
    //make a unique DOM id for this polyline
    if(BDCCPolygonId == null)
        BDCCPolygonId = 0;
    else
        BDCCPolygonId += 1;
            
    var uid = BDCCPolylineId.toString(16); //initial color so we can find dom node
    while (uid.length < 6)
        uid = "0" + uid;
    this.uid = "#" + uid;
        
    this.domid = "BDCCPolygonId" + BDCCPolygonId.toString();
    
    this.usesVml = (navigator.userAgent.indexOf("MSIE") != -1);
    
    //call super class constructor with temp colour and transperency for nearly invisible
    GPolygon.call(this,points,this.uid,strokeWeight,0.01,this.uid,0.01,{"clickable":false});//call super class constructor 
}
BDCCPolygon.prototype = new GPolygon(new Array(new GLatLng(0,0)));//subclass from GPolygon

// According to the GMap docs, GPolygon implements the GOverlay interface
// That is it implements the functions initialize, remove, copy and redraw
// Here we add to GPolygon's own implementation of these functions
//

BDCCPolygon.prototype.initialize = function(map) {
    GPolygon.prototype.initialize.call(this,map); //super class
    //Initialise cant be used to cache the SVG path node or its parent svg node as both are recreated in redraw
    //For VML the shape node is recreated in redraw and all shapes have a common parent      
    this.map = map;  
}

BDCCPolygon.prototype.remove = function() {
    GPolygon.prototype.remove.call(this); //super class
}

BDCCPolygon.prototype.copy = function(map) {
    return new BDCCPolygon(this.points,this.strokeColor,this.strokeWeight,this.strokeOpacity,this.fillColor,this.fillOpacity,this.tooltip,this.dash);
}

BDCCPolygon.prototype.redraw = function(force) {

   GPolygon.prototype.redraw.call(this,force); //super class
   
   //update later when the API's rendering has finished
   var credraw = GEvent.callback(this,this.delayedRedraw);
   
   if(this.dredraw)
       window.clearTimeout(this.dredraw); 
          
   this.dredraw = window.setTimeout(function(force){credraw(true);},100); //the true here is vital
}

BDCCPolygon.prototype.delayedRedraw = function(force) {
   
   var dom = null;
   var i = 1;
   var prnt;
   if(this.usesVml){
        try{        
            var shps = document.getElementsByTagName("shape"); 
	  	    i = shps.length-1;
	  	    
	        //You could omit parent node checking if you only have one map per document
	  	    //Doing so will give a performance improvement	  	    
	  	    this.map.getPane(G_MAP_MAP_PANE).parentNode.id = "Cntnr" + this.domid;

	  	    //find the one with our UID string as its colour + our 1% opacity
	  	    //and on the correct map       	
        	for(i=0;i<shps.length;i++){
            	dom = shps[i];
                if ((dom.stroke.color == this.uid) && 
                    (dom.fill.opacity > 0.005) &&
                    (dom.fill.opacity < 0.015)){
                    prnt = dom.parentNode;
                	while(prnt != null){
                        if (prnt.id == "Cntnr" + this.domid){
                            i = shps.length;
                            break;
                        }
                        else{
                            prnt = prnt.parentNode; 
                        }
                    }
                    if(i < shps.length)
                        dom = null;
                }
                else
                    dom = null;                                                	
        	}

            if(dom != null){
            
                //we found our vml node
                if(this.tooltip != null){
                    dom.style.cursor = "pointer";// "help";//to show mouseover 
                    dom.title = this.tooltip;
                }
                dom.id = this.domid;//assign unique DOM id so we can modify attributes later   
            }
        }
        catch (ex)
        {
		    if(BDCCPolygonId == 1)
			    alert("The designer of this Google Maps web page has attempted to use VML graphics without including the necessary header material.");
        }
   }
   else{
        var shps = document.getElementsByTagName("path"); 
	    i = shps.length-1;

	    //You could omit parent node checking if you only have one map per document
	  	//Doing so will give a performance improvement	  	    
        this.map.getPane(G_MAP_MAP_PANE).parentNode.setAttribute("id","Cntnr" + this.domid);

  	    //find the one with our UID string as its colour + our 1% opacity
  	    //and on the correct map       	
    	for(i=0;i<shps.length;i++){
        	dom = shps[i];
            if ((dom.getAttribute("stroke") == this.uid) && 
                (dom.getAttribute("fill-opacity") >= 0.005) &&
                (dom.getAttribute("fill-opacity") <= 0.015)){
                prnt = dom.parentNode;
            	while(prnt != null){
                    if (prnt.id == "Cntnr" + this.domid){
                        i = shps.length;
                        break;
                    }
                    else{
                        prnt = prnt.parentNode; 
                    }
                }
                if(i < shps.length)
                    dom = null;
            }
            else
                dom = null;                                                	
    	}

        if(dom != null){        
            //we found our svg node
            if(this.tooltip != null){
                dom.style.cursor = "pointer";//to show mouseover 
                dom.setAttribute("title",this.tooltip);
            }
            dom.setAttribute("id",this.domid);//assign unique DOM id so we can modify attributes later
        }
   }

   if(this.dredraw)
       window.clearTimeout(this.dredraw); 

   if(dom != null){

       //set up the appearance of our polygon
       this.setStrokeColor(this.strokeColor);
       this.setStrokeDash(this.dash);
       this.setStrokeOpacity(this.strokeOpacity);
       this.setStrokeWeight(this.strokeWeight);
       this.setFillColor(this.fillColor);
       this.setFillOpacity(this.fillOpacity);
       
       //set up event handlers
       var cclick = GEvent.callback(this,this.onClick);
       var cover = GEvent.callback(this,this.onOver);
       var cout = GEvent.callback(this,this.onOut);

       GEvent.clearInstanceListeners(dom);//safety 
       GEvent.addDomListener(dom,"click",function(event){cclick();});
       GEvent.addDomListener(dom,"mouseover",function(){cover();});
       GEvent.addDomListener(dom,"mouseout",function(){cout();});
   
   }
   else {
        //we could not paint because GMaps has not done its drawing yet, try a bit later
        var credraw = GEvent.callback(this,this.delayedRedraw);
        this.dredraw = window.setTimeout(function(force){credraw(true);},200); //the true here is vital
   }
   
   
}

//event handlers
BDCCPolygon.prototype.onClick = function(){
    GEvent.trigger(this,"click");
}
BDCCPolygon.prototype.onOver = function(){
    GEvent.trigger(this,"mouseover");
}
BDCCPolygon.prototype.onOut = function(){
    GEvent.trigger(this,"mouseout");
}

//once the shape has been drawn, we can modify it with these setX functions;

BDCCPolygon.prototype.setStrokeColor = function(color) {
    this.strokeColor = color;
    var dom = document.getElementById(this.domid); 
    if(!dom)
        return;
    if(this.usesVml){
        dom.stroke.color = this.strokeColor;
    }
    else{
        dom.setAttribute("stroke",this.strokeColor);
    }
}
BDCCPolygon.prototype.getStrokeColor = function() {
    return this.strokeColor;
}
BDCCPolygon.prototype.setStrokeDash = function(dash) {
    this.dash = dash;
    var dom = document.getElementById(this.domid); 
    if(!dom)
        return;
    if(this.usesVml){
        if(this.dash == "dash")
            dom.stroke.dashstyle = "dash";       
        else if (this.dash == "dot")
            dom.stroke.dashstyle = "dot";    
        else 
            dom.stroke.dashstyle = "";    
    }
    else{
        if(this.dash == "dash")
            dom.setAttribute("stroke-dasharray","10,10");
        else if (this.dash == "dot")
            dom.setAttribute("stroke-dasharray","3,17");
        else
            dom.setAttribute("stroke-dasharray","none");
    }
}
BDCCPolygon.prototype.getStrokeDash = function() {
    return this.dash;
}
BDCCPolygon.prototype.setStrokeWeight = function(weight) {
    this.strokeWeight = weight;
    var dom = document.getElementById(this.domid); 
    if(!dom)
        return;
    if(this.usesVml){
        dom.stroke.weight = this.strokeWeight.toString()+"px";   
    }
    else{
        dom.setAttribute("stroke-width",this.strokeWeight.toString()+"px");
    }
}
BDCCPolygon.prototype.getStrokeWeight = function() {
    return this.strokeWeight;
}
BDCCPolygon.prototype.setStrokeOpacity = function(opacity) {
    this.strokeOpacity = opacity;
    var dom = document.getElementById(this.domid); 
    if(!dom)
        return;
    if(this.usesVml){
        dom.stroke.opacity = this.strokeOpacity;
    }
    else{
        dom.setAttribute("stroke-opacity",this.strokeOpacity);
    }
}
BDCCPolygon.prototype.getStrokeOpacity = function() {
    return this.strokeOpacity;
}
BDCCPolygon.prototype.setFillColor = function(color) {
    this.fillColor = color;
    var dom = document.getElementById(this.domid); 
    if(!dom)
        return;
    if(this.usesVml){
        dom.fill.color = this.fillColor;
    }
    else{
        dom.setAttribute("fill",this.fillColor);
    }
}
BDCCPolygon.prototype.getFillColor = function() {
    return this.fillColor;
}
BDCCPolygon.prototype.setFillOpacity = function(opacity) {
    this.fillOpacity = ((opacity >= 0.005)&&(opacity <= 0.015))?0.02:opacity;//don't use our special value
    var dom = document.getElementById(this.domid); 
    if(!dom)
        return;
    if(this.usesVml){
        dom.fill.opacity = this.fillOpacity;
    }
    else{
        dom.setAttribute("fill-opacity",this.fillOpacity);
    }
}
BDCCPolygon.prototype.getFillOpacity = function() {
    return this.fillOpacity;
}

//====================================================================================================================
///////////////////////////////////////////////////////////////////////////////
// loadgpx.4.js
//
// Javascript object to load GPX-format GPS data into Google Maps.
//
// Copyright (C) 2006 Kaz Okuda (http://notions.okuda.ca)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
//
// If you use this script or have any questions please leave a comment
// at http://notions.okuda.ca/geotagging/projects-im-working-on/gpx-viewer/
// A link to the GPL license can also be found there.
//
///////////////////////////////////////////////////////////////////////////////
//
// History:
//    revision 1 - Initial implementation
//    revision 2 - Removed LoadGPXFileIntoGoogleMap and made it the callers
//                 responsibility.  Added more options (colour, width, delta).
//    revision 3 - Waypoint parsing now compatible with Firefox.
//    revision 4 - Upgraded to Google Maps API version 2.  Tried changing the way
//               that the map calculated the way the center and zoom level, but
//               GMAP API 2 requires that you center and zoom the map first.
//               I have left the bounding box calculations commented out in case
//               they might come in handy in the future.
//
// Author: Kaz Okuda
// URI: http://notions.okuda.ca/geotagging/projects-im-working-on/gpx-viewer/
//
///////////////////////////////////////////////////////////////////////////////

function GPXParser(xmlDoc, map) {
	this.xmlDoc = xmlDoc;
	this.map = map;
	this.trackcolour = "#ff00ff"; // red
	this.trackwidth = 5;
	this.trackstyle = "";     //line
	this.tooltiparray = [];   //tooltips
	this.mintrackpointdelta = 500; // 0.0001
}

// Set the colour of the track line segements.
GPXParser.prototype.SetTrackColour = function(colour) {
	this.trackcolour = colour;
}
// Set the alternate colour of the track line segements.
GPXParser.prototype.SetTrackAltColour = function(colour) {
	this.trackaltcolour = colour;
}

// Set the width of the track line segements
GPXParser.prototype.SetTrackWidth = function(width) {
	this.trackwidth = width;
}

// Set the tooltip text of the segments
GPXParser.prototype.SetTrackTooltip = function(tooltiparray) {
  for (i=0; i<tooltiparray.length; i++)  {
    this.tooltiparray[i] = tooltiparray[i];
  }   
}
// Set the style of the track line segements   (dot, dash, "")
GPXParser.prototype.SetTrackStyle = function(style) {
	this.trackstyle = style;
}

// Set the minimum distance between trackpoints.
// Used to cull unneeded trackpoints from map.
GPXParser.prototype.SetMinTrackPointDelta = function(delta) {
  if ( delta > 50 ) {
    this.mintrackpointdelta = delta;
  }
}

GPXParser.prototype.TranslateName = function(name) {
	if (name == "wpt")
	{
		return "Waypoint";
	}
	else if (name == "trkpt")
	{
		return "Track Point";
	}
}

// create marker with icon
GPXParser.prototype.CreateMarker = function(point) {
  
	var lon = parseFloat(point.getAttribute("lon"));
	var lat = parseFloat(point.getAttribute("lat"));
	var html = "";

	if (point.getElementsByTagName("html").length > 0)
	{
		for (i=0; i<point.getElementsByTagName("html").item(0).childNodes.length; i++)
		{
			html += point.getElementsByTagName("html").item(0).childNodes[i].nodeValue;
		}
	}
	else
	{
    // MRT
		// Create the html if it does not exist in the point.    
    var wp_name = "";
    var wp_desc = "";
    var wp_ele = "";
    if (point.hasChildNodes) {
		  var children = point.childNodes;
			var childrenlen = children.length;
		 	for (i=0; i<childrenlen; i++)
		 	{
		 		// Ignore empty nodes
		 		if (children[i].nodeType != 1) continue;
        // name of waypoint
        if (children[i].nodeName == "name" ) {
          wp_name = children[i].firstChild.nodeValue;
        }
        // desc of waypoint
        if (children[i].nodeName == "desc" ) {
          wp_desc = children[i].firstChild.nodeValue;
        }
        // elevation
        if (children[i].nodeName == "ele" ) {
          wp_ele = Math.round(children[i].firstChild.nodeValue);
        }
		 	}     
     }
     // add html for marker
     html = '<p style="font-family: Lucida Grande,Verdana,Arial,sans-serif; font-size: 12px; text-align: left; border-bottom: 1px dashed rgb(66, 0, 0);font-weight: bold;color: rgb(66, 0, 0);">';
     // icon for marker
     var pngurl   = 'http://traube-online.net/img/marker_default_small.png'; // default
     var pngtitle = 'Waypoint';
     // alert( typeof wpIcon[wp_name.substring(0,2)] );
     if ( typeof wpIcon[wp_name.substring(0,2)] != "undefined") {  // if this marker_name is known
     // if ( wpIcon[wp_name.substring(0,2)]) {
       var pngurl   = wpIcon[wp_name.substring(0,2)]["icon"].replace( /.png/, "_small.png");      // use small icon in bubble ;
       var pngtitle = encodeMyHtml( wpIcon[wp_name.substring(0,2)]["title"] );
     }
     html += '<img src="' + pngurl + '" style="float:left; margin-right: 10px;" width="15px" height="15px" title="' + pngtitle + '" alt="' + pngtitle + '"/> ' + pngtitle + '</p>';          
     
     // marker text
     html += '<p style="font-family: Lucida Grande,Verdana,Arial,sans-serif; font-size: 10px">';
     html += '<b>' + encodeMyHtml(wp_name) + "</b>";
     if ( wp_ele > 1 ) {  
       html +=  " (" + wp_ele +"m)";  
     }
     if ( wp_desc != "" ) {
       // check if desc contains a URL
       var s_obj = new Object();
       s_obj.value = wp_desc;

       var wpurl = includesURL(s_obj); 
       if (wpurl){
         if ( s_obj.value == ' ' ) { s_obj.value = wp_name;}
         html += "<br />" + "<a href='" + wpurl + "' target='_blank'>" + encodeMyHtml(s_obj.value) + "</a>";  
       } else {
         html += "<br />" + encodeMyHtml(wp_desc);  
       } 
     }
     html += "</p>";
	}
  
  //set icon for waypoint
  var icon    = new GIcon();
  var iconurl =  "http://traube-online.net/img/marker_default.png";  // default
  if ( typeof wpIcon[wp_name.substring(0,2)] != "undefined") {       // if this marker_name is known
    iconurl  = wpIcon[wp_name.substring(0,2)]["icon"];          
  }  
  icon.image      = iconurl;          
  icon.shadow     = "http://traube-online.net/img/marker_shadow.png";
  icon.iconSize   = new GSize(15, 25);
  icon.shadowSize = new GSize(28, 25);
  icon.iconAnchor = new GPoint(7, 25);
  icon.infoWindowAnchor = new GPoint(5, 1);
  
  // create marker with icon
	var marker = new GMarker( new GLatLng(lat,lon), icon);
	GEvent.addListener(marker, "click",
		function() {
      // open InfoHTML
			marker.openInfoWindowHtml(html);
		}
	);
  // add marker to overlay
	this.map.addOverlay(marker);
  // add this marker to the array
  gmarkers.push( marker );

	// All methods that add items to the map return the bounding box of what they added.
	//var latlng = new GLatLng(lat,lon);
	//return new GLatLngBounds(latlng,latlng);
}

GPXParser.prototype.AddTrackSegmentToMap = function(trackSegment, colour, width, segmentno, multi, start_km ) {
	//var latlngbounds = new GLatLngBounds();
  var end_km = start_km;  // starting for new segment

	var trackpoints = trackSegment.getElementsByTagName("trkpt");
	if (trackpoints.length == 0)
	{
		return end_km; //latlngbounds;
	}

	var pointarray = [];
  
	// process first point
	var lastlon = parseFloat(trackpoints[0].getAttribute("lon"));
	var lastlat = parseFloat(trackpoints[0].getAttribute("lat"));
	var latlng = new GLatLng(lastlat,lastlon);
	pointarray.push(latlng);
	//latlngbounds.extend(latlng);

  // start loop from 2nd point onwards
	for (var i=1; i < trackpoints.length; i++) {
    // calculate ~distance to last point
		var lon = parseFloat(trackpoints[i].getAttribute("lon"));
		var lat = parseFloat(trackpoints[i].getAttribute("lat"));

		// Verify that this is far enough away from the last point to be used.
		var latdiff = lat - lastlat;
		var londiff = lon - lastlon;
    var dis_km  = Math.sqrt(latdiff*latdiff + londiff*londiff) * 100;  // distance in [km]
		if ( dis_km * 1000 > this.mintrackpointdelta ) {                   // mintrackpointdelta in [m]
			lastlon = lon;
			lastlat = lat;
			latlng = new GLatLng(lat,lon);
			pointarray.push(latlng);
			//latlngbounds.extend(latlng);
      // end_km = Math.round((end_km + dis_km) * 100) / 100;    // 2 Nachkommastellen
      end_km = end_km + dis_km;    
		}
	}
  // add points to line
	//var polyline = new GPolyline(pointarray, colour, width);
  var polyline = new BDCCPolyline(pointarray, colour, width, 0.5, this.tooltiparray[segmentno], this.trackstyle, multi, start_km, end_km);

  var etappeID      = segmentno + 1;
  var etappeDescRef = parent.location.href + "#Etappe" + etappeID;
  GEvent.addListener(polyline,"click",function(){parent.location=etappeDescRef;});
//  GEvent.addListener(polyline,"mouseover",function(){polyline.setOpacity(0.9);});
//  GEvent.addListener(polyline,"mouseout",function(){polyline.setOpacity(0.5);});
  GEvent.addListener(polyline,"mouseover",function(){ 
                                                     polyline.setOpacity(0.9);
                                                     if ( polyline.getMulti() == true ) {     // XXX                                                       alert(segmentno );
                                                      //  var leftpx  = Math.round(this.start_km/(tripLength)*600);
                                                      //  var widthpx = Math.round((this.end_km - this.start_km)/(tripLength)*600);
                                                       var leftpx  = Math.round(etappearray[segmentno][0]/tripDistance *600);
                                                       var widthpx = Math.round(etappearray[segmentno][1]/tripDistance *600);
                                                       document.getElementById('etappe_zoom').style.visibility = 'visible';
                                                       document.getElementById('etappe_zoom').style.left  = leftpx + 'px';
                                                       document.getElementById('etappe_zoom').style.width = widthpx + 'px';
                                                      // document.getElementById('etappe_zoom').innerHTML = Math.round(this.start_km) + 'km &rarr; ' + Math.round(this.end_km) + 'km';
                                                       document.getElementById('etappe_zoom').innerHTML = Math.round(etappearray[segmentno][0]) + 'km &rarr; ' + Math.round(etappearray[segmentno][0] + etappearray[segmentno][1]) + 'km';
                                                      // var html_inner = this.tooltiparray[segmentno].substring(this.tooltiparray[segmentno].search('('), this.tooltiparray[segmentno].length - 1); 
                                                      // document.getElementById('etappe_zoom').innerHTML = html_inner;
                                                     }
                                                    });
  GEvent.addListener(polyline,"mouseout",function(){
                                                     polyline.setOpacity(0.5);
                                                     if ( polyline.getMulti() == true ) {     // XXX
                                                       document.getElementById('etappe_zoom').style.visibility = 'hidden';
                                                       document.getElementById('etappe_zoom').style.left =  '0px';
                                                       document.getElementById('etappe_zoom').style.width = '0px';
                                                       document.getElementById('etappe_zoom').innerHTML = '';
                                                     }
                                                    });
 
 //add line to map
	this.map.addOverlay(polyline);

	// All methods that add items to the map return the bounding box of what they added.
	//return latlngbounds;
  return end_km;
}

// Parse GPX-file segment-by-segment
//GPXParser.prototype.AddTrackToMap = function(track, colour, width) {
GPXParser.prototype.AddTrackToMap = function(track, width) {

	var segments = track.getElementsByTagName("trkseg");
  var colour   = this.trackcolour;        // first/even segments
  var multi    = false;
  var end_km      = 0;
  if ( segments.length > 1) { multi = true; }
	//var latlngbounds = new GLatLngBounds();
	for (var i=0; i < segments.length; i++) {
    // set colour of tracksegment
    if ( Math.round( i/2 ) == i/2 ) {
      colour = this.trackcolour;        // first/even segments
    } else {
      colour = this.trackaltcolour;     // odd segments
    }
		//var segmentlatlngbounds = this.AddTrackSegmentToMap(segments[i], colour, width );
		//this.AddTrackSegmentToMap(segments[i], colour, width);
		// var segmentlatlngbounds = this.AddTrackSegmentToMap(segments[i], colour, width, i );
		var end_km = this.AddTrackSegmentToMap(segments[i], colour, width, i, multi, end_km );
		//latlngbounds.extend(segmentlatlngbounds.getSouthWest());
		//latlngbounds.extend(segmentlatlngbounds.getNorthEast());
	}

	// All methods that add items to the map return the bounding box of what they added.
	//return latlngbounds;
}

GPXParser.prototype.CenterAndZoom = function (trackSegment, maptype)
{

	var pointlist = new Array("trkpt", "wpt");
	var minlat = 0;
	var maxlat = 0;
	var minlon = 0;
	var maxlon = 0;

	for (var pointtype=0; pointtype < pointlist.length; pointtype++)
	{

		// Center the map and zoom on the given segment.
		var trackpoints = trackSegment.getElementsByTagName(pointlist[pointtype]);

		// If the min and max are uninitialized then initialize them.
		if ( (trackpoints.length > 0) && (minlat == maxlat) && (minlat == 0) )
		{
			minlat = parseFloat(trackpoints[0].getAttribute("lat"));
			maxlat = parseFloat(trackpoints[0].getAttribute("lat"));
			minlon = parseFloat(trackpoints[0].getAttribute("lon"));
			maxlon = parseFloat(trackpoints[0].getAttribute("lon"));
		}

		for (var i=0; i < trackpoints.length; i++)
		{
			var lon = parseFloat(trackpoints[i].getAttribute("lon"));
			var lat = parseFloat(trackpoints[i].getAttribute("lat"));

			if (lon < minlon) minlon = lon;
			if (lon > maxlon) maxlon = lon;
			if (lat < minlat) minlat = lat;
			if (lat > maxlat) maxlat = lat;
		}
	}

	if ( (minlat == maxlat) && (minlat = 0) )
	{
		this.map.setCenter(new GLatLng(49.327667, -122.942333), 14);
		return;
	}

	// Center around the middle of the points
	var centerlon = (maxlon + minlon) / 2;
	var centerlat = (maxlat + minlat) / 2;

	var bounds = new GLatLngBounds(new GLatLng(minlat, minlon), new GLatLng(maxlat, maxlon));

	this.map.setCenter(new GLatLng(centerlat, centerlon), this.map.getBoundsZoomLevel(bounds), maptype);
	this.map.setCenter(new GLatLng(centerlat, centerlon), this.map.getBoundsZoomLevel(bounds), maptype);
  
}

GPXParser.prototype.WPCenterAndZoom = function (mymarker)
{
	var bounds = new GLatLngBounds(new GLatLng(mymarker.get_position.lat() - 10, mymarker.get_position.lon() - 10), 
                                 new GLatLng(mymarker.get_position.lat() + 10, mymarker.get_position.lon() + 10));

	this.map.setCenter(new GLatLng(centerlat, centerlon), this.map.getBoundsZoomLevel(bounds));

}

GPXParser.prototype.CenterAndZoomToLatLngBounds = function (latlngboundsarray)
{
	var boundingbox = new GLatLngBounds();
	for (var i=0; i<latlngboundsarray.length; i++)
	{
		if (!latlngboundsarray[i].isEmpty())
		{
			boundingbox.extend(latlngboundsarray[i].getSouthWest());
			boundingbox.extend(latlngboundsarray[i].getNorthEast());
		}
	}

	var centerlat = (boundingbox.getNorthEast().lat() + boundingbox.getSouthWest().lat()) / 2;
	var centerlng = (boundingbox.getNorthEast().lng() + boundingbox.getSouthWest().lng()) / 2;
	this.map.setCenter(new GLatLng(centerlat, centerlng), this.map.getBoundsZoomLevel(boundingbox));
}

// Load all track-points from file into MAP
// called from gpxviewer.php
GPXParser.prototype.AddTrackpointsToMap = function () {

	var tracks = this.xmlDoc.documentElement.getElementsByTagName("trk");
	//var latlngbounds = new GLatLngBounds();

	for (var i=0; i < tracks.length; i++)	{
//		this.AddTrackToMap(tracks[i], this.trackcolour, this.trackwidth);
//		this.AddTrackToMap(tracks[i], this.trackwidth);
		this.AddTrackToMap(tracks[i], this.trackwidth, tooltiparray);
		//var tracklatlngbounds = this.AddTrackToMap(tracks[i], this.trackcolour, this.trackwidth);
		//latlngbounds.extend(tracklatlngbounds.getSouthWest());
		//latlngbounds.extend(tracklatlngbounds.getNorthEast());
	}

	// All methods that add items to the map return the bounding box of what they added.
	//return latlngbounds;
}

GPXParser.prototype.AddWaypointsToMap = function ( wpType )
{
  // Waypoints are extracted from GPX
  if ( wpType == 'WP') {
	  var waypoints = this.xmlDoc.documentElement.getElementsByTagName("wpt");
	  //var latlngbounds = new GLatLngBounds();

	  for (var i=0; i < waypoints.length; i++)
	  {
    
		  this.CreateMarker(waypoints[i]);
      
		  //var waypointlatlngbounds = this.CreateMarker(waypoints[i]);
		  //latlngbounds.extend(waypointlatlngbounds.getSouthWest());
		  //latlngbounds.extend(waypointlatlngbounds.getNorthEast());
	  }  
  }

	// All methods that add items to the map return the bounding box of what they added.
	//return latlngbounds;
}


