//fonctions rajoute par jerome 
var xmlhttps= new Array();
function loadXMLdoc(url) {
  if(window.XMLHttpRequest) {/*Mozilla*/
    xmlhttps = new XMLHttpRequest();
    xmlhttps.open("GET", url, false);/*false=attend load complete*/
    xmlhttps.send(null);
    //if(xmlhttps.readyState==4) {/*complete*/
      //a = xmlhttps.responseText;
      //alert(a);
    //}
  }
  else if(window.ActiveXObject) {/*IE*/
    xmlhttps = new ActiveXObject("Microsoft.XMLHTTP");
    xmlhttps.open("GET", url, false);
    xmlhttps.send();
    //if(xmlhttps.readyState==4) {/*complete*/
      //a = xmlhttps.responseText;
      //alert(a);
    //}
  }
  else { // XMLHttpRequest non supporté par le navigateur 
    //alert("Votre navigateur ne supporte pas les objets XMLHTTPRequest..."); 
    return; 
  } 
}

couleurcourbes = '00FF30';
//debut complete par jg ( interval manuel finalement pas activé)

function go() {
  /*
  if (interval <= 0) { // || zoom >= 17
    document.getElementById("interval_div").innerHTML = '<i>Courbes de niveau non disponible pour ce facteur de zoom</i>';
    document.getElementById("zoomlevel_span").innerHTML = cloudMap.getZoom();
    return;
  }
  */
  //alert(couleurcourbes);
  if (contour_overlay)
    cloudMap.removeOverlay(contour_overlay);
  contour_overlay = new GTileLayerOverlay(TileLayer(0, 17, 'Courbes', '',
	    function(point, zoom) {
	      // if (!contour_intervals[zoom])
	      //  return 'images/no-contour.png';
	      // force blue color if looking at anything other than 'map' type
        //'&x={X}&y={Y}'
		 return 'http://www.heywhatsthat.com/bin/contour_tiles.cgi?x=' + point.x + '&y=' + point.y + '&zoom=' + zoom
		                           + '&interval=' + contour_interval(zoom) + '&color='+ couleurcourbes
            }));
            
          
  cloudMap.addOverlay(contour_overlay);
  //document.getElementById("interval_div").innerHTML = 'Interval entre les courbes de niveau : ' + meters_to_units0(interval);
}

function popup_color_picker(numpicker,CouleurEtTransparence) {
  var width = 400;
  var height = 300;
  //alert(CouleurEtTransparence);
  window.open('color_picker.html?numpicker='+numpicker+'&CouleurEtTransparence='+CouleurEtTransparence, 'cp', 'resizable=no, location=no, width='
        +width+', height='+height+', menubar=no, status=yes, scrollbars=no, menubar=no');
}

function SauveItineraire() {
  Itineraire = "" ;
  //Itineraire2 = "" ;
  HeureHorloge = new Date;
  for (var i = 0; i < current.points.length ; i++){
    var altitude = current.points[i].elev;
    if (altitude == null){
      Itineraire = Itineraire + current.points[i].lat + ' ' + current.points[i].lon + '\n';
      //Itineraire2 = Itineraire2 + current.points[i].lat + ' ' + current.points[i].lon + '<br>\n';
    }else{
      Itineraire = Itineraire + current.points[i].lat + ' ' + current.points[i].lon + ' ' + altitude + '\n';;
      //Itineraire2 = Itineraire2 + current.points[i].lat + ' ' + current.points[i].lon + ' ' + altitude + '<br>\n';;
    }
  }
  document.getElementById("textarea_export").value = Itineraire;
  document.getElementById("text_nom_fichier_export").value = HeureHorloge.getTime();
  alert('Vous pouvez maintenant enregistrer votre itinéraire en cliquant sur [Fichier]|[Enregistrer sous]');
  //Itineraire2 ="<html><head></head><body>" + Itineraire2 + "</body></html>";
  //fenetreNote = window.open("","_blank","status=yes,toolbar=yes,menubar=yes,scrollbars=yes,width=550,height=280,top=75,left=75");
  //fenetreNote = window.open("Itineraire.htm","_blank");
  //fenetreNote.document.write(Itineraire2); 
}

function ImportItineraire(){
  Refresh_textarea_import();
  document.getElementById("masque_import_div").style.display = 'none';
  document.getElementById("div_import").style.display = '';
}

