/**
 * JavaScript librairy
 * To enable cross-browser functionality on HostFlow
 * 
 * Should be compatible with : Internet Explorer (5+), Opera (7.1+), Netscape (7+), Mozilla (1.3+) and Konqueror 3.0+
 * Compatibility with previous versions has not been tested but might work with : Opera 7, Netscape 6 and Mozilla 1.0
 * 
 * Author : Cyril MICHAUD
 * Date : 08/05/2003
 */
var CURRENT_DATE;
var CURRENT_DATE_TIME;
var browser = 0;
//var browserVersion = 0;

var g_sHTMLTemplate = null;

var NETSCAPE = 1;
var IE = 2;
//notice: Konqueror is also Webkit, i.e. Safari
var KONQUEROR = 3;
var OPERA = 4;
var CHROME = 5;

var HELP_LAYER_NAME = "hf_help_layer";
var HELP_BGCOLOR = "#fffedd";

var TEXT_TO_UPPER = 1;
var TEXT_TO_LOWER = 2;
var TEXT_TO_CAPITALIZE = 3;
var TEXT_NO_FORMAT = 4;
var TEXT_TO_UPPER_ONLY_WORD = 5;

//from here
DOM = (document.getElementById) ? 1 : 0;
NS4 = (document.layers) ? 1 : 0;
IE4 = (document.all) ? 1 : 0;
IE7 = navigator.userAgent.indexOf("MSIE 7") > -1 ? 1 : 0;
Opera5 = (navigator.userAgent.indexOf("Opera 5") > -1 || navigator.userAgent.indexOf("Opera/5") > -1) ? 1 : 0;
//to here : to be deleted
//only here for compatibility with old templates

// Resalys namespace
com = {};
com.softbooking = {};
com.softbooking.resalys = {
    log: function( s )
    {
      if ( window.console )
        window.console.log( s );
    }
};

/**
 * Identify the browser
 * Return :
 *    - NETSCAPE : for Netscape Navigator and compatibles (ex: Mozilla)
 *    - IE : for Internet Explorer and compatibles (ex: Opera)
 *    - KONQUEROR : for Konqueror browser
 */
function getBrowser() {
    if(browser == 0) {
        var bwr = navigator.appName;
	var vendor = navigator.vendor;
	if( vendor == "Google Inc." ) {
	    browser = CHROME;
	}
        else if(bwr == "Netscape") {
            browser = NETSCAPE;
        }
        else if (bwr == "Microsoft Internet Explorer") {
            browser = IE;
        }
        else if (bwr == "Konqueror") {
            browser = KONQUEROR;
        }
        else if (bwr == "Opera") {
            browser = OPERA;
        }
        else {
            //unknown browser... we suppose it is a JavaScript compliant (not JScript) like Netscape or Mozilla
            browser = NETSCAPE;
        }
    }
    return browser;
}

// Figure out what browser is being used - taken from JQuery
/*function getBrowser() {
	if (browser == 0) {
		var userAgent = navigator.userAgent.toLowerCase();
		if (/webkit/.test( userAgent ))
			browser = KONQUEROR;
		else if (/opera/.test( userAgent ))
			browser = OPERA;
		else if (/msie/.test( userAgent ) && !/opera/.test( userAgent ))
			browser = IE;
		else if (/mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent ))
			browser = NETSCAPE;
		else
			browser = NETSCAPE;
	}
	return browser;
};

function getBrowserVersion() {
	if (browserVersion == 0) {
		var userAgent = navigator.userAgent.toLowerCase();
		browserVersion = (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1]; 
	}
	return browserVersion;
}

FF3 = (getBrowser()==NETSCAPE && getBrowserVersion()>3) ? 1 : 0;
if (FF3)
	alert('Running under firefox 3');*/

/**
 * Get the specified layer
 * Parameters :
 *   - layerName : the short name of the layer to show (example : <DIV id="toto">  => layerName="Toto")
 *                 note : a layer must be a <DIV> object to be compatible with both Netscape and IE
 *   - myDocument (optional) : default value = window.document
 *           Allows to specify a document object on another window
 * Returns :
 *   the layer object
 */

var paLayerCache = new Array();
var bUseLayerCache = false;
function getLayer( sLayerName, pDocument )
{
  if( pDocument == null) pDocument = window.document;

  if( !bUseLayerCache )
    return pDocument.getElementById( sLayerName );
  
  // Cache des layers
  if( !paLayerCache[ pDocument.title + sLayerName ] )
  {
    paLayerCache[ pDocument.title + sLayerName ] = pDocument.getElementById( sLayerName );
  }

  return paLayerCache[ pDocument.title + sLayerName ];
}

/**
 * Show the specified layer
 * Parameters :
 *   - layerName : the short name of the layer to show (example : <DIV id="toto">  => layerName="Toto")
 *                 note : a layer must be a <DIV> object to be compatible with both Netscape and IE
 *   - myDocument (optional) : default value = window.document
 *           Allows to specify a document object on another window
 * Returns :
 *   void
 */
function showLayer(layerName, myDocument, bBugFix, sNewValue, bSetVisibilityAttribute )
{
  var layers = getLayer(layerName, myDocument);

  var sNewDisplay = sNewValue ? sNewValue : '';

  if( bBugFix && layerName != 'globalcontent'  ) hideGlobalLayer();

  if(layers)
  {
    if( layers.length != null && layers.length > 0 )
    {
      for( var i = 0 ; i < layers.length ; i++ )
      {
        if (bSetVisibilityAttribute)
          layers[ i ].style.visibility = 'visible';
        else
          layers[ i ].style.display = sNewDisplay;
      }
    }
    else
    {
      if (bSetVisibilityAttribute)
        layers.style.visibility = 'visible';
      else
        layers.style.display = sNewDisplay;
    }
  }

  if( bBugFix && layerName != 'globalcontent'  ) showGlobalLayer();
}

/**
 * Hide the specified layer on the current html document
 * Parameters :
 *   - layerName : the short name of the layer to show (example : <DIV id="toto">  => layerName="Toto")
 *   - myDocument (optional) : default value = window.document
 *           Allows to specify a document object on another window
 * Returns :
 *   void
 */
function hideLayer( layerName, myDocument, bBugFix, unused, bSetVisibilityAttribute )
{
  var layers = getLayer(layerName, myDocument);
  if( layers == null )
  {
    return;
  }

  if( bBugFix && layerName != 'globalcontent' ) hideGlobalLayer();

  if( layers.length != null && layers.length > 0 )
  {
    for( var i = 0 ; i < layers.length ; i++ )
    {
      if (bSetVisibilityAttribute)
        layers[ i ].style.visibility = 'hidden';
      else
        layers[ i ].style.display = 'none';
    }
  }
  else
  {
    if (bSetVisibilityAttribute)
      layers.style.visibility = 'hidden';
    else
      layers.style.display = 'none';
  }

  if( bBugFix && layerName != 'globalcontent' ) showGlobalLayer();
}

// plus propre pour firefox
function showRow( sRowID, pDocument, bBugFix )
{
  var sNewDisplay = '';
  if ( getBrowser() == NETSCAPE  )
    sNewDisplay = 'table-row';

  showLayer( sRowID, pDocument, bBugFix, sNewDisplay );
}

function showRowIf( sRowID, bTest, pDocument, bBugFix )
{
  if( bTest )
    showRow( sRowID, pDocument, bBugFix );
  else
    hideRow( sRowID, pDocument, bBugFix );
}

// juste un alias
function hideRow( sRowID, pDocument, bBugFix )
{
  hideLayer( sRowID, pDocument, bBugFix );
}

/**
 * Get if the layer is currently displayed or not
 * Parameters :
 *   - layerName : the short name of the layer (example : <LAYER id="toto">  => layerName="Toto")
 *   - myDocument (optional) : default value = window.document
 *           Allows to specify a document object on another window
 * Returns :
 *   - true : the layer is displayed
 *   - false : the layer is not displayed
 */
function getLayerDisplayed(layerName, myDocument)
{
  var layers = getLayer(layerName, myDocument);
  if(!layers)
    return false;

  var style = (layers.length != null) ? layers[0].style : layers.style;

  return style.display == '' || style.display == 'block';
}



/**
 * Resize a layer
 * Parameters :
 *   - layerName : the short name of the layer (example : <LAYER id="toto">  => layerName="Toto")
 *   - width : the new width for the layer
 *   - height : the new height for the layer
 *   - myDocument (optional) : default value = window.document
 *           Allows to specify a document object on another window
 * Returns :
 *   - true : the layer is displayed
 *   - false : the layer is not displayed
 */
function resizeLayer(layerName, width, height, myDocument) {
  var objLayer = getLayer(layerName,myDocument);
  objLayer.style.width = width;
  objLayer.style.height = height;
}


/**
 * Get a layer size
 * Parameters :
 *   - layerName : the short name of the layer (example : <LAYER id="toto">  => layerName="Toto")
 *   - myDocument (optional) : default value = window.document
 *           Allows to specify a document object on another window
 * Returns :
 *   an array containing the size :
 *      ['height']
 *      ['width']
 */
function getLayerSize(layerName, myDocument) {
  var objLayer = getLayer(layerName, myDocument);
  var res = new Array();
  res['width'] = objLayer.style.width;
  res['height'] = objLayer.style.height;

  return res;
}


/**
 * Move a layer
 * Parameters :
 *   - layerName : the short name of the layer (example : <LAYER id="toto">  => layerName="Toto")
 *   - x : the new horizontal position
 *   - y : the new vertical position
 *   - myDocument (optional) : default value = window.document
 *           Allows to specify a document object on another window
 * Returns :
 */
function moveLayer(layerName, x, y, myDocument) {
  var browser = getBrowser();
  if(myDocument == null) myDocument = window.document;

  var objLayer = getLayer(layerName, myDocument);
  switch (browser) {
  case NETSCAPE :
      objLayer.style.top = y;
      objLayer.style.left = x;
      break;
  case CHROME :
  case KONQUEROR :
  case OPERA :
  case IE :
      objLayer.style.offsetTop = y;
      objLayer.style.offsetLeft = x;
      break;
  }
}

/**
 * Permet de déplacer une layer (div avec position: absolute)
 * A la même place qu'un autre élément de la page.
 * bUnderElement permet de positioner la layer en dessous de l'élement en question
 */
function moveLayerToElement(pLayer, pElement, bUnderElement)
{
    // sous internet explorer
    //  la proporiété element.style.top est une chaine de caratère qui peut
    //  être sous la forme 1cm ou 1px, c'est pourquoi on passe par la propriété
    //  offsetLeft et offsetHeight, qui est une propriété récursive de parent en parent
    if(getBrowser() == IE)
    {
        var iTop = pElement.offsetTop;
        var iLeft = pElement.offsetLeft;
        pParent = pElement.offsetParent;
        while( pLayer.offsetParent != pParent )
        {
            iTop += pParent.offsetTop;
            iLeft += pParent.offsetLeft;
            pParent = pParent.offsetParent;
        }
        pLayer.style.pixelTop = iTop + (bUnderElement ? pElement.offsetHeight : 0);
        pLayer.style.pixelLeft = iLeft;
    }
    // sous firefox, cela marche de faire cela... je ne sais pas ce qui se passe
    //  si une valeur est spécifiée en "cm"
    else
    {
        pLayer.style.top = pElement.style.top + (bUnderElement ? pElement.style.height : 0);
        pLayer.style.left = pElement.style.left;
    }
}


/**
 * Get a layer position
 * Parameters :
 *   - layerName : the short name of the layer (example : <LAYER id="toto">  => layerName="Toto")
 *   - myDocument (optional) : default value = window.document
 *           Allows to specify a document object on another window
 * Returns :
 *   an array containing the positions :
 *      ['top'] : the vertical postion
 *      ['left'] : the horizontal position
 */
function getLayerPosition(layerName, myDocument) {
  var browser = getBrowser();
  var objLayer = getLayer(layerName, myDocument);
  var res = new Array();
  switch (browser) {
  case NETSCAPE :
    res['top'] = findPosY( objLayer );
    res['left'] = findPosX( objLayer );
    break;
  case KONQUEROR :
  case OPERA :
  case CHROME :
  case IE :
    res['top'] = objLayer.style.offsetTop;
    res['left'] = objLayer.style.offsetLeft;
    break;
  }
  return res;
}

/*
 * Hides the global layer (on mozilla only) so that operations on layers are done smoothly and without error
 * hideGlobalLayer and showGlobalLayer should be used when showing or hiding large layers.
 */
function hideGlobalLayer( pDocument )
{
  if ( getBrowser() == NETSCAPE )
    setDOMObjectProperty( 'globalcontent', 'style.display', 'none' );
}

/*
 * See hideGlobalLayer()
 */
function showGlobalLayer( pDocument )
{
  if ( getBrowser() == NETSCAPE )
    setDOMObjectProperty( 'globalcontent', 'style.display', '' );
}

var paRegExp = new Array();

