// General-purpose functions

////////////////////
// Access to objects 
////////////////////
// Get an object from its name. 
function getObject(objName){
  var currentDoc;

  currentDoc = window.document;
  if (currentDoc){
    if (currentDoc.getElementById)   // IE 5+, NN 6
      return currentDoc.getElementById(objName);
    if (currentDoc.all)              // IE 4+
      return currentDoc.all(objName);
    if (currentDoc.layers)
      return currentDoc.layers[objName];
  }
  return null;
}

//////////////////// 
// Browser/OS check
////////////////////
function isIE() {
  return (navigator.appName == "Microsoft Internet Explorer");
}
function isMozilla(){
	// Note: Safari will return TRUE when calling this function
  return (navigator.userAgent.indexOf("Gecko") != -1);
}
function isFirefox(){
  return (isMozilla() && navigator.userAgent.indexOf("Firefox") != -1);
}
function isChrome(){
	return (navigator.userAgent.toLowerCase().indexOf('chrome') != -1);
}
function isSafari() {
	// Note: Chrome's user agent contains the string "Safari..."
  return (!isChrome() && navigator.userAgent.indexOf("Safari") != -1 );
}
function isOpera() {
  return (navigator.userAgent.indexOf("Opera") != -1 );
}

// Get Operating system
// returns windows, mac, unix, linux or empty string
function getOS(){
  var agent = navigator.userAgent.toLowerCase();

  if (agent.indexOf('win') != -1)
    return "windows";
  if (agent.indexOf('mac') != -1)
    return "mac";
  if (agent.indexOf('linux') != -1) 
    return "linux";
  if (agent.indexOf('x11') != -1)
    return "unix";
  return "";
}


///////////////////
// Event handling 
///////////////////
// Returns the event object.
// evt is the object passed to the function: only available in W3C, IE uses global object 
// window.event
function getEvent(evt){
  if (evt)
    return evt;
  else
    return window.event;   // IE
}

// Returns the target of the event
function getTarget(evt){
  var targetObj;
  var curObj;

  if (evt.target)  // W3C
    targetObj = evt.target;
  else 
    targetObj = evt.srcElement;   // IE
  // With Netscape 6/7, the target object is the text element, and it has
  // no offset (value undefined)
  // We want the a href parent element to be the target object
  curObj = targetObj;
  while (typeof curObj.offsetLeft == "undefined" && curObj.parentNode)
    curObj = curObj.parentNode;

  return curObj;
}


///////////////////
// Positionning
///////////////////
// Utility function: get the minimal non-zero value in an array of values
function getMinPositive(numValues){
	res = 0;
	for (rank = 0; rank < numValues.length; rank++){
		if ((res == 0 && numValues[rank] > 0) || (res > 0 && numValues[rank] < res && numValues[rank] != 0))
			res = numValues[rank];
	}
	return res;
}

// Functions to get the width and height of the visible part of the window, as well as the scroll position on left and top
// This code that should work on all browsers (tested with IE, Firefox, Chrome, Safari, Opera) is inspired from 
// http://www.softcomplex.com/docs/get_window_size_and_scrollbar_position.html
 
// Get the width of the visible part of the window
function getInnerHeight(){
	windowInnerHeight = window.innerHeight ? window.innerHeight : 0;
	docElementClientHeight = document.documentElement ? document.documentElement.clientHeight : 0;
	docBodyClientHeight = document.body ? document.body.clientHeight : 0;
	return getMinPositive(new Array(windowInnerHeight, docElementClientHeight, docBodyClientHeight));
}
// Get the width of the visible part of the window
function getInnerWidth(){
	windowInnerWidth = window.innerWidth ? window.innerWidth : 0;
	docElementClientWidth = document.documentElement ? document.documentElement.clientWidth : 0;
	docBodyClientWidth = document.body ? document.body.clientWidth : 0;
	return getMinPositive(new Array(windowInnerWidth, docElementClientWidth, docBodyClientWidth));
}
// Get the scrollbar offset from leftmost position 
function getScrollLeft(){
	windowXOffset = window.pageXOffset ? window.pageXOffset : 0;
	docElementScrollLeft = document.documentElement ? document.documentElement.scrollLeft : 0;
	docBodyScrollLeft =	document.body ? document.body.scrollLeft : 0;
	return getMinPositive(new Array(windowXOffset, docElementScrollLeft, docBodyScrollLeft));
}
// Get the scrollbar offset from topmost position 
function getScrollTop(){
	windowYOffset = window.pageYOffset ? window.pageYOffset : 0;
	docElementScrollTop = document.documentElement ? document.documentElement.scrollTop : 0;
	docBodyScrollTop =	document.body ? document.body.scrollTop : 0;
	return getMinPositive(new Array(windowYOffset, docElementScrollTop, docBodyScrollTop));
}

// Get window dimension: on x (width) or on y (height)
// axis is "x" or "y"
function getWindowDim(axis){
	if (axis == "x")
		return getInnerWidth();
	else
		return getInnerHeight();
}

// Get scrolling on x or y
function getScroll(axis){

	if (axis == "x")
		return getScrollLeft();
	else
		return getScrollTop();
}