function Refresh_textarea_import(){
  Itineraire = "" ;
  for (var i = 0; i < current.points.length ; i++){
    var altitude = current.points[i].elev;
    if (altitude == null){
      Itineraire = Itineraire + current.points[i].lat + ' ' + current.points[i].lon + '\n';
    }else{
      Itineraire = Itineraire + current.points[i].lat + ' ' + current.points[i].lon + ' ' + altitude + '\n';;
    }
  }
  document.getElementById("textarea_import").value = Itineraire;

}

function TraceItineraire(){
  pagetxt = document.getElementById("textarea_import").value;
  clear();
  if (pagetxt==""){
    return;
  }
  var a = pagetxt.split('\n');
  a.pop();
  if (a.length > 100){
    alert("Impossible d'extraire l'itinéraire, le texte n'est pas bien formaté;!");
    return;
  }
  backspace(); // directions end with this point
  //a._foreach(function(b) { var c = b.split(' '); add_point(c[0], c[1]); });
  a._foreach(function(b) { var c = b.split(' '); add_point(c[0], c[1]); reset_current_points();//jg
 });
  Refresh_textarea_import();
}

function ChargeItineraire(){
  var nom_fichier = document.getElementById("nom_fichier_file").value;
  //alert(nom_fichier.substring(nom_fichier.length-4, nom_fichier.length));
  if (nom_fichier.substring(nom_fichier.length-4, nom_fichier.length)=='.iti'){
    loadXMLdoc('iti/' + nom_fichier);
    if(xmlhttps.readyState==4) {//complete
      pagetxt = xmlhttps.responseText;
      document.getElementById("textarea_import").value = pagetxt;
      clear();
      var a = pagetxt.split('\n');
      a.pop();
      parse_directions(a);
    }
  }
}

function ChargeItineraireBorg(){
  var nom_fichier = "canoeborg.iti";
  //alert(nom_fichier.substring(nom_fichier.length-4, nom_fichier.length));
  if (nom_fichier.substring(nom_fichier.length-4, nom_fichier.length)=='.iti'){
    loadXMLdoc('iti/' + nom_fichier);
    if(xmlhttps.readyState==4) {//complete
      pagetxt = xmlhttps.responseText;
      document.getElementById("textarea_import").value = pagetxt;
      clear();
      var a = pagetxt.split('\n');
      a.pop();
      parse_directions(a);
    }
  }
}

function AbortImportItineraire(){
  document.getElementById("masque_import_div").style.display = '';
  document.getElementById('div_import').style.display = 'none';
}

function CentreItineraire() {
  if (document.getElementById("textarea_import").value == ""){
    return;
  }
  var r = point_rectangle(current.points[0], current.points[current.points.length - 1]);
  cloudMap.setCenter(r.getCenter(), cloudMap.getBoundsZoomLevel(r));
}

var PuceTypeEncours = 14;
function ChangePuces(PuceType){
  //alert(PuceType);
  PuceTypeEncours = PuceType;
  Refresh_textarea_import();
  TraceItineraire();
  document.forms['f_transect2'].elements['show_profile'].focus()
}


var TraitTypeEncours = 4;
function ChangeTraits(TraitType){
  //alert(TraitType);
  TraitTypeEncours = TraitType;
  Refresh_textarea_import();
  TraceItineraire();
  document.forms['f_transect2'].elements['show_profile'].focus()
}






//fin complete par jg (interval manuel finalement pas activé)




					//************************** GENERIC UI

var current = {
  magnetic: false,
  points: [],
  legs: [],
  total_dist: 0,
  latlon_mode: 0,
  show_grade: 0,
  use_metric: 1
};


var colors = [ 'ff0000', '00c000', '0000ff' ];

function backspace() {
  if (current.points.length == 0)
    return;
  if (current.points.length == 1) {
    clear();
    return;
  }
  var p = current.legs.pop();
  if (p) {
    cloudMap.removeOverlay(p.line);
    current.total_dist -= p.dist;
  }
  p = current.points.pop();
  cloudMap.removeOverlay(p.marker);
  write_list_div();
  //write_bearing_div();
  document.getElementById('transect_img').src = 'javascript/contours/images/no-profile.png';//jg
  document.getElementById("show_profile").checked = false;//jg
  set_show_profile(false);//jg
}

function clear() {
  current.legs._foreach(function(p) { cloudMap.removeOverlay(p.line); });
  current.points._foreach(function(p) { cloudMap.removeOverlay(p.marker); });
  current.points = [];
  current.legs = [];
  current.total_dist = 0;
  write_list_div();
  //write_bearing_div();
  document.getElementById('transect_img').src = 'javascript/contours/images/no-profile.png';//jg
  document.getElementById("show_profile").checked = false;//jg
  set_show_profile(false);//jg

}