function getRegExp( sExp, sParams )
{
    if( !paRegExp[ sExp ] )
    {
        paRegExp[ sExp ] = new RegExp( sExp, sParams );
    }
    paRegExp[ sExp ].lastIndex = 0;
    return paRegExp[ sExp ];
}

function clearRegExpCache()
{
  paRegExp = new Array();
}

/**
 * Get a form object.
 * Parameters :
 *   - inputName : the short name of the object to get (example : <INPUT NAME="toto">  => Name="Toto")
 *   - formName (optional) : the name of the form which contains the input object
 *                 If the input object is not in a form, put formName = ''
 *   - myDocument (optional) : default value = window.document
 *                 Allows to specify a document object on another window
 *   - enforce (optional) : SHOULD NOT BE USED.
 *                 When an input object is not inside a form object, the input object must be named with the ID tag
 *                 instead of the NAME tag. If not, the object will not be accessible by Netscape browsers.
 *                 Setting enforce value to TRUE removes the Internet Explorer warning message.
 * Returns :
 *   . the object if found
 */
function getFormObject(inputName, formName, myDocument, enforce)
{
    var browser = getBrowser();
    if(myDocument == null || myDocument == '') myDocument = window.document;
    var object;
    switch(browser)
    {
      case CHROME :
      case NETSCAPE :
        if(formName == null || formName == '' || formName == "all") 
        {
          object = myDocument.getElementById(inputName);
          if (object == null) 
          {
        	  object = myDocument.getElementsByName(inputName)[0];
          }
        }
        else if( myDocument[formName] )
          object = myDocument[formName][inputName];
        if(!object)
          return null;
        break;
      case KONQUEROR :
      case OPERA :
      case IE :
        if(formName == null || formName == '')
          formName = "all";
        object = myDocument[formName] ? myDocument[formName][inputName] : null;
        if(!object)
          return null;

        if((object.id == null || object.id == "") && formName == 'all' && !enforce)
          window.alert("Warning : your Javascript will only work on Internet Explorer browsers.\nYou have to provide a value for the 'formName' argument.");
        break;
    }
    return object;
}

/**
 * Get objects with specified name.
 */
function getObjectsByName( sName )
{
    return document.getElementsByName( sName );
}

function setObjectProperty(pObject,sProperty,sValue)
{
  if(pObject == null)
    return null;
  var aProperties = new String(sProperty).split(".");
  var sOldValue = null;
  if(pObject)
  {
    if(aProperties.length == 1)
    {
      sOldValue = pObject[aProperties[0]];
      pObject[aProperties[0]] = sValue;
    }
    else if(aProperties.length == 2)
    {
      sOldValue = pObject[aProperties[0]][aProperties[1]];
      pObject[aProperties[0]][aProperties[1]] = sValue;
    }
  }
  return sOldValue;
}

function setNamedObjectProperty(inputName, sProperty, sValue)
{
    var aObjects = document.getElementsByName(inputName);
    for(var i=0;i<aObjects.length;i++)
    {
        aObjects[i][sProperty] = sValue;
    }
}

function setDOMObjectProperty( inputName, sProperty, sValue, pDocument )
{
  var sOldValue;
  if(g_sHTMLTemplate && g_sHTMLTemplate != "")
  {
    var a;
    // if it's a style
    if(a = getRegExp('^style\.(.*)$').exec(sProperty))
      sOldValue = updateInputObjectStyleTag(inputName, a[1], sValue);
    // if its a tag without value (e.g. disabled)
    else if(sValue === true || sValue === false)
      sOldValue = updateInputObjectNoValueTag(inputName, sProperty, sValue);
    else
      sOldValue = updateInputObjectTag(inputName, sProperty, sValue);
  }
  else
  {
    var pObject = getDOMObject( inputName, pDocument );
    sOldValue = setObjectProperty(pObject, sProperty, sValue);
  }
  return sOldValue;
}

function setFormObjectProperty(inputName, formName, sProperty, sValue, pDocument)
{
  var sOldValue;
  if(g_sHTMLTemplate && g_sHTMLTemplate != "")
  {
    var a;
    // if it's a style
    if(a = getRegExp('^style\.(.*)$').exec(sProperty))
    {
      var sStyle = a[1];
      sOldValue = updateInputObjectStyleTag(inputName, sStyle, sValue);
      //updateInputObjectStyleTag(inputName+'_select', sStyle, sValue);
      //updateInputObjectStyleTag(inputName+'_text', sStyle, sValue);
    }
    // if its a tag without value (e.g. disabled)
    else if(sValue === true || sValue === false)
    {
      sOldValue = updateInputObjectNoValueTag(inputName, sProperty, sValue);
      //updateInputObjectNoValueTag(inputName+'_select', sProperty, sValue);
      //updateInputObjectNoValueTag(inputName+'_text', sProperty, sValue);
    }
    else
    {
      sOldValue = updateInputObjectTag(inputName, sProperty, sValue);
      //updateInputObjectTag(inputName+'_select', sProperty, sValue);
      //updateInputObjectTag(inputName+'_text', sProperty, sValue);
    }
    // special, when we disable a field that have an associated link, hide this link
//    if(sProperty == 'disabled')
//      updateInputObjectStyleTag(inputName+'_link', 'visibility', sValue ? 'hidden' : 'visible');
  }
  else
  {
    var pObject = getFormObject(inputName, formName, pDocument);
    sOldValue = setObjectProperty(pObject, sProperty, sValue);
/*    pObject = getFormObject(inputName+'_select', formName);
    setObjectProperty(pObject, sProperty, sValue);
    pObject = getFormObject(inputName+'_text', formName);
    setObjectProperty(pObject, sProperty, sValue);*/
    // special, when we disable a field that have an associated link, hide this link
/*    if(sProperty == 'disabled')
    {
      pObject = getDOMObject(inputName+'_link');
      setObjectProperty(pObject, 'style.visibility', sValue ? 'hidden' : 'visible');
    }*/
  }
  return sOldValue;
}

/**
 * Return the element with and id or name equal to the given inputName.
 * @param <String> inputName The input name, used to find an element with this id or name.
 * @param <DOM> myDocument Document to look inside to find an element with the given id or name
 * @return <Object> The element with the given id or name. Null if no element found.
 */
function getDOMObject(inputName, myDocument)
{
    if(myDocument == null || myDocument == '') myDocument = window.document;
    var ret = myDocument.getElementById(inputName);
    if ( ret != null )
         return ret;
    ret = myDocument.getElementsByName(inputName);
    if ( ret.length > 0)
       return ret.item(0);
    return null;
}

/**
 * Return the elements with and id or name equal to the given inputName.
 * @param <String> inputName The input name, used to find an element with this id or name.
 * @param <DOM> myDocument Document to look inside to find an element with the given id or name
 * @return <Object> The element with the given id or name. Null if no element found.
 */
function getDOMObjects(inputName, myDocument)
{
    if(myDocument == null || myDocument == '') myDocument = window.document;
    return myDocument.getElementsByName(inputName);
}

function getDOMInputValue( sObjectID, pDocument )
{
  return getObjectValue( getDOMObject( sObjectID, pDocument ) );
}

/**
 * Get the value of a form object.
 * Parameters :
 *   - inputName : the short name of the layer (example : <INPUT NAME="toto">  => Name="Toto")
 *   - formName (optional) : the name of the form which contains the input object
 *                 If the input object is not in a form, put formName = ''
 *   - myDocument (optional) : default value = window.document
 *                 Allows to specify a document object on another window
 *   - enforce (optional) : SHOULD NOT BE USED.
 *                 When an input object is not inside a form object, the input object must be named with the ID tag
 *                 instead of the NAME tag. If not, the object will not be accessible by Netscape browsers.
 *                 Setting enforce value to TRUE removes the Internet Explorer warning message.
 * Returns :
 *   . object is unique textfield/textarea : the value of the textfield
 *   . object is unique checkbox or radio : TRUE is checked, FALSE otherwise
 *   . object is multiple radio : the value of the radio checked
 *   . object is unique select-one : the value of the selected option
 *   . object is unique select-multiple : array of the values representing the selected options
 *   . other : unsupported
 */
function getInputValue( inputName, formName, myDocument, enforce )
{
  var ret = getFormObject( inputName, formName, myDocument, enforce );
  var val = getObjectValue( ret );
  if ( typeof(val) === 'undefined' && typeof(jQuery) !== 'undefined' )
  {
     val = jQuery( 'form[name="' + formName + '"] input[name="' + inputName + '"]').val();
  }
  return val;
}

function getObjectValue( object )
{
  if( object == null )
  {
    return null;
  }
    
  if(object.length != null)
  {
      var nb = object.length;
      if(object.type == "select-one")
      {
        var i;
        for(i=0; i<nb; i++)
        {
          if(object.options[i].selected)
            return object.options[i].value;
        }
        return null;
      }
      else if(object.type == "select-multiple")
      {
        var res = new Array();
        for(var i=0; i<object.options.length; i++)
        {
          if(object.options[i].selected)
              res.push(object.options[i].value);
        }
        return res;
      }
      else if(object[0].type == "radio")
      {
        var i;
        for(i=0; i<nb; i++)
        {
          if(object[i].checked)
            return object[i].value;
        }
        return null;
      }
  }
  else if(object.type == "checkbox")
  {
    return object.checked;
  }
  else if(object.type == "radio")
  {
    if(object.checked)
      return object.value;
    else
      return null;
  }
  else
    return object.value;
}





/**
 * Set the value of a form object.
 * Parameters :
 *   - inputName : the short name of the layer (example : <INPUT NAME="toto">  => Name="Toto")
 *   - value : the new value
 *      . object is unique textfield/textarea : the new value of the textfield
 *      . object is unique checkbox or radio : TRUE to check, FALSE to uncheck
 *      . object is multiple radio : the value of the radio to check
 *      . object is unique select-one : the value of the option to select
 *      . object is unique select-multiple : array of values representing the options to select
 *      . other : not supported
 *   - formName (optional) : the name of the form which contains the input object
 *                 If the input object is not in a form, put formName = ''
 *   - myDocument (optional) : default value = window.document
 *                 Allows to specify a document object on another window
 *   - enforce (optional) : SHOULD NOT BE USED.
 *                 When an input object is not inside a form object, the input object must be named with the ID tag
 *                 instead of the NAME tag. If not, the object will not be accessible by Netscape browsers.
 *                 Setting enforce value to TRUE removes the Internet Explorer warning message.
 * Returns :
 */

function setObjectValue( object, value )
{
  if( object == null )
    return;
  
  // text field    
  if(object.type == "text")
  {
    if(value == undefined)
      object.value = '';
    else
      object.value = value;
  }
  // select
  else if(object.length != null)
  {
    var nb = object.length;
    if(object.type == "select-one")
    {
      var i;
      for(i=0; i<nb; i++)
      {
        if(object[i].value == value)
          object.options[i].selected = true;
      }
    }
    else if(object.type == "select-multiple")
    {
      var i, j;
      if(!(value instanceof Array))
      {
        var aValue = new Array();
        aValue.push(value);
        value = aValue;
      }
      for(i=0; i<nb; i++)
      {
        object[i].selected = false;
        for (j=0; j<value.length; j++)
        {
          if(object[i].value == value[j])
            object[i].selected = true;
        }
      }
    }
    else if(object[0].type == "radio")
    {
      var i;
      for(i=0; i<nb; i++)
      {
        object[i].checked = false;
        if(object[i].value == value)
          object[i].checked = true;
      }
    }
    else
    {
       for ( var i = 0; i < nb; i++ )
       {
          object[i].value = value;
       }
    }
  }
  else if(object.type == "checkbox")
  {
    if (!value || value == 'false')
      object.checked = false;
    else
      object.checked = true;
  }
  else if(object.type == "radio") 
  {
    object.checked = value;
  }
  else
  {
    if(value == undefined)
      object.value = '';
    else
      object.value = value;
  }
}

function setInputValue(inputName, value, formName, myDocument, enforce)
{
  // if set value in html template
  if(g_sHTMLTemplate && g_sHTMLTemplate != "")
  {
    // update value tag
    updateInputObjectTag(inputName, 'value', value);
  }
  else
  {
    var pObject = getFormObject(inputName, formName, myDocument, enforce);
    if ( typeof(pObject) !== 'undefined' )
    {
       setObjectValue( pObject, value );
    }
    else if ( typeof(jQuery) !== 'undefined' )
    {
       jQuery( 'form[name="' + formName + '"] input[name="' + inputName + '"]').val( value );
    }
  }
}

function setDOMInputValue( sObjectID, sValue, pDocument )
{
  setObjectValue( getDOMObject( sObjectID, pDocument ), sValue );
}
//All words first lettre toUpper 
function capitalizeObject(obj) {
    var sVal = obj.value;
    var sNewVal = '';
    sVal = sVal.split(' ');
    for(var c=0; c < sVal.length; c++) {
        sNewVal += sVal[c].substring(0,1).toUpperCase() +
                   sVal[c].substring(1, sVal[c].length );
        if( c < sVal.length - 1 )
            sNewVal += ' ';
    }
    obj.value = sNewVal;
}

