// add a function to the onload() list
function addLoadListener(fn)
{
	if (typeof window.addEventListener != 'undefined')
	{
	    window.addEventListener('load', fn, false);
	}
	else if (typeof document.addEventListener != 'undefined')
	{
	    document.addEventListener('load', fn, false);
	}
	else if (typeof window.attachEvent != 'undefined')
	{
	    window.attachEvent('onload', fn);
	}
	else if (typeof window.onload != 'function') {
	    window.onload = fn;
	} 
	else 
	{
	    var oldonload = window.onload;
	    window.onload = function() {
		if (oldonload) { oldonload(); }
		func();
	    }
	}
	return true;
};

// return true if a value is defined and not empty
// tanks CGI::Ajax for this
function exists (v)
{
    return (v != undefined && v != '');
}

//wrapper around exists to do the document.getElementByid(...).value
function existsID (id)
{
    var e = document.getElementById(id);
    return e ? exists(e.value) : false;
}

//return an Xhr accepted by the browser
function getXhr ()
{
    var xmlhttp;
 
    if(typeof XMLHttpRequest != "undefined")
    {
        xmlhttp= new XMLHttpRequest();
    }
    else
    {			  
	var msv= ["Msxml2.XMLHTTP.7.0", "Msxml2.XMLHTTP.6.0",
		  "Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0",
		  "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];
	for(var j=0;j<=msv.length;j++){
	    try
		{
		    A = new ActiveXObject(msv[j]);
		    if(A){ 
			xmlhttp = new ActiveXObject(msv[j]);
			break;
		    }
		}
	    catch(e) { }
	}
    }

    return xmlhttp;
}

/*
* Execute an ajax call
* okfcn: unction to be executed when results arrives
* xurl: url to call
* hurl: fallback http url to call on a popup if no xhr
*/
function getAjax(okfcn, xurl, hurl)
{
	var xhr = getXhr();
	if (xhr)
	{
      document.body.style.cursor='wait';
      if (okfcn) { xhr.onreadystatechange = function() {okfcn(xhr)} };
      xhr.open("GET",xurl);
      xhr.send(null);
  }
  else
  {
      if (hurl)
      {
        window.open(hurl);
      }
  }
  
  return false;
}

/*
 * Return true if parameter is an array, false otherwise
 */
function isArray(o)
{
    return (o.constructor.toString().indexOf("Array") != -1);
}

/*
 * not tested yet
 */
function addEvent(obj, sType, fn){
    if (obj.addEventListener){
        obj.addEventListener(sType, fn, false);
    } else if (obj.attachEvent) {
        var r = obj.attachEvent("on"+sType, fn);
    } else {
        alert("Handler could not be attached");
    }
}


/*
 * call console.log, but only if it exists
 * i had to use try/catch for IE. this is weird, though. why if (console) does not work?
 */

function logme(str)
{
    
    try	{
	console.log(str);
    }
    catch (e)	{
	//	alert ('logged' + str);
    }
}

/*
 * thanks quirksmode.org
 * returns the pixel (left, top) position of an object
 */
function findPos(obj) {
    var curleft = curtop = 0;
    if (obj.offsetParent) {
	do {
	    curleft += obj.offsetLeft;
	    curtop += obj.offsetTop;
	} while (obj = obj.offsetParent);
    }
    return {x:curleft, y:curtop};
}

/*
 * general stuff
 */

/*
 * called on results.cgi, when the master select box changed => select/deselect all others
 */
function selectall (obj)
{
    var checked = obj.checked ? 'checked' : '';
    var boxes = document.getElementsByName('inum');
    for (var i=0; i<boxes.length; i++)
	{
	    boxes[i].checked=checked;
	}
}


/*
 * set the columns at the same size
 * It takes the 'main' column and the 'menu' column, and set their bottom at the same height.
 * 
 * Currently, the main column has the id 'bcol', and I set its last non-text child.
 * 
 * For menu, if there is an element with the NAME 'scolMenu', it will be used, if not I take the last 
 * non-text child of ID scol1 (this is needed for the metadata menu, for instance)
 *
 */
addLoadListener(column_size);
function column_size ()
{

    // we can't just set the column size, because they are container. We have to play with the columns inside these
    var body = getCol('bcol');
    
    var menu = '';
    var scolMenu = document.getElementById('scolMenu');
    var offset = 0; // this is needed if we are using a element by name
    if (scolMenu)
    {
      menu = scolMenu;

      offset = -5;
    }
    else
    {
      menu = getCol('scol1');
      offset = -10;
    }

    if ((menu != '') && (body != ''))
	{
	    var b_top = findPos(body).y;
	    var m_top = findPos(menu).y;

	    var m_bot =  m_top + menu.offsetHeight;
	    var b_bot =  b_top + body.offsetHeight;

	    if ( (m_bot > b_bot ))
		{
		    body.style.height = (m_bot - b_top)  + 'px';
		}
	    else
		{
		    menu.style.height = (b_bot - m_top + offset)  + 'px';
		}
	}
}

//returns the last non-text child of the elem whose id is in param
// return '' if elem not found
function getCol (id)
{
    var root = document.getElementById(id);
    if (!root) {return ''}

    var nodes = root.childNodes;
    for (var child = nodes.length - 1; child >= 0; child--)
	{
	    if (nodes[child].nodeType != 3) {return nodes[child]}
	}

    return '';
}

/*
 * This is triggered on a link click
 * popup the href instead of just following the link
 * returns false to avoid the link as well
 */

var _helpParam = "resizable=yes,scrollbars=yes,height=350,width=690";
var _bigParam = "resizable=yes,scrollbars=yes,height=770,width=762";

function help (obj, big)
{
    if (big){window.open(obj.href, "help", _bigParam);}
    else { window.open(obj.href, "help", _helpParam);}
    return false;
}

/*
 * open a new windows towards the href of the param
 */
function newwin (obj)
{
    window.open(obj.href, obj.href);
    return false;
}

/*
 * returns a standard map
 * id => map id
 * params => parameters to send to the map
 * options, hash, optional.
 *    layer => array of layer for the map. If present, they will be the only one.
 */
function genMap (id, params, options)
{
    //if we can't access google map, just leave...
    // other possibility: use another type of layer


    //we need to forbid the display of the world beyond the antimeridian
    GMercatorProjection.prototype.tileCheckRange = 
	function(tile,zoom,tilesize) {
	var maxTile = Math.floor(this.getWrapWidth(zoom) / tilesize);
	return ! (tile.x < 0 || tile.x >= maxTile || tile.y < 0 || tile.y >=  maxTile);
    }
    
    var layer;
    if (options && options.layer) {layer = options.layer}
    else {
      try {
	  layer = new OpenLayers.Layer.Google("Google Normal", { 'type': G_NORMAL_MAP,
								 'sphericalMercator': true,
								 MIN_ZOOM_LEVEL: 1
	    });
      }
      catch (e)	{
        logme (e);
	return false;
      }
      if (!layer) {return false;}
      layer=[layer];
    }

    if (!params) { params = {};}

    if (!params.theme)        { params.theme = '/css/openlayers.css'}
    if (!params.maxResolution){ params.maxResolution = 156543.0339}
    if (!params.projection)   { params.projection = new OpenLayers.Projection("EPSG:900913")}
    if (!params.units)        { params.units = 'm'}
    var toolbar;
    if (!params.controls)     { 
	toolbar = new OpenLayers.Control.NavToolbar();
	toolbar.controls[0].zoomWheelEnabled = false;
	params.controls=[new OpenLayers.Control.PanZoomBar(), toolbar];
    }

    var m = new OpenLayers.Map(id, params);
    m.addLayers(layer);
    // apparently, the (0,0) position for the map is at (left:6,top:300) of the top left corner of the map.
    // it means under the other control, basicaly
    // the 68 below is: 56 (size of the 2 images) + 6 (initial left position) + 6 (final 'padding')

    //WEIRD: the toolbar controls are duplicated. I do not know why.
    // This leads to a pathc in Maps.js:destroy
    if (toolbar)
    {
      toolbar.draw(new OpenLayers.Pixel(m.getSize().w-(68),-294));
      toolbar.activateControl(toolbar.controls[1]); // activate zoombax (why can;t I activate it alone??)
    }
    
    return m;

}

/*Return UK extent, or null if openlayers fails*/
function getUKExt()
{
	//UKExt (12W 3E / 49N 61N)
    return new OpenLayers.Bounds( -12, 49 , 3, 61 );
}

/*
 * Return world extent, or null if openlayers fails
 * optionnaly transform the coordinates from EPSG:4326 to the parameter
*/
function getWorldExt()
{   
    return new OpenLayers.Bounds(-180,-90,180,90);
}

/*
 * transform the parameter in EPSG:900913
 * please notice that we need to convert the +/-180 long and =/-90 lat to 179 and 89.
 */
function google(bounds)
{
  //LatLong case
  if (bounds.lat != undefined) { bounds.lat = cheatLat (bounds.lat) }
  if (bounds.lon != undefined) { bounds.lon = cheatLon (bounds.lon) }

  // bounding case
  if (bounds.left  != undefined) { bounds.left  = cheatLon (bounds.left)  }
  if (bounds.right != undefined) { bounds.right = cheatLon (bounds.right) }
  if (bounds.top   != undefined) { bounds.top   = cheatLat (bounds.top)   }
  if (bounds.bottom!= undefined) { bounds.bottom= cheatLat (bounds.bottom)}

  return bounds.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));
}

/*
 * To be called when we grab values from the map itself
 * Convert from Mercatot to Lon/Lat
 */
function fromGoogle(bounds)
{
    return bounds.transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326"));    
}


/*If a latitude is +/- 90, returns +/-89*/
function cheatLat (lat)
{
    if (lat == 90)      {return 89}
    else if (lat == -90){return -89}
    else                {return lat}
}

/*If a longitude is +/- 180, returns +/-179*/
function cheatLon (lon)
{
    if (lon == 180)      {return 179}
    else if (lon == -180){return -179}
    else                 {return lon}
}

/* For terns and conditions checkbox*/

function validate(form) {
	
	// Checking if at least o button is selected. Or not.
	if (!form.confirmTnC.checked){
		alert("Please accept the Terms and Conditions.");
		return false;
	}
	
	return true;
}