function clear_manuel() {
  if(confirm("Voulez-vous vraiment effacer l'itinéraire ?")){
    clear();
  }
}


function show_faq() {
  window.open('faq.html', '_faq', 'height=600,width=500,scrollbars');
}

function email_us() {
  location.href = 'mailto:comments-profiler@hey' + '' + 'what' + 'sthat.com';
}

function set_show_grade(b) {
  current.show_grade = b;
  document.getElementById('show_grade').checked = b;
  reset_current_points();
}
  
function set_show_profile(b) {
  //alert(b);
  if (b == true){
    document.getElementById("profile").style.display = '';
  } else{
    document.getElementById("profile").style.display = 'none';
  }
}


var set_lat_lon_timeout_id = 0;

function handle_map_click(overlay, point) {
  if (!point)
    return;
  add_point(point.y, point.x);
  reset_current_points();//jg
  Refresh_textarea_import();//jg

}

function set_points(a) {
  clear();
  a._foreach(function(x) { add_point(x.lat, x.lon, x.elev) });
}

function reset_current_points() {
  set_points(current.points);
}


function add_point(lat, lon, elev) {
  lat = round6(lat);
  lon = round6(lon);

  var latlng = new GLatLng(lat, lon);

  if (elev == null)
    elev = get_elev(lat, lon);


  if (current.points.length > 0) {
    var pp = current.points[current.points.length - 1];
    var color = '#' + colors[(current.points.length - 1) % colors.length];
    var b = bearing_and_range(pp.lat, pp.lon, lat, lon);
    current.total_dist += b[1];
    var rb = bearing_and_range(lat, lon, pp.lat, pp.lon);

    var start_elev;
    var prev_elev;
    if (current.points.length > 0) {
	start_elev = current.points[0].elev;
	prev_elev  = current.points[current.points.length - 1].elev;
    }
    var dist = (elev != null && prev_elev != null)? Math.sqrt(b[1] * b[1] + (elev - prev_elev) * (elev - prev_elev)) : b[1];

    var l = {line: new GPolyline([latlng, pp.marker.getPoint()], color, TraitTypeEncours, .5),
	     dist: dist,
	     html:   '<tr align=right style="color: ' + color + '">'
                   + '<td title="Azimut arrière ' + round0(adjust_for_declination(rb[0])) + '&deg;">'
                      + round0(adjust_for_declination(b[0])) + '&deg;</td>'
                   + '<td>' + miles_or_km1(dist) + '</td>'
		   + '<td>=&nbsp;' + miles_or_km1(current.total_dist) + '</td></tr>'
		   + (current.show_grade && elev != null && start_elev != null && prev_elev != null?
		          '<tr align=right style="color: ' + color + '">' 
                        + '<td>' + feet_or_meters(elev - prev_elev) + ' (' + percent1((elev - prev_elev)/b[1]) + ')</td>'
		        + '<td>=&nbsp;' + feet_or_meters(elev - start_elev) + '</td></tr>'
                      : '')
            };
    current.legs.push(l);
    cloudMap.addOverlay(l.line);
  }

  var p = {lat:  lat,
	   lon:  lon,
	   elev: elev,
	   html: point_html(lat, lon, elev),
	   marker: new GMarker(latlng, { icon: baseIcon[PuceTypeEncours], clickable: false, title: lat_lon_to_string(lat, lon, 0) })
	  };

  current.points.push(p);
  cloudMap.addOverlay(p.marker);

  write_list_div();
  //write_bearing_div();
}


function point_html(lat, lon, elev) {
  return           '<tr align=right><td>' + format_angle(lat, current.latlon_mode, 'N', 'S', 1) + '</td>'
                 + '<td>' + format_angle(lon, current.latlon_mode, 'E', 'W', 1) + '</td>'
		 + (elev != null? '<td>' + feet_or_meters(elev) + '</td>' : '')
	         + '</tr>';
//	   html:   '<tr align=right><td>' + format_angle(lat, current.latlon_mode, 'N', 'S', 1) + '</td>'
//                 + '<td>' + format_angle(lon, current.latlon_mode, 'E', 'W', 1) + '</td>'
//	         + '</tr>',
}


function handle_map_mousemove(latlng) {
  if (!latlng)
    return;
  update_latlon_div(latlng.lat(), latlng.lng());
}