function formatText(inputName, pObject, formName, nFormat, myDocument )
{
    if( !pObject && inputName )
        pObject = getFormObject( inputName, formName, myDocument )
        
    if( pObject )
    {
        var sVal = pObject.value;
        if(nFormat == TEXT_TO_UPPER)
        {
           pObject.value =  sVal.toUpperCase();
        }
        else if(nFormat == TEXT_TO_LOWER)
        {
            pObject.value =  sVal.toLowerCase();
        }
        else if(nFormat == TEXT_TO_CAPITALIZE)
        {
            capitalizeObject( pObject );
        }
        else if( nFormat == TEXT_TO_UPPER_ONLY_WORD )
        {
            pObject.value = new String( sVal.toUpperCase() ).replace( /\W/ig, ' ' );
        }
    }
}

function updateInputObjectNoValueTag(sName, sTag, sValue)
{
    // Ancienne fonction

  // remove it
  var re = getRegExp('<!--OBJ_' + sName + '--><(.*?)' + sTag + '(.*?)>(.*)<!--END_OBJ_' + sName + '-->', 'm');
  g_sHTMLTemplate = g_sHTMLTemplate.replace(re, '<!--OBJ_' + sName + '--><$1 $2>$3<!--END_OBJ_' + sName + '-->');
  if(sValue)
  {
    re = getRegExp('<!--OBJ_' + sName + '--><(.*?)>(.*)<!--END_OBJ_' + sName + '-->', 'm');
    g_sHTMLTemplate = g_sHTMLTemplate.replace(re, '<!--OBJ_' + sName + '--><$1 ' + sTag + '>$2<!--END_OBJ_' + sName + '-->');
  }

/*
     // Nouvelle
  var re = getRegExp('<!--OBJ_' + sName + '--><(.*?)(?:' + sTag + ')?(.*?)>(.*)<!--END_OBJ_' + sName + '-->', 'm');
  g_sHTMLTemplate = g_sHTMLTemplate.replace(re, '<!--OBJ_' + sName + '--><$1 ' + ( sValue ? sTag : '' ) + ' $2>$3<!--END_OBJ_' + sName + '-->');
*/
}

function updateInputObjectTag(sName, sTag, sValue)
{
  sValue = htmlAttributeQuote(sValue);
  // replace $ by $$
  sValue = sValue.replace( /\$/g, '$$$$' );
  var re = getRegExp('<!--OBJ_' + sName + '-->(.*?)' + sTag + '="(.*?)"(.*?)<!--END_OBJ_' + sName + '-->', 'm');
  if(re.test(g_sHTMLTemplate))
  {
    var sNewTag = '<!--OBJ_' + sName + '-->$1'+sTag+'='+sValue+'$3<!--END_OBJ_' + sName + '-->';
    g_sHTMLTemplate = g_sHTMLTemplate.replace(re, sNewTag);
  }
  else
  {
    re = getRegExp('<!--OBJ_' + sName + '--><(.*?)>(.*?)<!--END_OBJ_' + sName + '-->', 'm');
    g_sHTMLTemplate = g_sHTMLTemplate.replace(re, '<!--OBJ_' + sName + '--><$1 '+sTag+'='+sValue+'>$2<!--END_OBJ_' + sName + '-->');
  }
}

function updateInputObjectStyleTag(sName, sTag, sValue)
{
  var re = getRegExp('<!--OBJ_' + sName + '-->([^>]*?)style="([^>]*?)"(.*?)<!--END_OBJ_' + sName + '-->', 'm');
  if(re.test(g_sHTMLTemplate))
  {
    var reExists = getRegExp('<!--OBJ_' + sName + '-->([^>]*?)style="([^>]*?)'+sTag+':(.*?);(.*?)"(.*?)<!--END_OBJ_' + sName + '-->', 'm');
    if(reExists.test(g_sHTMLTemplate))
      g_sHTMLTemplate = g_sHTMLTemplate.replace(reExists, '<!--OBJ_' + sName + '-->$1style="$2'+sTag+':'+sValue+';$4"$5<!--END_OBJ_' + sName + '-->');
    else
      g_sHTMLTemplate = g_sHTMLTemplate.replace(re, '<!--OBJ_' + sName + '-->$1style="$2'+sTag+':'+sValue+';"$3<!--END_OBJ_' + sName + '-->');
  }
  else
  {
    //re = new RegExp('<!--OBJ_' + sName + '--><(.*?)>(.*?)<!--END_OBJ_' + sName + '-->', 'm');
    re = getRegExp('<!--OBJ_' + sName + '-->(?:\r\n|\n|\s)*<(.*?)>((?:\r\n|\n|.)*?)<!--END_OBJ_' + sName + '-->', 'm');
    g_sHTMLTemplate = g_sHTMLTemplate.replace(re, '<!--OBJ_' + sName + '--><$1 style="'+sTag+':'+sValue+';">$2<!--END_OBJ_' + sName + '-->');
  }
}

//
// met a jour le contenu HTML d'un champ input (textarea)
//
function updateInputObjectContent( sName, sContent )
{
  var pRegExp = getRegExp( '<!--OBJ_' + sName + '--><(.*?)>(.*)</(.*?)><!--END_OBJ_' + sName + '-->', 'm' );
  g_sHTMLTemplate = g_sHTMLTemplate.replace( pRegExp, '<!--OBJ_' + sName + '--><$1>' + sContent + '</$3><!--END_OBJ_' + sName + '-->' );
}

/*
 *  On demande le remplacement des tags HTML
 *     (Ne plus les afficher)
 *  Parameters :
 *    - sText : Chaine de caractère avec tags HTML
 *  Return :
 *    - sText : Chaine de caractère sans tags HTML
 */
function replaceHTMLTags( sText )
{
    //    \n
    sText = sText.replace(/\n/gi,'');
    //    <br>
    sText = sText.replace(/\<br\>/gi,"\n");    
    //    Tous les tags <>
    sText = sText.replace(/<.*?\>/gi,' ');
    //    &nbsp;
    sText = sText.replace(/&nbsp;/gi,' ');

    return sText;
}

/**
 * Append the value of a form object.
 * Parameters :
 *   - sSeparator : The used separator between old value and new one.
 *   - inputName : the short name of the layer (example : <INPUT NAME="toto">  => Name="Toto")
 *   - value : the new value
 *      . object is unique textfield/textarea : the new value of the textfield
 *      . object is unique checkbox or radio : TRUE to check, FALSE to uncheck
 *      . object is multiple radio : the value of the radio to check
 *      . object is unique select-one : the value of the option to select
 *      . object is unique select-multiple : array of values representing the options to select
 *      . other : not supported
 *   - formName (optional) : the name of the form which contains the input object
 *                 If the input object is not in a form, put formName = ''
 *   - myDocument (optional) : default value = window.document
 *                 Allows to specify a document object on another window
 *   - enforce (optional) : SHOULD NOT BE USED.
 *                 When an input object is not inside a form object, the input object must be named with the ID tag
 *                 instead of the NAME tag. If not, the object will not be accessible by Netscape browsers.
 *                 Setting enforce value to TRUE removes the Internet Explorer warning message.
 *   - bHTMLTagsReplace : Replace / destroy all HTML tags
 * Returns :
 */
function appendInputValue(sSeparator,inputName, value, formName, myDocument, enforce, bHTMLTagsReplace)
{
	var sOldValue = getInputValue(inputName,formName,myDocument,enforce);
	sOldValue = sOldValue + ( sOldValue != '' ? sSeparator : '' ) + value;
        
        // Faut il supprimer les tags HTML de la chaine
        if( bHTMLTagsReplace )
        {
            sOldValue = replaceHTMLTags( sOldValue );
        }
        
	setInputValue(inputName, sOldValue, formName, myDocument, enforce); 
}

/**
 * Set an input object disabled.
 * Parameters :
 *   - inputName : the short name of the layer (example : <INPUT NAME="toto">  => Name="Toto")
 *   - formName (optional) : the name of the form which contains the input object
 *                 If the input object is not in a form, put formName = ''
 *   - myDocument (optional) : default value = window.document
 *                 Allows to specify a document object on another window
 *   - enforce (optional) : SHOULD NOT BE USED.
 *                 When an input object is not inside a form object, the input object must be named with the ID tag
 *                 instead of the NAME tag. If not, the object will not be accessible by Netscape browsers.
 *                 Setting enforce value to TRUE removes the Internet Explorer warning message.
 * Returns :
 */
function disableInput(inputName, formName, myDocument, enforce) {
  var object = getFormObject(inputName, formName, myDocument, enforce);
  if( object.disabled != null )
  {
    object.disabled = true;
  }
  if( object.length != null )
  {
    for( var i = 0 ; i < object.length ; i++ )
    {
      if( object[i].disabled != null )
      {
        object[i].disabled = true;
      }
    }
  }
}

/**
 * Enable an input object.
 * Parameters :
 *   - inputName : the short name of the layer (example : <INPUT NAME="toto">  => Name="Toto")
 *   - formName (optional) : the name of the form which contains the input object
 *                 If the input object is not in a form, put formName = ''
 *   - myDocument (optional) : default value = window.document
 *                 Allows to specify a document object on another window
 *   - enforce (optional) : SHOULD NOT BE USED.
 *                 When an input object is not inside a form object, the input object must be named with the ID tag
 *                 instead of the NAME tag. If not, the object will not be accessible by Netscape browsers.
 *                 Setting enforce value to TRUE removes the Internet Explorer warning message.
 * Returns :
 */
function enableInput(inputName, formName, myDocument, enforce) {
  var object = getFormObject(inputName, formName, myDocument, enforce);
  if( object.disabled != null )
  {
    object.disabled = false;
  }
  if( object.length != null )
  {
    for( var i = 0 ; i < object.length ; i++ )
    {
      if( object[i].disabled != null )
      {
        object[i].disabled = false;
      }
    }
  }
}

/**
 * Get if an input object is disabled or enabled
 * Parameters :
 *   - inputName : the short name of the layer (example : <INPUT NAME="toto">  => Name="Toto")
 *   - formName (optional) : the name of the form which contains the input object
 *                 If the input object is not in a form, put formName = ''
 *   - myDocument (optional) : default value = window.document
 *                 Allows to specify a document object on another window
 *   - enforce (optional) : SHOULD NOT BE USED.
 *                 When an input object is not inside a form object, the input object must be named with the ID tag
 *                 instead of the NAME tag. If not, the object will not be accessible by Netscape browsers.
 *                 Setting enforce value to TRUE removes the Internet Explorer warning message.
 * Returns :
 *    - true : object is enabled
 *    - false : object is disabled
 */
function getInputEnabled(inputName, formName, myDocument, enforce) {
    var object = getFormObject(inputName, formName, myDocument, enforce);
    return !object.disable;
}


/**
 * Submit a form
 * Parameters :
 *   - formName : the name of the form to submit
 *   - action (optional) : to submit the form to a specific URL
 *   - myDocument (optional) : default value = window.document
 *                 Allows to specify a document object on another window
 * Returns : false
 */
function submitForm(formName, action, myDocument, sAnchor )
{
  var browser = getBrowser();
  if(myDocument == null || myDocument == '') myDocument = window.document;

  var object = eval("myDocument." + formName);
  if( object == null )
    throw new Error("Cannot found form '"+formName+"' in document");

  if (action != null && action != '')
  {
    object.action = action;
  }
  if( sAnchor && sAnchor != '' )
  {
    object.action += "#" + sAnchor;
  }

  object.submit();
}

function submitDisplayFormIn( sLink, sNewFormAction, sNewTarget, sNewDisplay )
{
    if( sLink.match( /submitDisplayForm\((.*), (.*), (.*), (.*), (.*), (.*), (.*), (.*), (.*), (.*)\)/ ) )
    {
        var sFormName      = RegExp.$1;
        var sDisplay       = RegExp.$2;
        var sActions       = RegExp.$3;
        var sTokens        = RegExp.$4;
        var sCheckFunction = RegExp.$5;
        var pDocument      = RegExp.$6;
        var sAnchor        = RegExp.$7;
        var sFormAction    = RegExp.$8;
        var sLinkID        = RegExp.$9;
        var sTarget        = RegExp.$10;
        
        sNewFormAction = sNewFormAction ? "'"+sNewFormAction+"'" : sFormAction;
        sNewTarget     = sNewTarget     ? "'"+sNewTarget+"'"     : sTarget;
	sNewDisplay    = sNewDisplay    ? "'"+sNewDisplay+"'"	 : sDisplay;

        var sNewCall = "submitDisplayForm( "+sFormName+", "+sNewDisplay+", "+sActions+", "+sTokens+", "+sCheckFunction+", "+pDocument+", "+sAnchor+", "+sNewFormAction+", "+sLinkID+", "+sNewTarget+")";
        eval( sNewCall );
    }
}