// Get absolute position of an object on X or Y axis
function getObjAbsPos(obj, axis){
  // Parent object that serves  as a reference for positionning
  var parentElt = obj.offsetParent;
  var result;

  // Compute offset of obj relative to its parent
  if (axis == "x")
    result = obj.offsetLeft;
  else
    result = obj.offsetTop;
  // Sum parent position:
  if (parentElt)
    result += getObjAbsPos(parentElt, axis);

  return result;
}


////////////////////
// URL computation
////////////////////
// Returns the path to the last folder, ie the string ending with the last slash (included)
// For instance, if path is http://mysites/mydir/myimage.gif, returns http://mysites/mydir/
// Note: the path must use slashes!
function getPathToFolder(path){
  var slashIndex;

  slashIndex = path.lastIndexOf("/");
  if (slashIndex != -1)
    return path.substring(0, slashIndex) + "/";
  else
    return "";
}


//////////////////////////////////////////
// General-purpose fonctions for cookies
//////////////////////////////////////////
// Set a cookie value (pair name, value)
// The cookie expires when the browser application stops
function setCookie(name, value, cpath){
  // Note: there is a security issue with Netscape 4 when in frame of another domain
  // Note: set cpath to / if you want the cookie to be valid for the entire domain
  // Note: if you consult document.cookie, you only get the name/value pair, even though
  // a path has been set
  if (cpath)
    document.cookie = name + "=" + escape(value) + "; path=" + cpath;
  else
    document.cookie = name + "=" + escape(value);
}

// Returns the cookie value associated to labelName.
// a cookie value string is of format <name1>=<value1>; <name2>=<value2>...
function getCookieData(labelName){
  var cookieData = document.cookie;
  var i = 0;
  var firstChar, lastChar;   // will ultimately contain first and last char of value
  var cookieLength = cookieData.length;

  while (i < cookieLength){
    firstChar = i + labelName.length;
    if (cookieData.substring(i, firstChar + 1) == labelName + '='){
      lastChar = cookieData.indexOf(";", firstChar);
      if (lastChar == -1)   // no ; char because this is the last value of cookie
	      lastChar = cookieData.length;
      return unescape(cookieData.substring(firstChar + 1, lastChar));
    }
    i++;
  }
  return "";   // no value found
}

// Deletes the cookie having the passed name.
function deleteCookie(name){
	if (getCookieData(name) != "")
		document.cookie = name + '=; expires=Thu, 01-Jan-70 00:00:01 GMT;';
}


///////////////////
// Other general-purpose function
///////////////////
// Indicates whether an object is visible, using its style
// objId: ID of the DHTML object
function isVisible(objId){
	var obj;
	
	obj = getObject(objId);
	if (obj){
		return (obj.style.display != "none")
	}else
		return false;
}

// Shows a block and changes the link so that the block can be hidden afterwards
// Note: this function must not return anything else it displays the object returned when called from a page (e.g. livre_finance.php)
function showBlock(blockId, linkId, showText, hideText){
  showHideBlock(blockId, linkId, showText, hideText, true);
}

// Hides a block and changes the link so that the block can be shown afterwards
// Note: this function must not return anything else it displays the object returned when called from a page (e.g. livre_finance.php)
function hideBlock(blockId, linkId, showText, hideText){
  showHideBlock(blockId, linkId, showText, hideText, false);
}

// Shows/hides a block and changes the link so that the block can be hidden/shown afterwards
// This function is called by the finance book page to show/hide prices and by the functions used to expand/collapse a node
// blockId: ID of the block to shown/hidden
// linkId: ID of the link to be updated. Can be NULL. In this case, the function will only show/hide the block
// showText: text of the link when it can show the block
// hideText: text of the link when it can hide the block
// show: true if the block must be shown, otherwise false
// Note: this function must not return anything else it displays the object returned when called from a page (e.g. livre_finance.php)
function showHideBlock(blockId, linkId, showText, hideText, show){
  blockObj = getObject(blockId);
  linkObj = getObject(linkId);
  hrefValue = "";
  if (blockObj){
    if (show){
      // Show the block
      blockObj.style.display = "block";
      if (linkObj){
        // Change the text of the link
        linkObj.innerHTML = hideText;
        // Initialize the link
        hrefValue += "javascript:hideBlock";
      }
    }else{
      blockObj.style.display = "none";
      if (linkObj){
        linkObj.innerHTML = showText;
        hrefValue += "javascript:showBlock";
      }
    }
    if (linkObj){
      // Change link
      hrefValue += "('" + blockId + "', '" + linkId + "', '" + showText + "', '" + hideText + "')";
      linkObj.href = hrefValue;
    }
  }
}

// Shows some blocks and hides others
// shownBlockIds: array of the IDs of the block to be displayed
// hiddenBlockIds: array of the IDs of the blocks to be hidden
function showBlocksHideOthers(shownBlockIds, hiddenBlockIds){
	var rank;

	for (rank = 0; rank < shownBlockIds.length; rank++)
		showBlock(shownBlockIds[rank]);
	for (rank = 0; rank < hiddenBlockIds.length; rank++)
		hideBlock(hiddenBlockIds[rank]);
}

// Shows the passed block if it is hidden and hides other passed blocks 
function toggleBlockHideOthers(blockId, otherBlockIds){
	var block;
	var otherBlock;
	var rank;

	block = getObject(blockId);
	if (block.style.display == "block")
		block.style.display = "none";
	else{
		// Show the clicked block, hide others
		showBlocksHideOthers(new Array(blockId), otherBlockIds);
	}
}