var lastlat;
var lastlon;
function update_latlon_div(lat, lon) {
  if (lat != null && lon != null) {
    lastlat = lat;
    lastlon = lon;
  }
  document.getElementById("map_latlon_div").innerHTML = lat_lon_to_string(lastlat, lastlon, 1);
  //map_latlon_div.innerHTML = lat_lon_to_string(lastlat, lastlon, 1);
}

function latlon_click() {
   current.latlon_mode = (current.latlon_mode + 1) % 3;
   update_latlon_div();
   reset_current_points();
}

function units_click() {
  current.use_metric = radio_get(units_radio) - 0;
  reset_current_points();
  redraw_contour_overlay();
  document.getElementById("interval_div").innerHTML = 'interval des courbes de niveau : ' + contour_interval_with_units(cloudMap.getZoom());
  //complete par jg pour interval manuel finalement pas activé
  /*
  document.getElementById("u1").innerHTML = use_metric? 'm' : 'ft';
  if (current_zoom != null) reset_interval();
  */
}

/*
function set_other_color(s) {
  //document.q.other_color.value = s;
  couleurcourbes = s;
  couleurcourbes = s + 'f0';  	// transparency 30
  //redraw_contour_overlay();
  go();
}

function set_color(s) {
  if (!radio_set(document.q.color, s)) {
    set_other_color(s);
    radio_set(document.q.color, 'other');
  } else {
    set_other_color(s);
  }
  //prefs.set('couleurcourbes', s);
  //couleurcourbes = s + '30';  	// transparency 30
}
*/

function set_color(s) {
  if (s != 'auto'){
    couleurcourbes = s;
  } else {
    couleurcourbes = '';
  }
  go();
}

//debut complete par jg pour interval manuel finalement pas activé
/*
function reset_interval() {
  document.q.interval.value = use_metric? intervals_m._bounded(current_zoom) : intervals_ft._bounded(current_zoom);
}
function set_all_intervals_m(s) {
  intervals_m = [];
  s.split('|')._foreach(function(i) { intervals_m.push(i - 0); });
  prefs.set('intervals_m', intervals_m.join('|'));
}
function set_all_intervals_ft(s) {
  intervals_ft = [];
  s.split('|')._foreach(function(i) { intervals_ft.push(i - 0); });
  prefs.set('intervals_ft', intervals_ft.join('|'));
}
function set_interval_m(zoom, x) {
  if (x < min_intervals_m._bounded(zoom)) {
    alert('Minimum at this zoom is ' + min_intervals_m._bounded(zoom));
    reset_interval();
    return;
  }
  intervals_m[zoom] = x;
  prefs.set('intervals_m', intervals_m.join('|'));
}
function set_interval_ft(zoom, x) {
  if (x < min_intervals_ft._bounded(zoom)) {
    alert('Minimum at this zoom is ' + min_intervals_ft._bounded(zoom));
    reset_interval();
    return;
  }
  intervals_ft[zoom] = x;
  prefs.set('intervals_ft', intervals_ft.join('|'));
}
function set_interval(x) {
  if (isNaN(x - 0))
    x = '';
  if (use_metric)
    set_interval_m(current_zoom, x);
  else
    set_interval_ft(current_zoom, x);
}
*/
//fin complete par jg pour interval manuel finalement pas activé

function write_list_div() {
  set_list_div_style('300px', current.points.length > 12);

  if (!current.points.length) {
    list_div.innerHTML = '';
    return;
  }

  var s = '<table>';
  for (var i = 0; i < current.points.length - 1; i++)
    s += current.points[i].html + current.legs[i].html;
  s += current.points[current.points.length - 1].html + '</table>';
  list_div.innerHTML = s;
}


var geocoder = null;
function geocode(s, f) {
  if (!geocoder)
    geocoder = new GClientGeocoder();
  geocoder.getLatLng(s, function(l) { if (l) f(l); else alert(s + " pas trouvé"); });
}
  

function handle_location() {
  //alert(document.f_location.location.value);
  if (!document.f_location.location.value)
    return;
  geocode(document.f_location.location.value, function(l) { add_point(l.lat(), l.lng()); cloudMap.setCenter(l, 12); });
  document.getElementById('transect_img').src = 'javascript/contours/images/no-profile.png';//jg
  document.getElementById("show_profile").checked = false;//jg
  set_show_profile(false);//jg
}