function submitDisplayForm( sFormName, sDisplay, sActions, sTokens, sCheckFunction, pDocument, sAnchor, sFormAction, sLinkID, sTarget )
{
  var bRet = true;
  if(sDisplay != undefined && sDisplay !== null)
    setInputValue('display', sDisplay, sFormName, pDocument);
  if(sActions != undefined && sActions !== null)
    setInputValue('actions', sActions, sFormName, pDocument);
  if(sTokens != undefined && sTokens !== null)
    setInputValue('tokens', sTokens, sFormName, pDocument);
  if(sTarget != undefined && sTarget !== null ) // Change le target du formulaire
  {
    var pForm = getForm(sFormName, pDocument);
    if(pForm && pForm != undefined && sTarget !== null)
    {
        pForm.target = sTarget;
    }
  }
    
  if( !pDocument && sCheckFunction != null && sCheckFunction != '' )
  {
    // on ne plante pas si la fonction n'existe pas
    var bDefined = false;
    try
    {
      bDefined = eval( sCheckFunction ) != '';
    }
    catch (ex) {}
    if( bDefined )
    {
      try
      {
        bRet = eval( sCheckFunction+"( '"+sFormName+"' );" )
      }
      catch (ex)
      {
        bRet = false;
      }
    }
  }
  if( bRet )
  {
    // faudrait peut-etre un try catch pour rétablir l'affichage si le submitForm echoue
    // mais on risque de perdre l'exception
    try
    {
      if( getDOMObject( 'please_wait_layer', pDocument ) )
      {
        hideLayer( 'content_layer', pDocument );
        showLayer( 'please_wait_layer', pDocument );
      }
      // vérification que l'utilisateur ne clique pas deux fois sur le bouton
      if( sLinkID )
      {
        var pLink = getDOMObject( sLinkID );
        if( pLink && pLink instanceof Array )
        {
          for(var i=0;i<pLink.length;i++)
            pLink.style.visibility = 'hidden';
        }
        else if(pLink)
        {
          pLink.style.visibility = 'hidden';
        }
      }
      // valide le formulaire
      submitForm( sFormName, sFormAction, pDocument, sAnchor );
    }
    catch( ex )
    {
      if( getDOMObject( 'please_wait_layer' ) )
      {
        showLayer( 'content_layer' );
        hideLayer( 'please_wait_layer' );
      }
      throw ex;
    }
  }
}



/**
 * Reset a form
 * Parameters :
 *   - formName : the name of the form to reset
 *   - myDocument (optional) : default value = window.document
 *                 Allows to specify a document object on another window
 * Returns :
 */
function resetForm(formName, action, myDocument) {
    var browser = getBrowser();
    if(myDocument == null || myDocument == '') myDocument = window.document;

    var object;
    switch(browser) {
    case KONQUEROR :
    case CHROME :
    case OPERA :
    case NETSCAPE :
    case IE :
        object = eval("myDocument." + formName);
        break;
    }

    object.reset();
    //return object;
}

/**
 * Submit a form
 * Parameters :
 *   - inputValue : the value of the input to be posted ( 'go', 'update', ... )
 *   - formName : the name of the form to reset
 *   - myDocument (optional) : default value = window.document
 *                 Allows to specify a document object on another window
 * Returns :
 */
function submitActionForm( actionName, formName, myDocument)
{
  var browser = getBrowser();
  if(myDocument == null || myDocument == '') myDocument = window.document;

  var object = eval("myDocument." + formName);
  if( object == null )
    throw new Error("Cannot found form '"+formName+"' in document");

  setInputValue( 'formAction', actionName, formName, myDocument );

  if( !validateForm( formName, actionName ) )
  {
    return;
  }

  if(object)
  {
    for( var i=0 ; i<object.elements.length ; i++ )
    {
      object.elements[ i ].disabled = false;
    }
  }

  showPleaseWait();

  if(object.onsubmit)
    object.onsubmit();
  object.submit();
}

function submitSortbarName( sortbarName, formName, myDocument)
{
  var browser = getBrowser();
  if(myDocument == null || myDocument == '') myDocument = window.document;

  var object = eval("myDocument." + formName);
  if( object == null )
    throw new Error("Cannot found form '"+formName+"' in document");

  setInputValue( 'selected_sortbar_name', sortbarName, formName, myDocument );
  setInputValue( 'formAction', 'GO_ITEMS', formName, myDocument );

  if( !validateForm( formName, sortbarName ) )
  {
    return;
  }

  if(object)
  {
    for( var i=0 ; i<object.elements.length ; i++ )
    {
      object.elements[ i ].disabled = false;
    }
  }

  showPleaseWait();

  if(object.onsubmit)
    object.onsubmit();
  object.submit();
}

/**
 * Simulate a click on the specified button
 * WARNING : the click() function can only be called on a BUTTON or on a LINK
 *           DO NOT TRY to call it on a <input type="image" ...>, it does NOT work on Netscape/Mozilla/Konqueror
 * Parameters :
 *   - buttonName : the short name of the button (example : <BUTTON ID="toto">  => Name="Toto")
 *   - formName (optional) : the name of the form which contains the object
 *                 If the button is not in a form, put formName = ''
 *   - myDocument (optional) : default value = window.document
 *                 Allows to specify a document object on another window
 *   - enforce (optional) : SHOULD NOT BE USED.
 *                 When an input object is not inside a form object, the input object must be named with the ID tag
 *                 instead of the NAME tag. If not, the object will not be accessible by Netscape browsers.
 *                 Setting enforce value to TRUE removes the Internet Explorer warning message.
 * Returns :
 *    the value returned by [button].click()
 */
function clickButton(buttonName, myDocument) {
    var object = getFormObject(buttonName, formName, myDocument, enforce);
    return object.click();
}



/**
 * Get a form
 * Parameters :
 *   - formName : the name of the form which contains the object
 *                If the button is not in a form, put formName = ''
 *   - myDocument (optional) : default value = window.document
 *                 Allows to specify a document object on another window
 * Returns :
 *    the form object
 */
function getForm(formName, myDocument) {
    var browser = getBrowser();
    if(myDocument == null || myDocument == '') myDocument = window.document;

    var object;
    switch(browser) {
    case KONQUEROR :
    case NETSCAPE :
    case CHROME :
    case OPERA :
    case IE :
        object = eval( "myDocument." + formName);
        break;
    }

    return object;
}

/**
 * Get the action of a form
 * Parameters :
 *   - formName : the name of the form which contains the object
 *                If the button is not in a form, put formName = ''
 *   - myDocument (optional) : default value = window.document
 *                 Allows to specify a document object on another window
 * Returns :
 *    the form object
 */
function getFormAction(formName, myDocument) {
    var object = getForm(formName, myDocument);
    return object.action;
}




function printCurrentWindow() {
    if(window.print) {
        window.print();
    }
    else {
        window.alert("Your browser does not support this functionnality. To print this document, try to click with the right button on the page and select \"Print\".");
    }
}



var helpLayer;

function mouse_move(e)
{
   if (!loaded)
   {
      return;
   }

   if (!helpLayer)
   {
       helpLayer = getLayer(HELP_LAYER_NAME);
   }

   var x;
   var y;
   var maxX;
   var width = helpLayer.style.width;
   if (!width)
   {
      width = 250;
   }

   switch(browser) {
      case IE :
      case OPERA :
      case CHROME :
         x = event.x + document.body.scrollLeft - 45;
         y = event.y + document.body.scrollTop + 20;
         maxX = document.body.clientWidth;
         break;
      case KONQUEROR :
         x = event.x - 45;
         y = event.y + 20;
         maxX = document.body.clientWidth;
         break;
      case NETSCAPE :
         x = e.pageX - 45;
         y = e.pageY + 20;
         maxX = window.innerWidth;
   }

   if (x + width > maxX) { x = maxX - width; }
   if (x < 0) { x = 0; }

   helpLayer.style.left = x;
   helpLayer.style.top = y;

   return true;
}

function setQuickHelpBGColor(bgcolor)
{
   HELP_BGCOLOR = bgcolor;
}

function displayQuickHelp(msg, width) 
{
   if (!loaded)
   {
      return;
   }

   if (!width)
   {
      width = 200;
   }

   var content="<TABLE BORDER=\"0\" WIDTH=\"" + width + "\" CELLPADDING=\"1\" CELLSPACING=\"0\" BGCOLOR=\"#000000\">" +
               "  <tr><td><TABLE WIDTH=\"100%\" BORDER=\"0\" CELLPADDING=\"3\" CELLSPACING=\"0\"> "+
               "  <tr><TD BGCOLOR=\"" + HELP_BGCOLOR + "\" style=\"font-size:10px\">" + msg + "</TD></TR></TABLE></TD></TR></TABLE>";
   
   var zeLayer = getLayer(HELP_LAYER_NAME);
   setInnerHTML( zeLayer, content );
   showLayer(HELP_LAYER_NAME);
}

function hideQuickHelp()
{
   if (!loaded)
   {
      return;
   }
   hideLayer(HELP_LAYER_NAME);
   var zeLayer = getLayer(HELP_LAYER_NAME);
   setInnerHTML( zeLayer, "");
}

var openedWindows = new Array();

/**
 * Open a popup window.
 */
function popup(path,name,props)
{
  openedWindows[ openedWindows.length ] = window.open(path,name,props);

  //return openedWindows[ openedWindows.length - 1 ];
}

function getModalAttributes(props)
{
    props = props.replace(/width=(\d+)/,'dialogWidth:$1px');
    props = props.replace(/height=(\d+)/,'dialogHeight:$1px');
    props = props.replace(/\,/g,';');
    props = props.replace(/\=/g,':');
    return props;
}

function modalNoReturn(path,name,props, aNamedArgs)
{
    modal(path,name,props, aNamedArgs);
    return;
}

function modal(path,name,props, aNamedArgs)
{
  aNamedArgs = aNamedArgs ? aNamedArgs : [];
  if( window.showModalDialog )
  {
    var aArgs = [];
    aArgs[0] = name;
    aArgs[1] = window;
    aArgs[2] = aNamedArgs;
    if( getBrowser() === IE )
    {
      return window.showModalDialog('dblframe.cgi?url='+encodeURIComponent(path),aArgs,getModalAttributes(props));
    } 
    else
    {
      return window.showModalDialog( path, aArgs, getModalAttributes(props) );
    }
  }
  else
  {
    var pPopup = popup(path,name, props);
    return null;
  }
}

function modalNoReturn(path,name,props, aNamedArgs)
{
    modal(path,name,props, aNamedArgs);
    return;
}

function alternativeModal( path, name, props, aNamedArgs)
{
  aNamedArgs = aNamedArgs ? aNamedArgs : new Array();
  if(window.showModalDialog)
  {
    var aArgs = new Array();
    aArgs[0] = name;
    aArgs[1] = window;
    aArgs[2] = aNamedArgs;
    if(getBrowser() == IE)
	return window.showModalDialog('dblframe.cgi?url='+encodeURIComponent(path),aArgs,getModalAttributes(props));
    else
	return window.showModalDialog(path,aArgs,props);
  }
  else
  {
    var pPopup = popup(path,name, props);
    return null;
  }
}

function getModalOpenerWindow(pWindow)
{
    pWindow = pWindow ? pWindow : window;
    if(pWindow.dialogArguments)
	return pWindow.dialogArguments[1];
    return null;
}

function getBaseModalOpenerWindow(pWindow)
{
    pWindow = pWindow ? pWindow : window;
    var pOpener = getModalOpenerWindow(pWindow);
    if(pOpener && getModalOpenerWindow(pOpener) != null)
	return getBaseModalOpenerWindow(pOpener);
    return pOpener;
}

function getModalNamedArg(sArgName, pWindow)
{
   pWindow = pWindow ? pWindow : window;
   if(pWindow.dialogArguments)
	return pWindow.dialogArguments[2][sArgName];
}

function setModalReturnValue(sValue)
{
    window.returnValue = sValue;
}

function closeAllOpenedWindows()
{
  for( var i = 0 ; i < openedWindows.length ; i++ )
  {
    if( !openedWindows[i].closed )
    {
      if( openedWindows[i].closeAllOpenedWindows )
      {
        openedWindows[i].closeAllOpenedWindows();
      }

      eval( 'openedWindows[i].close()' );
    }
  }
}

//*******************************************************************
//*                    MENU FUNCTIONS                               *
//* Some browser specific functions or variable to display the menu *
//*******************************************************************
var thresholdY = 15;		// in pixels; threshold for vertical repositioning of a layer
var ordinata_margin = -10;	// to start the layer a bit above the mouse vertical coordinate
var currentY = -1;

if(document.all) {
   window.onresize = hf_resizeWindow;
}
function hf_resizeWindow() {
   if( document.all && document.body && document.body.clientHeight && document.all('hf_template_data') ) {
      document.all('hf_template_data').style.height = parseInt(document.body.clientHeight) - 138;
   }
   return true;
}

/**
 * Capture the mouse movements
 */