function get_route() {
  if (current.points.length < 2)
    return;
  var p  = current.points[current.points.length - 1];
  var pp = current.points[current.points.length - 2];
  var NbEtapes = document.getElementById('NbEtapes_Input').value
  if (NbEtapes > 30){
    NbEtapes = 30;
    document.getElementById('NbEtapes_Input').value = 30;
  }
  if (NbEtapes < 2){
    NbEtapes = 2;
    document.getElementById('NbEtapes_Input').value = 2;
  }
  //alert(NbEtapes);
  //wt_async_request_array_of_lines('http://www.heywhatsthat.com/bin/directions.cgi?max=30&elevs=1&q=from+' + pp.lat + ',' + pp.lon + '+to+' + p.lat + ',' + p.lon, 'Directions', parse_directions);
  //wt_async_request_array_of_lines('chargepage.php?url='+encodeURIComponent('http://www.heywhatsthat.com/bin/directions.cgi?max=30&elevs=1&q=from+' + pp.lat + ',' + pp.lon + '+to+' + p.lat + ',' + p.lon, 'Directions'), parse_directions);
  loadXMLdoc('chargepage.php?url='+encodeURIComponent('http://www.heywhatsthat.com/bin/directions.cgi?max=' + NbEtapes + '&elevs=1&q=from+' + pp.lat + ',' + pp.lon + '+to+' + p.lat + ',' + p.lon, 'Directions'));
  if(xmlhttps.readyState==4) {/*complete*/
    pagetxt = xmlhttps.responseText;
    //alert(pagetxt);
    var a = pagetxt.split('\n');
    a.pop();
    parse_directions(a);
  }
}





function point_rectangle(p1, p2) {
  var lat0 = p1.lat;
  var lon0 = p1.lon;
  var lat1 = p2.lat;
  var lon1 = p2.lon;

  if (lat0 > lat1) { var x = lat0; lat0 = lat1; lat1 = x; }
  if (lon0 > lon1) { var x = lon0; lon0 = lon1; lon1 = x; }
  return new GLatLngBounds(new GLatLng(lat0, lon0), new GLatLng(lat1, lon1));
}

function parse_directions(a) {
  //alert(a.length);
  if (a.length > 100)
    return;
  backspace(); // directions end with this point
  a._foreach(function(b) { var c = b.split(' '); add_point(c[0], c[1], c[2]); });
  var r = point_rectangle(current.points[0], current.points[current.points.length - 1]);
  cloudMap.setCenter(r.getCenter(), cloudMap.getBoundsZoomLevel(r));
}


					//***************************** CONTOURS
var contour_overlay;
var contour_widget;
var contour_listener;

				 // 0     1     2     3     4     5     6     7    8    9   10   11   12   13  14  15  16  17 18 19 20 21
var contour_interval_ft_array = [2500, 2500, 2500, 2500, 2500, 1000, 1000, 1000, 500, 250, 100, 100, 100, 100, 50, 25, 10, 10, 10, 10, 10];
var contour_interval_m_array  = [1000, 1000,  750,  750,  750,  250,  250,  250, 200, 100,  50,  50,  25,  25, 25, 10,  3, 3, 3, 3, 3];




function contour_interval_ft(z) {
  if (z >= contour_interval_ft_array.length)
    return contour_interval_ft_array[contour_interval_ft_array.length - 1];
  return contour_interval_ft_array[z];
}

function contour_interval_m(z) {
  if (z >= contour_interval_m_array.length)
    return contour_interval_m_array[contour_interval_m_array.length - 1];
  return contour_interval_m_array[z];
}

function contour_interval_with_units(z) {
  return current.use_metric? contour_interval_m(z) + ' m' : contour_interval_ft(z) + ' ft';
}

function contour_interval(z) {
  return current.use_metric? contour_interval_m(z) : contour_interval_ft(z) / feet_per_meter;
}

function redraw_contour_overlay() {
  if (contour_overlay) {
    document.getElementById("interval_div").innerHTML = 'interval des courbes de niveau : ' + contour_interval_with_units(cloudMap.getZoom());
    document.getElementById("zoomlevel_span").innerHTML = cloudMap.getZoom();
    show_contour_overlay();
    if (contour_widget)
      contour_widget.set_title();
  }
}

function show_contour_overlay() {
  //alert(couleurcourbes);
  if (contour_overlay)
    cloudMap.removeOverlay(contour_overlay);
  contour_overlay = new GTileLayerOverlay(TileLayer(0, 17, 'Courbes', '',
	    function(point, zoom) {
	      // if (!contour_intervals[zoom])
	      //  return 'images/no-contour.png';
	      // force blue color if looking at anything other than 'map' type
		 return 'http://www.heywhatsthat.com/bin/contour_tiles.cgi?x=' + point.x + '&y=' + point.y + '&zoom=' + zoom
		                           + '&interval=' + contour_interval(zoom)
					   + (cloudMap.getCurrentMapType().getName() != 'Map'? '&color=0000FF30' : '');
            }));
  cloudMap.addOverlay(contour_overlay);
  //document.getElementById("interval_div").innerHTML = 'interval entre les courbes de niveau : ' + contour_interval_with_units(cloudMap.getZoom());
}


 



function create_contour_widget(x, width) {
  WTGControl(map, x, width, 'Courbes', '<b>Courbes</b>',
    function() {
      document.getElementById("interval_div").innerHTML = 'interval des courbes de niveau : ' + contour_interval_with_units(cloudMap.getZoom());
      document.getElementById("zoomlevel_span").innerHTML = cloudMap.getZoom();
      return this.state?
		 'interval des courbes de niveau ' + contour_interval_with_units(cloudMap.getZoom())
               : 'Courbes de niveau';
    },
    function(i) {
      if (i) {
        show_contour_overlay();
      } else {
       if (contour_overlay)
          cloudMap.removeOverlay(contour_overlay);
        contour_overlay = null;
      }
    },
    function() {
      contour_widget = this;
    });

  contour_listener = GEvent.addListener(cloudMap, "zoomend", contour_zoom_callback);
}


function contour_zoom_callback(oldz, newz) {
  if (contour_widget)
    contour_widget.set_title();
}



	// Google Maps Bug: copyright stuff seems to only work for new map types, NOT for tile overlays ??
function TileLayer(min_zoom, max_zoom, copyright_prefix, copyright, url_function) {
  var cc = new GCopyrightCollection(copyright_prefix);
  cc.addCopyright(new GCopyright(2, new GLatLngBounds(new GLatLng(-54,-180), new GLatLng(60,180)), min_zoom, copyright));
  var t = new GTileLayer(cc, min_zoom, max_zoom);
  t.getTileUrl = url_function;
  return t;
}


					//***************************** TRANSECTS
var transect_widget;

function init_transect() {
    document.getElementById('transect_img').src = 'javascript/contours/images/no-profile.png';
}

function draw_transect(warn) {
  if (current.points.length < 2) {
    if (warn)
      alert("Il faut au moins placer 2 points,\navant de calculer le profil");
    return;
  }
  document.getElementById("profile").style.display = '';
  document.getElementById("show_profile").checked = true;

  var s = '';
  var i = 0;

  current.points._foreach(function(a) { s += '&pt' + i + '=' + a.lat + ',' + a.lon + ',,,' + colors[i % colors.length ]; i++ });
  document.getElementById('transect_img').src = 'http://www.heywhatsthat.com/bin/profile1.cgi?src=profiler&axes=1&curvature=' + radio_get(flat_earth_radio) + '&metric=' + current.use_metric + s;
}


function clear_transect() {
  if (current.show_transect)
    document.getElementById('transect_img').src = 'javascript/contours/images/no-profile.png';
}



					//***************************** CONTROLS

function WTControl(parent, n_states, enablef, disablef, innerHTMLf, titlef, clickf) {
  this.div        = document.createElement('div');
  parent.appendChild(this.div);
  this.style      = this.div.style;
  this.n_states   = n_states;
  this.enablef    = enablef;
  this.disablef   = disablef;
  this.innerHTMLf = innerHTMLf;
  this.clickf     = clickf;
  this.titlef     = titlef;
  this.state      = 0;
  this.enabled    = 0;
  this.enable();
  this.update();
}

WTControl.prototype.enable = function()  {
  this.enablef(this.div);
  var t = this;
  this.div.onclick = function() { t.onclick(); };
  this.enabled = 1;
  this.set_title();
}

WTControl.prototype.disable = function() {
  this.enabled = 0;
  this.disablef(this.div);
  this.div.onclick = null;
  this.set_title();
}

WTControl.prototype.show = function() {
  this.style.display = '';
}

WTControl.prototype.hide = function() {
  this.style.display = 'none';
}

WTControl.prototype.is_visible = function() {
  return this.style.display != 'none';
}

WTControl.prototype.update = function() {
  this.div.innerHTML = exec_or_value(this.innerHTMLf, this, this.state);
  this.set_title();
}

WTControl.prototype.callback = function() {
  if (this.clickf)
    this.clickf(this.state);
}

WTControl.prototype.onclick = function() {
  this.state++;
  if (this.state >= this.n_states)
    this.state = 0;
  this.update();
  this.callback();
}