function captureMouseEvents() {
    var browser = getBrowser();
    switch(browser) {
    case NETSCAPE :
       //if (!document.getElementsByClassName)
    	   document.captureEvents(Event.MOUSEDOWN | Event.MOUSEMOVE);
       /*else
       {
    	   document.addEventListener("MouseDown", function() {}, true);
    	   document.addEventListener("MouseMove", function() {}, true);
       }*/
       break;
    }
}

/**
 * Used to get menu vertical position
 */
function grabMouse(e) {
   var browser = getBrowser();
   switch(browser) {
   case NETSCAPE :
      currentY = e.pageY;
      break;
   case OPERA :
   case CHROME :
   case IE :
   case KONQUEROR :
      currentY = event.y + document.body.scrollTop;
      break;
   }
}


/**
 * Move a menu layer to its location
 */
function moveLayerY(menuName, level, obj) 
{
  var browser = getBrowser();
  if(loaded)
  { // to avoid stupid errors of Microsoft browsers
    if( obj )
    {
      if( browser == NETSCAPE) 
      {
        if (level == 3) 
        {
          document.getElementById(menuName).style.left = getx(obj+'_right_position', level);
          document.getElementById(menuName).style.top = gety(obj);
        }
        else
        {
          document.getElementById(menuName).style.left = getx(obj, level);
        }
      }
      else
      {
        if (level == 3) 
		    {
  				document.all[menuName].style.pixelTop = gety(obj)+2;
  				document.all[menuName].style.pixelLeft = getx(obj+'_right_position', level);
  			}
  			else
  			{
  				document.all[menuName].style.pixelLeft = getx(obj, level);
  			}
      }
    }
  }
}


function setOnClickFunction(fonction) {
    var browser = getBrowser();
    switch(browser) {
    case NETSCAPE:
    case OPERA :
    case CHROME :
    case KONQUEROR:
    case IE:
        document.onclick = fonction;
        break;
    }
}



function getElementsToHide() {
    var browser = getBrowser();
    if(browser == NETSCAPE || browser == OPERA || browser == IE7 || browser == CHROME)
        return new Array();

    if(browser == IE) {
        return document.all.tags("SELECT");
    }

    if(browser == KONQUEROR) {
        var res = new Array();
        var cpt = 0;
        var formsArray = document.forms;
        for (var i = 0; i < formsArray.length; i++) {
            var elementsArray = formsArray[i].elements;
            for(var j = 0; j < elementsArray.length; j++) {
                var elem = elementsArray[j];
                if(elem.type != 'hidden')
                    res[cpt++] = elem;
            }
        }
        return res;
    }

    return new Array();
}

function getElementsToShow() {
    return getElementsToHide();
}


function getx( obj, level )
{
  var x = 0;
  var elt = getLayer(obj);
 
  if (!elt)
	  return 0;
  if (level == 2)
  {
	  while (elt.tagName != "BODY")
	  {
		  x += elt.offsetLeft;
		  elt = elt.parentNode;
	  }
	  return x;
  }
  else
  {
	  switch (browser)
    {
      case NETSCAPE:
     //     return elt.pageX;
      case IE:
      case OPERA :
      case CHROME :
      case KONQUEROR:
        x =  elt.offsetLeft + 4;
      do
      {
        x += parseInt( elt.offsetLeft );
        elt = elt.offsetParent;
      } while ( elt );
		  return x;
	  }
  }
}

function gety(obj, level)
{
	var elt = getLayer(obj);
	var y = -7;
	if (!elt) {
		return 0;
	}
	switch (browser) {
	case NETSCAPE:
 //   	return elt.y;
    case OPERA :
    case CHROME :
    case KONQUEROR:
	case IE:
		do { y += parseInt( elt.offsetTop );
		elt = elt.offsetParent;
		} while ( elt );
		return y;
	}
}