//WTControl.prototype.clear_title = function() {
// this.div.title = null;
//}

WTControl.prototype.set_title = function() {
  if (this.titlef)
    this.div.title = exec_or_value(this.titlef, this);
}

WTControl.prototype.set_state = function(state) {
  this.state = state;
  this.update();
}

WTControl.prototype.trigger = function(state) {
  this.state = state;
  this.update();
  this.callback();
}

WTControl.prototype.reset = function() {
  this.trigger(0);
}



	// for these guys, the action happens when the map calls initialize
function WTGControl(map, x, width, text0, text1, titlef, onclick, oncreate) {
  var c = new GControl(0, 0);
  c.initialize = function(map) {
    var w = new WTControl(cloudMap.getContainer(), 2,
	          function(d) { s = d.style;
				s.border          = '1px solid black'
				s.padding         = '0px 3px';
				s.backgroundColor = 'white';
				s.color           = 'black';
				s.fontSize        = '12px';
				s.fontFamily      = 'Arial,sans-serif';
				s.cursor          = 'pointer';
				s.width           = width + 'px';
				s.textAlign       = 'center';
	          },
		  null,  // for disable, tried  function(d) { d.style.color = '#606060'; },
		  function(i) { return i? text1 : text0; },
		  titlef,
		  onclick
            );

    if (oncreate)
      oncreate.call(w);
    return w.div;
  };
  cloudMap.addControl(c, new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(x, 30)));
}

function answerbutton_enable(d) {
  d.className = 'answerbutton';
}


					//***************************** ICONS

	// voir gicons.js modif jg



					//**************************** ELEVATION DATA CACHE
var elevs = new Object;

function get_elev(lat, lon) {
  if (elevs[lat + ' ' + lon] != null)
    return elevs[lat + ' ' + lon];
  //wt_async_request_array_of_lines('http://www.heywhatsthat.com/bin/points.cgi?lat0=' + lat + '&lon0=' + lon, 'Elevation', receive_elev);
  //wt_async_request_array_of_lines('chargepage.php?url='+encodeURIComponent('http://www.heywhatsthat.com/bin/points.cgi?lat0=' + lat + '&lon0=' + lon, 'Elevation'), receive_elev);
  //wt_request_array_of_lines('chargepage.php?url='+encodeURIComponent('http://www.heywhatsthat.com/bin/points.cgi?lat0=' + lat + '&lon0=' + lon, 'Elevation'), receive_elev);
  
  loadXMLdoc('chargepage.php?url='+encodeURIComponent('http://www.heywhatsthat.com/bin/points.cgi?lat0=' + lat + '&lon0=' + lon, 'Elevation'));
  if(xmlhttps.readyState==4) {//complete
    pagetxt = xmlhttps.responseText;
    //alert(pagetxt);
    var a = pagetxt.split('\n');
    a.pop();
    receive_elev(a);
  }

  return null;
}

function receive_elev(a) {
  if (a.length > 100)
    return;
	// points.cgi returns lat/lon with 6 digits of precision, including trailing zeroes,
	// but round6() strips trailing zeroes and that's what we've stored in p.lat and p.lon 
  a._foreach(function(b) { var c = b.split(' '); if (c.length == 3) elevs[round6(c[0]) + ' ' + round6(c[1])] = c[2]; });
  check_elevs();
}

function check_elevs() {
  var got_one = 0;
  current.points._foreach(function(p) {
    var e;
    if (p.elev == null && (e = elevs[p.lat + ' ' + p.lon]) != null) {
      p.elev = e;
      p.html = point_html(p.lat, p.lon, e);
      got_one = 1; }
    });

  if (got_one)
		// BUG: just redo html of legs before and after this point, not the whole thing
		//      (if it's the start point redo the whole thing)
    if (current.show_grade)
      reset_current_points();
    else
      write_list_div();
}


					//***************************** MISCELLANEOUS

function miles_or_km0_no_label(x) {
  return round0(current.use_metric? x/1000 : x/1609.344);
}

function miles_or_km1(x) {
  return current.use_metric?  round1(x/1000).toFixed(1)     + '&nbsp;km'
	                    : round1(x/1609.344).toFixed(1) + '&nbsp;miles';
}

function pretty_degrees(x, pos, neg) {
    return round6(Math.abs(x)) + '&deg;' + (x >= 0? pos : neg);
}

function pretty_lat(x) {
    return pretty_degrees(x, 'N', 'S');
}

function pretty_lon(x) {
    return pretty_degrees(x, 'E', 'W');
}


var feet_per_meter = 3.2808399;

function feet_or_meters_no_label(x) {
  return current.use_metric? round0(x) : round0(x * feet_per_meter);
}

function feet_or_meters(x) {
  return current.use_metric? round0(x) + ' m' : round0(x * feet_per_meter) + ' ft';
}

function percent1(x) {
  return round1(x * 100) + '%';
}


function lat_lon_to_string(lat, lon, is_html) {
  return format_latlon(lat, lon, current.latlon_mode, is_html);
}


var DEGREES_TO_RADIANS = Math.PI / 180.;
var EARTH_RADIUS = 6367447;

function bearing_and_range(lat0, lon0, lat1, lon1) {
	// rotate so viewer at zero longitude
  lon1 -= lon0;

	// about 11cm.  prevents NaN values below
  if (Math.abs(lat1 - lat0) + Math.abs(lon1) < .000001)
     return [0, 0];

  lat0 *= DEGREES_TO_RADIANS;
  lat1 *= DEGREES_TO_RADIANS;
  lon1 *= DEGREES_TO_RADIANS;

  var sinlon1 = Math.sin(lon1);
  var coslon1 = Math.cos(lon1);
  var sinlat0 = Math.sin(lat0);
  var coslat0 = Math.cos(lat0);
  var sinlat1 = Math.sin(lat1);
  var coslat1 = Math.cos(lat1);

  var x = coslat1 * coslon1;
  var y = coslat1 * sinlon1;
  var z = sinlat1;

	// rotate about y axis so viewer at north pole
  var xx =  x * sinlat0 - z * coslat0;
  var yy =  y;
  var zz =  x * coslat0 + z * sinlat0;

  var theta = Math.PI - Math.atan2(yy, xx);
  var phi   = Math.acos(zz);
  return [ theta/DEGREES_TO_RADIANS, phi * EARTH_RADIUS];
}


function adjust_for_declination(d) {
  if (current.magnetic) {
    d -= current.declination;
    if (d < 0)
       d += 360;
    else if (d > 360)
       d -= 360;
  }
  return d;
}

function scroll_if_needed(e, div) {
  var i = e.offsetTop - div.scrollTop;
  if (i < 0)
    e.scrollIntoView();
  else if (i > parseInt(div.style.height) - 23)
    e.scrollIntoView(false);
}


/*
Trying to avoid scrollbars on the list_div
Due to silliness in CSS spec, on firefox (but interestingly
not on IE6 and IE7), once you ask for vertical scrollbar,
you have to specify a horizontal size. Further, layout gets
confused on firefox if you toggle the vertical scrollbar
on and off.
*/

function set_list_div_initial() {
  if (is_msie) {
    list_div.style.overflowY = 'auto';
  } else {
    list_div.style.overflow  = 'auto';
    list_div.style.height    = '500px';
  }
}

function set_list_div_style(min_width, show_vertical_scrollbar) {
  if (is_msie) {
    list_div.style.height = show_vertical_scrollbar? '500px' : 'auto';
  } else {
    //list_div.style.minWidth  = min_width;
  }
}


// hack to add overlay of feature data (until we implement it right)

var icon_data = new GIcon();
icon_data.image = "images/blue-plus.png";
icon_data.shadow = null;
icon_data.iconSize = new GSize(13, 13);
icon_data.shadowSize = new GSize(0, 0);
icon_data.iconAnchor = new GPoint(6, 6);

function getnamesdata() {
  var b = cloudMap.getCenter();
  wt_async_request_array_of_lines('http://www.heywhatsthat.com/bin/namesdata.cgi?lat0=' + b.lat() + '&lon0=' +  b.lng(),
	      'NAMES DATA', function(a) {
		a._foreach(function(s) {
	          var t = s.match(/(-?[\d\.]+) (-?[\d\.]+) ([\-\d]+) \S+ \S+ (.*)/);
		  if (t)
		    cloudMap.addOverlay(new GMarker(new GLatLng(t[1], t[2]),
				{ icon: icon_data, clickable: false, title: feet_or_meters(t[3]) + ' ' + t[4] }));
		});});
}


/**************************
// simplify adding hacks (cf. http://www.elsewhere.org/journal/gmaptogpx)
// just need a bookmark that looks like 'javascript:addon("hack.js")'

function addon(s) {
  var script = document.createElement('script');
  script.src = s;
  document.getElementsByTagName('head')[0].appendChild(script);
}
*****************************/