function sprintf()
{
  if (!arguments || arguments.length < 1 || !RegExp)
    {
      return;
    }
  var str = arguments[0];
  var re = /([^%]*)%('.|0|\x20)?(-)?(\d+)?(\.\d+)?(%|b|c|d|u|f|o|s|x|X)(.*)/;
  var a = b = [], numSubstitutions = 0, numMatches = 0;
  while (a = re.exec(str))
    {
      var leftpart = a[1], pPad = a[2], pJustify = a[3], pMinLength = a[4];
      var pPrecision = a[5], pType = a[6], rightPart = a[7];
      
      //alert(a + '\n' + [a[0], leftpart, pPad, pJustify, pMinLength, pPrecision);
      
      numMatches++;
      if (pType == '%')
        {
          subst = '%';
        }
      else
        {
          numSubstitutions++;
          if (numSubstitutions >= arguments.length)
            {
              alert('Error! Not enough function arguments (' + (arguments.length - 1) + ', excluding the string)\nfor the number of substitution parameters in string (' + numSubstitutions + ' so far).');
            }
          var param = arguments[numSubstitutions];
          var pad = '';
          if (pPad && pPad.substr(0,1) == "'") pad = leftpart.substr(1,1);
          else if (pPad) pad = pPad;
          var justifyRight = true;
          if (pJustify && pJustify === "-") justifyRight = false;
          var minLength = -1;
          if (pMinLength) minLength = parseInt(pMinLength);
          var precision = -1;
          if (pPrecision && pType == 'f') precision = parseInt(pPrecision.substring(1));
          var subst = param;
          if (pType == 'b') subst = parseInt(param).toString(2);
          else if (pType == 'c') subst = String.fromCharCode(parseInt(param));
          else if (pType == 'd') subst = parseInt(param) ? parseInt(param) : 0;
          else if (pType == 'u') subst = Math.abs(param);
          else if (pType == 'f') subst = (precision > -1) ? Math.round(parseFloat(param) * Math.pow(10, precision)) / Math.pow(10, precision): parseFloat(param);
          else if (pType == 'o') subst = parseInt(param).toString(8);
          else if (pType == 's') subst = param;
          else if (pType == 'x') subst = ('' + parseInt(param).toString(16)).toLowerCase();
          else if (pType == 'X') subst = ('' + parseInt(param).toString(16)).toUpperCase();
        }
      str = leftpart + subst + rightPart;
    }
  return str;
}

function jsQuote( sVar )
{
  if(sVar != null )
  {
	  sVar = new String(sVar);
	  sVar = sVar.replace( /\"/g, '\\"' );
	  sVar = sVar.replace( /\n/g, '\\n' );
    return ('"' + sVar + '"');
  }
  else
  {
    return '\'\'';
  }
}
/**
 * Supprime les espaces inutiles en début et fin de la chaîne passée en paramètre.
 */
function trim(aString) {
    return aString.replace(/^\s+/, "").replace(/\s+$/, "");
}
 
/**
 * Supprime les espaces inutiles en début de la chaîne passée en paramètre.
 */
function ltrim(aString) {
    return aString.replace(/^\s+/, "");
}
 
/**
 * Supprime les espaces inutiles en fin de la chaîne passée en paramètre.
 */
function rtrim(aString) {
    return aString.replace(/\s+$/, "");
} 

function htmlAttributeQuote(sValue)
{
  if(sValue != null )
  {
    sValue = new String(sValue);
    sValue = sValue.replace( /\"/g, '&#34;' );
    sValue = sValue.replace( /&/g, '&#38;' );
    //LMA: I hope it breaks nothing, and it's also 
    //not allowed in html specs to have < or > in an attribute value.
    sValue = sValue.replace( /</g, '&lt;' );
    sValue = sValue.replace( />/g, '&gt;' );
    return "\""+sValue+"\"";
  }
  else
  {
    return "\"\"";
  }
}


function evalFunc()
{
  var args = evalFunc.arguments;
  if(evalFunc.arguments < 1)
    return null;
  // function name
  var sFuncName = args[0];
  // arguments
  var aTmp = new Array();
  for( var i=1 ; i<args.length ; i++ )
    aTmp[aTmp.length] = 'args['+i+']';
  var sArgs = aTmp.join(',');
  var sRet = eval( sFuncName + '(' + sArgs + ')' );
  return sRet;
}

function switchLayer( sLayerName, bBugFix )
{
  if( getLayerDisplayed( sLayerName ) )
  {
    hideLayer( sLayerName, null, bBugFix );
  }
  else
  {
    showLayer( sLayerName, null, bBugFix );
  }
}

function startPleaseWait()
{
  hideLayer( 'global_layer' );
  showLayer( 'please_wait_layer' );
}

function  stopPleaseWait()
{
  hideLayer( 'please_wait_layer' );
  showLayer( 'global_layer' );
}

function cancelRequest()
{
  stopPleaseWait();
  if(navigator.appName == "Microsoft Internet Explorer")
  {
    window.document.execCommand('Stop');
  }
  else
  {
    window.stop();
  }
}

function copyArray( src, dest )
{
  for( i in src )
  {
    dest[i] = src[i];
  }

  return dest;
}

function mapArray(aArray, pFunction)
{
  ////if (typeof pFunction != "function") throw new TypeError();
  var aResult = new Array();
  for (var i in aArray)
  {
    aResult.push(pFunction.call(aArray, aArray[i]));
  }
  return aResult;
}

function getRecParentDocument( frameName, parentWindow )
{
  if( parentWindow == null )
  {
    parentWindow = window;
  }
  if( frameName == null )
  {
    return parentWindow;
  }
  if( parentWindow.parent[frameName] != null )
  {
    return parentWindow.parent[frameName];
  }
  else
  {
    if( parentWindow.opener != null )
    {
      return getParentDocument( frameName, parentWindow.opener );
    }
    else if(parentWindow.parent != null)
    {
      return getParentDocument( frameName, parentWindow.parent );
    }
    else
    {
      return parentWindow;
    }
  }
}

function getParentDocument( frameName, parentWindow )
{
  if( parentWindow == null )
  {
    parentWindow = window;
  }
  if( frameName == null )
  {
    return parentWindow;
  }
  if( parentWindow.parent[frameName] != null )
  {
    return parentWindow.parent[frameName];
  }
  else
  {
    return parentWindow;
  }
}

function findParentDocument(sName, pWindow)
{
    var pWin = findParentWindow(sName, pWindow);
    return pWin ? pWin.document : null;
}

function findParentWindow(sName, pWindow)
{
    if(pWindow.name == sName)
        return pWindow;
    if(getModalOpenerWindow(pWindow) )
        return findParentWindow(sName, getModalOpenerWindow(pWindow));
    if(pWindow.opener && pWindow.opener.name != pWindow.name)
        return findParentWindow(sName, pWindow.opener);
    if(pWindow.parent && pWindow.parent.name != pWindow.name)
        return findParentWindow(sName, pWindow.parent);

    //Try to find the window.opener from dialogArguments if it is a modal window
    if(    getModalOpenerWindow(pWindow)
        && getModalOpenerWindow(pWindow).name != pWindow.name )
	return findParentWindow( sName, getModalOpenerWindow(pWindow) );

    return null;
}

function createSelectOption(sID, sText, pDocument)
{
  pDocument = pDocument ? pDocument : window.document;
  if( pDocument.parentWindow )
    return new pDocument.parentWindow.Option( sText, sID );
  else
    return new Option( sText, sID );
}

function cancelBackAndRefresh( event )
{
  if( event == null )
  {
    return;
  }

  if( event.keyCode == 116 )
  {
    // F5
    //alert( 'The F5 key has been disabled' );
    cancelKeyEvent( event );
  }

  if( event.ctrlKey && (event.keyCode == 78 || event.keyCode == 82) )
  {
    // When ctrl is pressed with R or N
    cancelKeyEvent( event );
  }
//   if( event.keyCode > 17 )
//     {
//       alert( 'event.ctrlKey='+event.ctrlKey+' event.keyCode=' + event.keyCode );
//     }

  if (event.keyCode == 8 && (event.srcElement && event.srcElement.type != "text" && event.srcElement.type != "textarea" && event.srcElement.type != "password" && !event.srcElement.isContentEditable))
  {
    // When backspace is pressed but not in form element
    cancelKeyEvent(event);
  }
}

function cancelKeyEvent( event )
{
  //alert( event.preventDefault );
  if( event.preventDefault )
  {
    event.preventDefault();
    return false;
  }
  else
  {
    event.keyCode = 0;
    event.returnValue = false;
  }
}

if(getBrowser() == NETSCAPE )
{
  /*if (!document.getElementsByClassName)
  {*/
	  document.captureEvents( "KeyPress" );
	  document.captureEvents( "KeyDown" );
  //}
  document.addEventListener( "KeyPress", cancelBackAndRefresh, true );
  document.addEventListener( "KeyDown", cancelBackAndRefresh, true );
}

document.onkeydown = cancelBackAndRefresh;

//history.forward();

//alert( 'OK' );

function showPleaseWait()
{
  hideLayer( 'global_layer' );

  showLayer( 'please_wait_layer' );
}

function move( inputName, formName, offset )
{
  var obj = getFormObject( inputName, formName );

  if( obj.options == null )
  {
    return;
  }

  var minPos = 0;
  var maxPos = obj.options.length - 1;
  var oldPos = obj.options.selectedIndex;
  var newPos = oldPos + offset;
  if( newPos < minPos )
  {
    newPos = minPos;
  }
  if( newPos > maxPos )
  {
    newPos = maxPos;
  }
  if( newPos == oldPos )
  {
    return;
  }

  //  alert( 'oldPos='+oldPos +' newPos='+newPos );
  var option = new Option( obj.options[ oldPos ].text, obj.options[ oldPos ].value );
  if( newPos < oldPos )
  {
    for( var i = oldPos ; i > newPos ; i-- )
    {
      //      alert( obj.options[ i ].text + ' ' + obj.options[ i - 1 ].text );
      obj.options[ i ] = new Option( obj.options[ i - 1 ].text, obj.options[ i - 1 ].value );
      //      alert( obj.options[ i ].text + ' ' + obj.options[ i - 1 ].text );
    }
  }
  else
  {
    for( var i = oldPos ; i < newPos ; i++ )
    {
      //      alert( obj.options[ i ].text + ' ' + obj.options[ i + 1 ].text );
      obj.options[ i ] = new Option( obj.options[ i + 1 ].text, obj.options[ i + 1 ].value );
      //      alert( obj.options[ i ].text + ' ' + obj.options[ i + 1 ].text );
    }
  }
  obj.options[ newPos ] = option;
  obj.options.selectedIndex = newPos;
}

function selectAllOptions( inputName, formName )
{
  var obj = getFormObject( inputName, formName );

  if( obj.options == null )
  {
    return;
  }

  for( var i = 0 ; i < obj.options.length ; i++ )
  {
    obj.options[i].selected = true;
  }
}

function emptyAllOptions( inputName, formName )
{
  var obj = getFormObject( inputName, formName );

  if( obj.options == null )
  {
    return;
  }

  for( var i = (obj.options.length - 1) ; i >= 0 ; i-- )
  {
    obj.options[i] = null;
  }
}

function removeArrayElement(aArray, pElement)
{
	var index;
	for(index=0;index<aArray.length && aArray[index] != pElement;index++);
	if(index != aArray.length)
	{
		for(;index<aArray.length-1;index++)
			aArray[index]=aArray[index+1];
		delete aArray[aArray.length - 1];
		aArray.length = aArray.length - 1;
		return pElement;
	}
	return false;
}

function arrayContains(aArray, pElement)
{
  for(var index=0;index<aArray.length;index++)
    if(aArray[index] == pElement)
      return true;
}

function arrayPush(aDest, aSrc)
{
    for(var i=0;i<aSrc.length;i++)
        aDest.push(aSrc[i]);
    return aDest;
}

function cloneArray(aArray)
{
  if(aArray == null)
    return null;
  var aNewArray = new Array();
  for(var index=0;index<aArray.length;index++)
    aNewArray.push(aArray[index]);
  return aNewArray;
}

/**
 * goAction launch the global action selected in the listparam.
 * @param <String> sAction The name of the action (remote) to launch
 * @param <String> sFormName The name of the form to use to retrieve the datas used for the action
 * @param <Boolean> bGlobal true if the action is global, false otherwise
 * @param <String> sDocument The document URL (?) to use
 * @param <Boolean> bUseActionAsFormAction true if the action to use is a form action, and so sAction is the subaction
 * @param <Boolean> bDoNotAlertUser true if no alert should be displayed to the user at the end of the validation if no line as been selected
 * @param <Function> fCallBack optional Function to call before submitting the action, MUST return true for the action to proceed
 * @param <Function> fFailCallBack optional Function to call if the callback function didn't return true.
 * @return void
 */
function goAction( sAction, sFormName, bGlobal, sDocument, bUseActionAsFormAction, bDoNotAlertUser, fCallBack, fFailCallBack )
{
  if ( bGlobal )
  {
    enableAll( 'select', sFormName, 1 );
  }
  setInputValue( sAction, '1', sFormName, sDocument );
  // usual case
  if ( typeof(fCallBack) !== 'function' )
  {
    submitActionsForm( bUseActionAsFormAction ? sAction : 'update', sFormName, sDocument, bDoNotAlertUser);
  }
  else 
  {
    // with callback
    if ( fCallBack() )
    {
      submitActionsForm( bUseActionAsFormAction ? sAction : 'update', sFormName, sDocument, bDoNotAlertUser);     
    }
    // and optional fallback
    else if ( typeof(fFailCallBack) === 'function' ) 
    {
      fFailCallBack();
    }
  }
}

function toggleActionLayer( sAction, sLayerOn, sLayerOff, pObjectToFocus )
{
  if( sLayerOn )
  {
    switchLayer( sLayerOn, true );
    switchLayer( sAction + '_button_layer' );
    if ( pObjectToFocus && getLayerDisplayed( sLayerOn ) )
       pObjectToFocus.focus();
  }
  if( sLayerOff )
  {
    switchLayer( sLayerOff, true );
  }
}

function switchPortlet( nContainerID )
{
  switchLayer( nContainerID );
  switchLayer( nContainerID + '_close_button' );
  switchLayer( nContainerID + '_open_button' );

  if ( getBrowser() != IE ) //&& getLayer('portalview') )
  {
      setDOMObjectProperty('portalview', 'style.display', 'none');
      setDOMObjectProperty('portalview', 'style.display', '');
  }
}

// bAppend to append the result to the existing value
// bMultiple to return multiple results (if the function is called more than once)
function setReturnValue( sJSSetter, sFieldName, sFormName, sValue, bAppend, bFocus, bMultiple )
{
  if( window.dialogArguments != undefined )
  {
    if( bMultiple && window.returnValue != undefined )
      window.returnValue += ',' + sValue;
    else
      window.returnValue = sValue;
  }
  else
  {
    var pDocument = findParentDocument( 'app', window.opener );

    if( !getFormObject( sFieldName, sFormName, pDocument ) )
      pDocument = window.opener.document;
    
    var sExistingValue = getInputValue( sFieldName, sFormName, pDocument );
    var sReturnValue = bAppend
      ? sExistingValue + ( sExistingValue != '' ? ',' : '' ) + sValue
      : sValue;

    evalFunc( sJSSetter, sFieldName, sReturnValue, sFormName, pDocument );

    var pInputObject = getFormObject( sFieldName, sFormName, pDocument );
    
    if( bFocus )
       focusObject( pInputObject );
       
    try { pInputObject.onchange(); } catch( ex ) {}
    try { pInputObject.onblur(); } catch( ex ) {}
  }
}


// Works well BUT because of the fixed-layout table, the content of the former scrollview
// spills over the other cells :/
// Update: Fixed??

function hideScrollPanels( pDocument )
{
  if ( getBrowser() == NETSCAPE || g_bDisableScrolPanels )
  {
    hideGlobalLayer();
    
    // on remet en place les croll globales
    pDocument ? pDocument.body.style.overflow = "auto" : window.document.body.style.overflow = "auto";
    
    
    var aPanels = getScrollPanes( pDocument );
    for (var nI=0; nI<aPanels.length; nI++)
    {
      var pPanel = aPanels[nI];
      var nH = pPanel.style.height;

      if ( !nH || nH.substring( nH.length-1, nH.length ) == '%' )
      {
        pPanel.style.overflow = 'visible';
        // ca m'arrange dans certains cas, mais ca pourrait causer des problèmes
        pPanel.style.height = '';          
      }
    }
    
    var aTables = getFixedTables( pDocument );
    for( var nJ = 0; nJ < aTables.length; nJ++ )
    {
      aTables[ nJ ].style.tableLayout = "";
    }

    showGlobalLayer();
  }
}

function getScrollPanes( pDocument )
{
  if( pDocument == null ) pDocument = window.document;

  var panels = new Array();

  var divs = pDocument.getElementsByTagName('DIV');
  for (var d=0; d<divs.length; d++)
  {
    if ( divs[d].className == 'scrollpane' )
    {
      panels.push( divs[d] );
    }
  }
  
  var pPlanningDiv = getDOMObject("master_div");
  if( pPlanningDiv )
  {
    panels.push( pPlanningDiv );
  }

  return panels;
}

function getFixedTables( pDocument )
{
  if( pDocument == null ) pDocument = window.document;

  var aFixed  = new Array();

  // pas la peine de boucler sur toutes les tables, il n'y en a que très peu à modifier:

  var p1 = getDOMObject( 'planning_fixed_layer', pDocument );
  if( p1 != null )
    aFixed.push(p1);

  var p2 = getDOMObject( 'sub_global_fixed_layer', pDocument );
  if( p2 != null )
    aFixed.push(p2);

  var p3 = getDOMObject( 'global_popup_fixed_layer', pDocument );
  if( p3 != null )
    aFixed.push(p3);

/*
  var p4 = getDOMObject( 'global_iframe_fixed_layer', pDocument );
  if( p4 != null )
    aFixed.push(p4);
*/
  
/*
  var aTables = pDocument.getElementsByTagName('TABLE');
  for( var nI = 0; nI < aTables.length; nI++ )
  {
    if( aTables[nI].style.tableLayout == 'fixed' && aTables[nI].id != 'menu_layer' )
    {
      aFixed.push( aTables[ nI ] );
    }
  }
*/

  return aFixed;
}

function getParentNode( pObject, sTagName )
{
  var pParent = pObject.parentNode;
  if( sTagName )
  {
    while( pParent != null && pParent.tagName.toUpperCase() != sTagName )
      pParent = pParent.parentNode;
  }
  return pParent;
}

// Simple encryption function

var g_sCryptKey = "fs'v#{~^@]$1s\"d5x.4(*_=s9";

function _xorString( sString, sKey )
{
  var sResult = "";
  for(var nI=0; nI<sString.length; ++nI)
  {
    sResult += String.fromCharCode( sKey.charCodeAt(nI % sKey.length) ^ sString.charCodeAt(nI) );
  }
  return sResult;
}

function encryptString( sString, sKey )
{
  return "C"+encodeURIComponent(_xorString(sString,sKey));
}

function decryptString( sString, sKey )
{
  if( sString.charAt(0) == 'C' )
  {
    sString = sString.substring(1);
    sString = decodeURIComponent(sString);
    sString = _xorString( sString, sKey );
  }
  
  return sString;
}

function findPosX(obj, pParent)
{
  var curleft = 0;
  if (obj.offsetParent)
  {
    while (obj.offsetParent && (!pParent || obj.offsetParent != pParent) )
    {
      curleft += obj.offsetLeft;
      obj = obj.offsetParent;
    }
  }
  else if (obj.x)
    curleft += obj.x;
  return curleft;
}

function findPosY( obj, pParent )
{
  var curtop = 0;
  if( obj.offsetParent )
  {
    while( obj.offsetParent  && (!pParent || obj.offsetParent != pParent) )
    {
      curtop += obj.offsetTop;
      obj = obj.offsetParent;
    }
  }
  else if (obj.y)
    curtop += obj.y;
  return curtop;
}

function findBrowserPosX( obj, pParent )
{
  if( getBrowser() == IE )
    return obj.offsetLeft;
  else
    return findPosX(obj, pParent);
}

function findBrowserPosY( obj, pParent )
{
  
  if( getBrowser() == IE )
    return obj.offsetTop;
  else
    return findPosY(obj, pParent);
}

function fireOnChangeEvent( pObject )
{
  // IE
  if( pObject.onchange != null )
    pObject.onchange();
  // Mozilla
  if( pObject.onChange != null )
    pObject.onChange();
}


function fireOnClickEvent( pObject )
{
  // IE
  if( pObject.onclick != null )
    pObject.onclick();
  // Mozilla
  if( pObject.onclick != null )
    pObject.onclick();
}

function printfire()
{
    if (document.createEvent)
    {
        printfire.args = arguments;
        var ev = document.createEvent("Events");
        ev.initEvent("printfire", false, true);
        dispatchEvent(ev);
    }
}

// fonction pour gérer les positions

function parsePosition( sString )
{
  var pRegExp = getRegExp( '([^p]*)\s*(?:px)?', 'm');
  var aMatches = pRegExp.exec(sString);
  if( aMatches )
    return aMatches[1] * 1;
  return 0;
}

function positionToString( nPosition )
{
  return nPosition + 'px';
}

function getScrollX( pElement ) 
{
  var sx = 0;

  if( pElement != null && pElement.scrollLeft )
    return pElement.scrollLeft;
    
  if ( document.documentElement && document.documentElement.scrollLeft )
    sx = document.documentElement.scrollLeft;
  else if ( document.body && document.body.scrollLeft ) 
    sx = document.body.scrollLeft; 
  else if ( window.pageXOffset )
    sx = window.pageXOffset;
  else if ( window.scrollX )
    sx = window.scrollX;
  return sx;
}

function getScrollY( pElement ) 
{
  var sy = 0;
  
  if( pElement != null && pElement.scrollTop )
    return pElement.scrollTop;
  
  if ( document.documentElement && document.documentElement.scrollTop )
    sy = document.documentElement.scrollTop;
  else if ( document.body && document.body.scrollTop ) 
    sy = document.body.scrollTop; 
  else if ( window.pageYOffset )
    sy = window.pageYOffset;
  else if ( window.scrollY )
    sy = window.scrollY;
  return sy;
}



function showWaitLayer( sLayerName, sWaitMessage)
{ 
  var pWaitLayer = getLayer( sLayerName );
  if( pWaitLayer )
  {
    // place le layer
    //try
    //{
    //    var nScreenWidth  = document.body.offsetWidth;
    //    var nScreenHeight = document.body.offsetHeight;
    //    var nLayerWidth  = parsePosition( pWaitLayer.style.width );
    //    var nLayerHeight = parsePosition( pWaitLayer.style.height );
    //
    //    if( getBrowser() == NETSCAPE )
    //    {
    //      //pWaitLayer.style.left = getScrollX() + nScreenWidth / 2 - nLayerWidth / 2;
    //      //pWaitLayer.style.top  = getScrollY() + nScreenHeight / 2 - nLayerHeight / 2;
    //    }
    //    else
    //    {
    //      //pWaitLayer.style.left = 0;
    //      //pWaitLayer.style.top  = 0;
    //      //pWaitLayer.style.width = document.body.clientWidth;
    //      //pWaitLayer.style.height  = document.body.clientHeight;
    //    }
    //}
    //catch( ex ) { }

    // sous IE 6 cache les select car sinon, ils apparaissent toujours en avant plan
    if( getBrowser() == IE )
      hideSelect( null );
      
    // spécification du message d'attente
    var pWaitMessageLabel = getDOMObject('wait_message_label');
    if( pWaitMessageLabel )
        setInnerHTML( pWaitMessageLabel, sWaitMessage );
    
    // on affiche la layer
    showLayer( sLayerName, null, true );
    showLayer( sLayerName+"_content", null, true );
  }
}

function hideWaitLayer( sLayerName )
{ 
    var pWaitLayer = getLayer( sLayerName );
    if( pWaitLayer )
    {
      if( getBrowser() == IE )
        showSelect( null );
        
      hideLayer( sLayerName, null, true );
      hideLayer( sLayerName+"_content", null, true );
    }
}

function createWaitLayer( sLayerName, sWaitMessage)
{ 
  jQuery('wait_message_label').html(sWaitMessage);
  var waitLayer = jQuery( sLayerName ).clone().show();
  waitLayer.attr('id',sLayerName + '_clone');
  waitLayer.find('#'+sLayerName+"_content").attr('id',sLayerName+"_clone_content").show();
}

function destroyWaitLayer( sLayerName )
{ 
  jQuery('#'+sLayerName+'_clone,#'+sLayerName+'_clone_content').remove();
}

// Fonctions permettant l'affichage d'un élément avant l'appel à une fonction (remote)

function showLayerAndCall( sLayerName, fFunction )
{ 
  var aArguments = showLayerAndCall.arguments;
  if( aArguments < 2 )
    return;
  
  var aRealArgs = new Array();
  // ignore les 2 premiers arguments
  for( var i=2; i < aArguments.length; i++ )
    aRealArgs.push( aArguments[ i ] );

  var pWaitLayer = getLayer( sLayerName );
  if( pWaitLayer )
  {
    // place le layer
    try
    {
        var nScreenWidth  = document.body.offsetWidth;
        var nScreenHeight = document.body.offsetHeight;
        var nLayerWidth  = parsePosition( pWaitLayer.style.width );
        var nLayerHeight = parsePosition( pWaitLayer.style.height );
  
        if( getBrowser() == NETSCAPE )
        {
          pWaitLayer.style.left = getScrollX() + nScreenWidth / 2 - nLayerWidth / 2;
          pWaitLayer.style.top  = getScrollY() + nScreenHeight / 2 - nLayerHeight / 2;
        }
        else
        {
          pWaitLayer.style.left = nScreenWidth / 2 - nLayerWidth / 2;
          pWaitLayer.style.scrollTop  = nScreenHeight / 2 - nLayerHeight / 2;
        }
    }
    catch( ex ) { }

    if( getBrowser() == IE )
      hideSelect( null ); // pWaitLayer
    showLayer( sLayerName, null, true );
  }

  // utilise un timer pour appeler la vraie fonction
  var hCallBack = getCallbackHandler( sLayerName, fFunction, aRealArgs );
  window.setTimeout( hCallBack, 50 );
}

function handleCallback()
{
    var pException = null;
    var aRealArgs = top.CallbackHandler.aRealArgs;
    var fFunction = top.CallbackHandler.fFunction;
    var sLayerName = top.CallbackHandler.sLayerName;
    try
    {
      fFunction.call( aRealArgs[0], aRealArgs[1], aRealArgs[2], aRealArgs[3], aRealArgs[4], aRealArgs[5], aRealArgs[6], aRealArgs[7], aRealArgs[8], aRealArgs[9], aRealArgs[10] );
    }
    catch( ex )
    {
      pException = ex;
    }

    var pWaitLayer = getLayer( sLayerName );
    if( pWaitLayer )
    {
      if( getBrowser() == IE )
        showSelect( null ); // pWaitLayer
      hideLayer( sLayerName, null, true );
    }

    if( pException != null )
      throw pException;
    top.CallbackHandler = null;
}
// retourne une fonction anonyme pour gérer l'appel
function getCallbackHandler( sLayerName, fFunction, aRealArgs )
{
  top.CallbackHandler = {
      sLayerName: sLayerName,
      fFunction: fFunction,
      aRealArgs: aRealArgs
  };
  return handleCallback;
}

function DumpObjectToFile(sName, xObject, sFile)
{
   WriteToFile( sFile, DumpObject( sName, xObject ) );
   //alert(DumpObject( sName, xObject ));
}

function DumpObject(sName, xObject, aAlreadyDumped, nLevel)
{
   aAlreadyDumped = aAlreadyDumped ? aAlreadyDumped : new Array();
   nLevel = nLevel ? nLevel : 0;
   var sDump = new String();
   if( ! (xObject instanceof Function) )
   {
      for(i=0;i<nLevel;i++)
         sDump += ' ';
      try
      {
         if( xObject instanceof DBObject ||
             xObject instanceof Array)
         {
            if( arrayContains(aAlreadyDumped, xObject) )
            {
               sDump += sName+': ...\n';
            }
            else
            {
               aAlreadyDumped.push(xObject);
               sDump += sName+':\n';
               for (var xProperty in xObject)
                 sDump += DumpObject( xProperty, xObject[xProperty], aAlreadyDumped, nLevel+1);
            }
         }
         else
            sDump += sName+": "+xObject+'\n';
      }
      catch(ex)
      {
         sDump += sName+': ERROR';
      }
   }
   return sDump;
}

function WriteToFile(sFile, sContent) {
 try {
   var fso, s;
   fso = new ActiveXObject("Scripting.FileSystemObject");
   s = fso.OpenTextFile(sFile , 2, 1, -2);
   s.writeline(sContent);
   s.Close();
 }
catch(err){
  var strErr = 'Error:';
  strErr += '\nNumber:' + err.number;
  strErr += '\nDescription:' + err.description;
  alert(strErr);
 }
}

function getRowCount( sButtonID, sLabelID, sListName, sParameters )
{
  var nCount = "-";
  
  // Remote pour avoir le nombre d'éléments
  try
  {
    var pLabel = getDOMObject( sLabelID );
    if( pLabel )
    {
      setInnerHTML( pLabel, '&nbsp;&nbsp;...&nbsp;&nbsp;');
      hideLayer( sButtonID );
      showLayer( sLabelID );

      nCount = remoteCall( 'engine::remote::listparam',
                                'getRowCount',
                                sListName,
                                sParameters );
      
      var pLabel = getDOMObject( sLabelID );
      if( pLabel )
        setInnerHTML(pLabel, nCount);
    }
  }
  catch( ex )
  {
  }
}



/* **************************************************************
                            Console
 ************************************************************* */

function DBConsole()
{
}

DBConsole.prototype.setFrame = function DBConsole_setFrame( sFrameName, pFrameWindow, pEvalWindow )
{
  this.pEvalWindow   = pEvalWindow;
  this.sFrameName    = sFrameName;
  this.pFrameWindow  = pFrameWindow;
  this.bInit         = false;
  this.bEnabled      = true;
  this.pTable        = null;
  this.pInputCell    = null;
  this.pInput        = null;
  
  this.aCommandHistory      = new Array();
  this.nHistoryCurrentIndex = 0;
  this.nHistoryInsertIndex  = -1;
  this.nHistoryMax          = 50;
  
  this.aTimers = new Array();
  
  // handler pour scroller
  var pSelf = this;
  this.hScrollFunc = function( event ) { pSelf._scrollToLast(); };
}

// Initialisation de l'objet et du tableau
DBConsole.prototype.init = function DBConsole_init()
{
  if( !this.bInit )
  {
    try
    {
      this.pFrameDocument = this.pFrameWindow.document;
      
      var pFrame = getDOMObject( this.sFrameName, this.pFrameDocument );
      
      var pTable = getDOMObject( 'db_list', this.pFrameDocument );
      var pInput = getDOMObject( 'db_command_input', this.pFrameDocument );
      var pClear = getDOMObject( 'db_clear_button', this.pFrameDocument );

      if( !pTable )
      {
        // Liste
        pTable = this.pFrameDocument.createElement("table");
        pTable.id = 'db_list';
        pTable.cellPadding = 0; // saleté d'IE qui comprend rien
        pTable.cellSpacing = 0;
        pTable.className = 'dbconsole_table';
  
        var pBody = this.pFrameDocument.createElement("tbody");
        pTable.appendChild( pBody );

        pFrame.appendChild( pTable );
      }

      if( !pInput )
      {
        // Editeur
        var pInputTable = this.pFrameDocument.createElement("table");
        pInputTable.cellPadding = 0; // saleté d'IE qui comprend rien
        pInputTable.cellSpacing = 0;
        pInputTable.className = 'dbconsole_table';
        
        var pInputBody = this.pFrameDocument.createElement("tbody");
        pInputTable.appendChild( pInputBody );
        
        var pInputRow = pInputBody.insertRow(-1);
        
        this.pInputCell = pInputRow.insertCell(-1);
        this.pInputCell.className = "dbconsole_log_row dbconsole_log_row_command_input";
        var pButtonsCell = pInputRow.insertCell(-1);
        pButtonsCell.className = "dbconsole_log_row dbconsole_log_row_command_buttons";
  
        pInput = this.pFrameDocument.createElement("input");
        pInput.id = 'db_command_input';
        pInput.type = 'text';
        pInput.className = 'dbconsole_log_row dbconsole_input';

        this.pInputCell.appendChild( pInput );
        
        pClear = this.pFrameDocument.createElement("input");
        pClear.id = 'db_clear_button';
        pClear.type = 'button';
        pClear.value = 'Clear';
        pClear.className = 'dbconsole_log_row dbconsole_button';
        
        pButtonsCell.appendChild( pClear );

        pFrame.appendChild( pInputTable );
      }

      // on fait ça en dehors de if au cas où les tables soient déjà
      // initialisées mais qu'on aie changé d'objet et dans ce cas il
      // faut relier les evenements!

      // Evenements
      var pSelf = this;
      this.onKeyPress = function( event ) { pSelf.onInputKeyPress(event); };
      if( pInput.addEventListener )
        pInput.addEventListener( "keypress", this.onKeyPress, true );
      else if( pInput.attachEvent )
        pInput.attachEvent( "onkeydown", this.onKeyPress );

      this.onClearPress = function( event ) { pSelf.clear(); };
      if( pClear.addEventListener )
        pClear.addEventListener( "click", this.onClearPress, true );
      else if( pClear.attachEvent )
        pClear.attachEvent( "onclick", this.onClearPress );

      this.pTable = pTable;
      this.pInput = pInput;

      // HACK : ultime bidouille...
      // le problème lorsqu'on stock l'objet dans la frame server
      // c'est que les autres objets sont initialisés avec leur
      // propre objet (mais qui ne fait rien).
      // Si on change de page dans "app" on va bien utiliser le
      // bon pDBObject, mais les autres frames (menu et top) ne
      // sont jamais rechargées. Pour que tout le monde aie le
      // même objet, je les remplace moi même dans le init!
      
      // sinon on utilise une console vide qui n'affiche rien
      if( this.pEvalWindow )
      {
        this.pEvalWindow.pDBConsole = this;
        for( var nI=0; nI < this.pEvalWindow.frames.length; nI++ )
          this.pEvalWindow.frames[nI].pDBConsole = this;
      }
      
      this.bInit = true;
    }
    catch( ex )
    {
      alert(ex);
      return false;
    }
  }
  
  return true;
}

DBConsole.prototype._log = function DBConsole_log( sMessage, sRowClass )
{
  // si pas bien initialisé on ne fait rien...
  if( !this.bInit || !this.bEnabled ) return;

  var pTable = this.pTable;
  var pBody  = pTable.tBodies[0];

  var pRow = pBody.insertRow(-1);
  
  var pCell = pRow.insertCell(-1);

  if( sMessage && typeof(sMessage) == "string" && sRowClass == "result" )
    sMessage = '"'+sMessage+'"';
  
  // pas la peine de surcharger ça avec Firefox
  if( getBrowser() == IE && sMessage )
  {
    if( typeof(sMessage) == "object" && this.pEvalWindow.eval(sMessage instanceof Error) )
      sMessage = sMessage.name + ": " + sMessage.message;
    else if( typeof(sMessage) == "object" && sMessage.toString )
      sMessage = sMessage.toString();
      
    if( sMessage && typeof(sMessage) == "string" )
    {
      sMessage = sMessage.replace( / /g, '&nbsp;' );
      sMessage = sMessage.replace( /\n/g, '<br>' );
    }
  }

  setInnerHTML( pCell, sMessage != null && sMessage != "" ? sMessage : "&nbsp;");
  pCell.className = "dbconsole_log_row dbconsole_log_row_"+sRowClass;
  
  this._startScroll();
}

// Le défilement n'est pas synchrone, on le fait après 100ms
// Donc si d'autres appels sont fait, on ne scroll qu'une fois

DBConsole.prototype._startScroll = function DBConsole__startScroll()
{
  if( this.nScrollTimer != null ) return;
  this.nScrollTimer = this.pFrameWindow.setTimeout( this.hScrollFunc, 150 );
}

DBConsole.prototype._scrollToLast = function DBConsole__scrollToLast()
{
  this.nScrollTimer = null;
  this.pFrameWindow.scrollTo( 0, this.pInputCell.y ? this.pInputCell.y : this.pInputCell.offsetTop );
}

DBConsole.prototype._evaluateInput = function DBConsole__evaluateInput()
{
  var sExpression = this.pInput.value
  
  if( sExpression == "" )
    return;
  
  this.pInput.value = '';

  this._appendToHistory( sExpression );

  this._log( ">>> " + sExpression, "command" );
  
  var sResult = null;
  var sError = null;
  try
  {
    var pEvalWindow = this.pEvalWindow ? this.pEvalWindow : window;

    //with(this.pEvalWindow)
    //{
    //    pDBConsoleEvalFunction = new Function("return "+sExpression);
    //    sResult = pDBConsoleEvalFunction();
    //}

    sResult = pEvalWindow.eval( sExpression );
  }
  catch( ex )
  {
    // window.eval perd le type du résultat sur l'IE o_O
    if( getBrowser() == IE && ex && ex.message )
    {
      var pNew = new Error();
      pNew.name = ex.name;
      pNew.message = ex.message;
      ex = pNew;
    }
    this.error( ex );
  }
  
  if( sResult != null && sResult != undefined )
    this._log( sResult, "result" );
}

DBConsole.prototype._appendToHistory = function DBConsole__appendToHistory( sExpression )
{
  if( ++this.nHistoryInsertIndex >= this.nHistoryMax )
    this.nHistoryInsertIndex = 0;
    
  this.nHistoryCurrentIndex = this.nHistoryInsertIndex + 1;
  this.aCommandHistory[ this.nHistoryInsertIndex ] = sExpression;
}

DBConsole.prototype._cycleInputHistory = function DBConsole__cycleInputHistory( nOffset )
{
  this.aCommandHistory[ this.nHistoryCurrentIndex ] = this.pInput.value;
  
  if( nOffset < 0 )
  {
    this.nHistoryCurrentIndex += nOffset;
    if( this.nHistoryCurrentIndex < 0 )
      this.nHistoryCurrentIndex = 0;
  }
  else
  {
    this.nHistoryCurrentIndex += nOffset;
    if( this.nHistoryCurrentIndex > this.nHistoryInsertIndex + 1 )
      this.nHistoryCurrentIndex = this.nHistoryInsertIndex + 1;
  }

  var sExpression = this.aCommandHistory[ this.nHistoryCurrentIndex ];

  this.pInput.value = sExpression;
  
  if( this.pInput.setSelectionRange )
  {
    this.pInput.setSelectionRange( sExpression.length, sExpression.length );
  }
  else if( this.pInput.setSelectionRange )
  {
    var pRange = this.pInput.createTextRange();
    pRange.collapse( true );
    pRange.moveEnd( 'character', sExpression.length );
    pRange.moveStart( 'character', sExpression.length );
    pRange.select();
  }
}

DBConsole.prototype.onInputKeyPress = function DBConsole_onInputKeyPress( event )
{
  if( event.keyCode == 13 )
    this._evaluateInput();
  else if( event.keyCode == 27 )
    this.pInput.value = '';
  else if( event.keyCode == 38 )
    this._cycleInputHistory(-1);
  else if( event.keyCode == 40 )
    this._cycleInputHistory(1);
}


  /* Fonction publiques */

// TODO : pourquoi 'arguments' ne marche pas???

DBConsole.prototype.log = function DBConsole_log( sMessage )
{
  this._log( sMessage, "log" );
}

DBConsole.prototype.debug = function DBConsole_debug( sMessage )
{
  this._log( sMessage, "debug" );
}

DBConsole.prototype.info = function DBConsole_info( sMessage )
{
  this._log( sMessage, "info" );
}

DBConsole.prototype.warn = function DBConsole_warn( sMessage )
{
  this._log( sMessage, "warn" );
}

DBConsole.prototype.error = function DBConsole_error( sMessage )
{
  this._log( sMessage, "error" );
}

DBConsole.prototype.clear = function DBConsole_clear()
{
  if( !this.bInit || !this.bEnabled ) return;

  var pTable = this.pTable;
  var pBody  = pTable.tBodies[0];
  while( pBody.rows.length != 0 )
    pBody.deleteRow(0);
}

DBConsole.prototype.time = function DBConsole_time( sName )
{
  if( !this.bInit || !this.bEnabled || !sName ) return;

  var pTime = new Date().getTime();
  this.aTimers[ sName ] = pTime;
}

DBConsole.prototype.timeEnd = function DBConsole_timeEnd( sName )
{
  if( !this.bInit || !this.bEnabled || !sName ) return;

  var pTime = new Date().getTime();

  var pStartTime = this.aTimers[ sName ];
  if( pStartTime )
  {
    this._log( sName + ": " + ( pTime - pStartTime ) + "ms", "log" );
    delete this.aTimers[ sName ];
  }
}

DBConsole.prototype.trace = function DBConsole_trace()
{
  this._log( getStackTrace(1), "stack" );
}

DBConsole.prototype.focus = function DBConsole_focus()
{
  if( !this.bInit ) return;
  
  this.pInput.focus();
}

/* Fonction utiles */

function getStackTrace( nIgnoreLevel )
{
  var sOut = '';
  try
  {
    nIgnoreLevel = nIgnoreLevel ? nIgnoreLevel : 0;
    
    var fCaller = getStackTrace.caller;
    var nLevel = 0;
    
    for( var a = fCaller; a != null; a = a.caller )
    {
      var sFuncName = "anonymous";
      try
      {
        var aMatches = a.toString().match(/function (\w*)/);
        if( aMatches && aMatches[1] )
          sFuncName = aMatches[1];
      }
      catch( ex ) {}
  
      if( a.caller == a )
        sFuncName += "*";
  
      if( nLevel >= nIgnoreLevel )
        sOut += sFuncName + "\n";
  
      if( a.caller == a )
        break;
      
      nLevel++;
    }
  }
  catch(ex)
  {
    sOut += 'Cannot get stacktrace: '+ex.message;
  }
  
  return sOut;
}

function getTopFrameSet()
{
  var pFrameSet = null;
  
  if( getDOMObject( "homeframes", window.document ) )
    pFrameSet = getDOMObject( "homeframes", window.document );
  else if( window.top && getDOMObject( "homeframes", window.top.document ) )
    pFrameSet = getDOMObject( "homeframes", window.top.document );

  return pFrameSet;  
}

function showDBConsole()
{
  var pFrameSet = getTopFrameSet();
  if( pFrameSet )
    pFrameSet.rows = "80%,20%,0%";
  pDBConsole.focus();
}

function hideDBConsole()
{
  var pFrameSet = getTopFrameSet();
  if( pFrameSet )
    pFrameSet.rows = "100%,0%,0%";
}

// si la console dans la frame 'server' est initialisée on l'utilise
// sinon on utilise une console vide qui n'affiche rien
var pDBConsole = window.top && window.top.server && window.top.server.pDBConsole
                    ? window.top.server.pDBConsole
                    : new DBConsole();
// TODO : tester window.console (Firebug) aussi

// Renvoie la date du jour en fonction de la configuration
// /!\ Il faut utiliser cette fonction au lieu de new Date() 
function getCurrentDate()
{
  if( CURRENT_DATE == undefined )
  {
    dDate = new Date();
    dDate.setHours(0);
    dDate.setMinutes(0);
    dDate.setSeconds(0);
    dDate.setMilliseconds(0);
    return dDate;
  }
  return parseFixedDate( CURRENT_DATE );
}

function getCurrentDateTime()
{
  if( CURRENT_DATE_TIME == undefined )
    return new Date();
  return parseFixedDateTime( CURRENT_DATE_TIME );
}

function goHref(newHref, windowObj)
{
  if(windowObj == null)
    windowObj = window;
  if(windowObj.destroyPage)
  {
    try
    {
      if(windowObj.destroyPage(newHref) !== false)
        windowObj.location.href = newHref;
    }
    catch(ex)
    {
      //if(ex instanceof CheckerException && ex.getErrorNumber() == WARNING_PLEASE_SAVE_BEFORE_QUITTING )
        ex.showUser();
    }
  }
  else
    windowObj.location.href = newHref;
}

/**
 * Hide a tab. This require jQuery.
 * @param <String> name Name of the tab to hide.
 * @return void
 */
function hideTab(name) {
	jQuery('#tabs_'+name).hide();
}

//Call stack code
function showCallStack(){
   var f=showCallStack,result="Call stack:\n";
   while((f=f.caller)!==null){
      var sFunctionName = f.toString().match(/^function (\w+)\(/)
      sFunctionName = (sFunctionName) ? sFunctionName[1] : 'anonymous function';
      result += sFunctionName;
      result += getArguments(f.toString(), f.arguments);
      result += "\n";
   }
   return result;
}

function getArguments(sFunction, a) {
   var i = sFunction.indexOf(' ');
   var ii = sFunction.indexOf('(');
   var iii = sFunction.indexOf(')');
   var aArgs = sFunction.substr(ii+1, iii-ii-1).split(',')
   var sArgs = '';
   for(var i=0; i<a.length; i++) {
      var q = ('string' == typeof a[i]) ? '"' : '';
      sArgs+=((i>0) ? ', ' : '')+(typeof a[i])+' '+aArgs[i]+':'+q+a[i]+q+'';
   }
   return '('+sArgs+')';
}

//This prototype is provided by the Mozilla foundation and
//is distributed under the MIT license.
//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license

function ArrayIndexOf(array, elt , from)
{
    if ( array == null )
      return -1;
    var len = array.length;
    var from = Number(arguments[2]) || 0;
    from = (from < 0) ? Math.ceil(from) : Math.floor(from);
    if (from < 0)
        from += len;
    for (; from < len; from++)
    {
        if (from in array && array[from] === elt)
            return from;
    }
    return -1;
}

function fixUnload() {
        // Is there things still loading, then fake the unload event
        if (document.readyState == 'interactive') {
                function stop() {
                        // Prevent memory leak
                        document.detachEvent('onstop', stop);
                        // Call unload handler
                        unload();
                };
                // Fire unload when the currently loading page is stopped
                document.attachEvent('onstop', stop);
                // Remove onstop listener after a while to prevent the unload function
                // to execute if the user presses cancel in an onbeforeunload
                // confirm dialog and then presses the stop button in the browser
                window.setTimeout(function() {
                        document.detachEvent('onstop', stop);
                }, 0);
        }
};

function unload() 
{
    //if ( window.jQuery !== null )
    if ( window && window.jQuery )
    {
      window.jQuery('body').unbind('load').unbind('unload');
      var handlers = window.jQuery.allEventsHandlers;
      for (var ha in handlers)
      {
          var h = handlers[ha];
          h.element.detachEvent("on"+h.type,h.handle);
      }
      window.jQuery.allEventsHandlers = null;
      window.DP_jQuery = null;
      window.jQuery = null;
      window.$ = null;
    }
    window.onresize = null;
    window.onload = null;
    window.onerror = null;
    window.popupWindowObjects = null;
    window.onbeforeunload = null;
    window.onunload = null;
    window.detachEvent('onbeforeunload',fixUnload);
    window.detachEvent('onunload',unload);
};

if ( window.attachEvent )
{
  window.attachEvent('onunload', unload);
  window.attachEvent('onbeforeunload', fixUnload);
}

