PARTNER_ACCOUNT    = 1;
INDIVIDUAL_ACCOUNT = 2;

var CLIENT_TYPE_PROPRI = 3;

function genInputHTML( HTMLTemplate, name , nRowNumber, nColNumber, sRowID )
{
  var sRet = HTMLTemplate;

  sRet = sRet.replace( /templateName/g, name );
  sRet = sRet.replace( /nRowNumber/g, nRowNumber );
  sRet = sRet.replace( /nColNumber/g, nColNumber );
  sRet = sRet.replace( /sRowID/g, sRowID );
  
  return sRet;
}

function genTextInputOperatorsHTML( HTMLTemplate, name )
{
  var sRet = HTMLTemplate;

  var sTmp = sRet.replace( /templateName_cs/g, name + '_cs' );

  return sTmp.replace( /templateName/g, name );
}

function setTextInputOperatorValue( inputName, value, formName, myDocument )
{
  if( value != null && value != '' )
  {
    var select_value = value.substr( 0, 2 );
    var checkbox_value = (value.substr( 3, 1 ) == '0') ? false : true;

    setInputValue( inputName, select_value, formName, myDocument );
    setInputValue( inputName + '_cs', checkbox_value, formName, myDocument );
  }
  else
  {
    setInputValue( inputName, '', formName, myDocument );
    setInputValue( inputName + '_cs', false, formName, myDocument );
  }
}

function getTextInputOperatorValue( inputName, formName, myDocument )
{
  var select_value = getInputValue(inputName, formName, myDocument );
  var checkbox_value = (!getInputValue(inputName + '_cs', formName, myDocument )) ? '0' : '1';

  return select_value + '|' + checkbox_value;
}

function setCheckboxInputValue( inputName, value, formName, myDocument, bNoVisibilityChange )
{
  //  alert( value );
  if( !bNoVisibilityChange )
  {
    if(value == -1)
    {
      setFormObjectProperty(inputName, formName, 'style.visibility', 'hidden', myDocument);
    }
    else
    {
      setFormObjectProperty(inputName, formName, 'style.visibility', 'visible', myDocument);
    }
  }
  if( !value || value == '' || value == '0' )
  {
    //return setInputValue( inputName, false, formName, myDocument )
    setFormObjectProperty(inputName, formName, 'checked', false, myDocument);
  }
  else
  {
    //return setInputValue( inputName, true, formName, myDocument )
    setFormObjectProperty(inputName, formName, 'checked', true, myDocument);
  }
}

function setImageHiddenLabelInputValue(sName, sValue, sFormName, dDocument)
{
  if(sValue)
  {
    setHiddenLabelInputValue(sName + '_label', sValue, sFormName, dDocument);
    setDOMObjectProperty(sName, 'style.visibility', 'visible', dDocument);
  }
  else
  {
    setHiddenLabelInputValue(sName + '_label', '', sFormName, dDocument);
    setDOMObjectProperty(sName, 'style.visibility', 'hidden', dDocument);
  }
}

function setLangTextInputValue(sName, sValue, sFormName, dDocument)
{
  sName = sName + "_" + USER_LANG_ID;
  setInputValue(sName, sValue, sFormName, dDocument);
}

//
// Setter le contenu d'un champ textarea
//
function setTextAreaInputValue( sInputName, sValue, sFormName, pMyDocument )
{
  // if set value in html template
  if( g_sHTMLTemplate && g_sHTMLTemplate != "" )
  {
    updateInputObjectContent( sInputName, sValue );
  }
  else
  {
    setInputValue( sInputName, sValue, sFormName, pMyDocument );
  }
}

/*function getDyntableTextInputValue( inputName, formName, myDocument )
{
  var text_value = getInputValue( inputName, formName, myDocument );
  var hidden_value = getInputValue( inputName + '_field_name', formName, myDocument );

  alert( text_value + '|' + hidden_value );

  return text_value + '|' + hidden_value;
}

function setDyntableTextInputValue( inputName, value, formName, myDocument )
{
  if( value != null && value != '' )
  {
    value.match( /^(.*)\|(.*)$/ );

    var text_value = RegExp.$1;
    var hidden_value = RegExp.$2;

    alert( 'value=' + value + ' text_value=' + text_value + ' hidden_value=' + hidden_value );

    setInputValue( inputName, text_value, formName, myDocument );
    setInputValue( inputName + '_field_name', hidden_value, formName, myDocument );
  }
  else
  {
    setInputValue( inputName, '', formName, myDocument );
    setInputValue( inputName + '_field_name', '', formName, myDocument );
  }
}
*/

function isCodeSelect( sInputName, sFormName, pDocument )
{
  var pControl = getFormObject( sInputName + '_select', sFormName, pDocument );
  return pControl != null;
}

function setCodeSelectInputValue( inputName, value, formName, myDocument, pOption )
{
  //Obligé de faire une deuxieme fonction setSelectInputValue ne doit pas renvoyer quoi que ce soit !
  var found = setSelectAndReturnInputValue(inputName + '_select', value, formName, myDocument);

  if( found )
  {
    setInputValue( inputName, value, formName, myDocument );
  }
  else
  {
    if(pOption)
    {
      setSelectOptions(inputName+'_select', formName, new Array(pOption), true);
      setInputValue( inputName, pOption.value, formName, myDocument );
      setSelectInputValue( inputName + '_select', pOption.value, formName, myDocument);
    }
    else
    {
      var val = getSelectInputValue(inputName + '_select', formName, myDocument);
      setInputValue(inputName, val, formName, myDocument);
      setSelectInputValue(inputName + "_select", val, formName, myDocument);
    }
  }
}

function getCodeSelectInputValue(sName, sFormName)
{
  return getInputValue(sName+'_select', sFormName);
}

function setCodeSelectProperty(sName, sFormName, sProperty, sValue, pDocument)
{
  setFormObjectProperty(sName+'_select', sFormName, sProperty, sValue, pDocument);

  return setFormObjectProperty(sName, sFormName, sProperty, sValue, pDocument);
}

function setCodeSelectOptions(sName, sFormName, aOptions, bLeaveExisting, bLabelSort, bAddPleaseSelect)
{
  var sValue = getInputValue(sName, sFormName);
  setSelectOptions(sName+'_select', sFormName, aOptions, bLeaveExisting, bLabelSort, bAddPleaseSelect);
  setCodeSelectInputValue(sName, sValue, sFormName);
}

function getSelectInputText(sName, sFormName)
{
  var pSelect = getFormObject(sName, sFormName);
  if(pSelect)
    return pSelect.options[pSelect.selectedIndex].text;
  return '';
}

// used for input controls defined in HTML templates
function getSelectInputValue( inputName, formName, myDocument )
{
  var sValue;
  
  if(g_sHTMLTemplate)
  {
    var reObject = getRegExp('<!--OBJ_' + inputName + '-->.*<!--END_OBJ_' + inputName + '-->', 'm');
    var a = reObject.exec(g_sHTMLTemplate);
    if(a)
    {
      var sObject = a[0];
      if(sObject.indexOf('selected') >= 0)
      {
        reObject = getRegExp('<option(?:.*?)value="([^"]*)"(?:.*?)selected(?:.*?)>', 'm');
        a = reObject.exec(sObject);
        sValue = a ? a[1] : null;
      }
      else
      {
        reObject = getRegExp('<option(?:.*?)value="([^"]*)"(?:.*?)>', 'm');
        a = reObject.exec(sObject);
        sValue = a ? a[1] : null;
      }
    }
  }
  else
  {
    sValue = getInputValue( inputName, formName, myDocument );
  }
  
  return sValue;
}

function setSelectInputValue( inputName, value, formName, myDocument )
{
  if(!(value instanceof Array))
    value = new Array(String(value));
  var bFound = false;
  if(g_sHTMLTemplate)
  {
    var reObject = getRegExp('<!--OBJ_' + inputName + '-->.*<!--END_OBJ_' + inputName + '-->', 'm');
    var a = reObject.exec(g_sHTMLTemplate);
    if(a)
    {
      var sObject = a[0];
      // unselect
      // this regular expression can be slow, then test if it is realy needed
      if(sObject.indexOf('selected') >= 0)
        //sObject = sObject.replace(getRegExp('<option(.*?)value="(.*?)"(.*?)selected(.*?)>','gm'), '<option$1value="$2"$3>');
        sObject = sObject.replace(getRegExp('<option(.*?)selected(.*?)>','gm'), '<option$1$2>');
      // select
      for(var j=0;j<value.length;j++)
      {
        var sValue = value[j];
        var reSelect = getRegExp('<option(.*?)value="'+sValue+'"(.*?)>','g');
        if(reSelect.test(sObject))
        {
          sObject = sObject.replace(reSelect, '<option$1value="'+sValue+'" selected$2>');
          g_sHTMLTemplate = g_sHTMLTemplate.replace(reObject, sObject);
          bFound = true;
        }
      }
    }
  }
  else
  {
    var selectObj = formName ? getFormObject( inputName, formName, myDocument ) : getDOMObject( inputName, myDocument );
    if(selectObj)
    {
      if(selectObj.type == "select-multiple")
      {
        for( var i=0 ; i < selectObj.options.length ; i++ )
          selectObj.options[i].selected = false;
      }
      for(var j=0;j<value.length;j++)
      {
        var sValue = value[j];
        for( var i=0 ; i < selectObj.options.length ; i++ )
        {
          if( selectObj.options[ i ].value == sValue )
          {
            selectObj.options[ i ].selected = true;
            bFound = true;
          }
        }
      }
      if(!bFound && selectObj.options.length && selectObj.type != "select-multiple")
        selectObj.options[ 0 ].selected = true;
    }
  }
}

// la même que setSelectInputValue mais return FALSE ou TRUE.
function setSelectAndReturnInputValue( inputName, value, formName, myDocument )
{
  if(!(value instanceof Array))
    value = new Array(String(value));
  var bFound = false;
  if(g_sHTMLTemplate)
  {
    var reObject = getRegExp('<!--OBJ_' + inputName + '-->.*<!--END_OBJ_' + inputName + '-->', 'm');
    var a = reObject.exec(g_sHTMLTemplate);
    if(a)
    {
      var sObject = a[0];
      // unselect
      // this regular expression can be slow, then test if it is realy needed
      if(sObject.indexOf('selected') >= 0)
        //sObject = sObject.replace(getRegExp('<option(.*?)value="(.*?)"(.*?)selected(.*?)>','gm'), '<option$1value="$2"$3>');
        sObject = sObject.replace(getRegExp('<option(.*?)selected(.*?)>','gm'), '<option$1$2>');
      // select
      for(var j=0;j<value.length;j++)
      {
        var sValue = value[j];
        var reSelect = getRegExp('<option(.*?)value="'+sValue+'"(.*?)>','g');
        if(reSelect.test(sObject))
        {
          sObject = sObject.replace(reSelect, '<option$1value="'+sValue+'" selected$2>');
          g_sHTMLTemplate = g_sHTMLTemplate.replace(reObject, sObject);
          bFound = true;
        }
      }
    }
  }
  else
  {
    var selectObj = getFormObject( inputName, formName, myDocument );
    if(selectObj)
    {
      if(selectObj.type == "select-multiple")
      {
        for( var i=0 ; i < selectObj.options.length ; i++ )
          selectObj.options[i].selected = false;
      }
      for(var j=0;j<value.length;j++)
      {
        var sValue = value[j];
        for( var i=0 ; i < selectObj.options.length ; i++ )
        {
          if( selectObj.options[ i ].value == sValue )
          {
            selectObj.options[ i ].selected = true;
            bFound = true;
          }
        }
      }
      if(!bFound && selectObj.options.length && selectObj.type != "select-multiple")
        selectObj.options[ 0 ].selected = true;
    }
  }
  return bFound;
}

function setSelectOptions(sName, sFormName, aOptions, bLeaveExisting, bLabelSort, bAddPleaseSelect, pDocument)
{
  var sValue = getInputValue(sName, sFormName, pDocument);
  
  if(bLabelSort)
    aOptions.sort(sortSelectOptions);
  if(bAddPleaseSelect)
	  aOptions.unshift(new Option(getUserMessage('LANG_please_select'),''));
  if(g_sHTMLTemplate)
  {
    var re = getRegExp('<!--OBJ_' + sName + '--><select(.*?)>(.*)</select(.*?)><!--END_OBJ_' + sName + '-->', 'm');
    var sOptions = '';
    for(var i=0;i<aOptions.length;i++)
    {
      if(sValue == aOptions.value)
        sOptions += '<option value="'+aOptions[i].value+'" selected>'+aOptions[i].text+'</option>';
      else
        sOptions += '<option value="'+aOptions[i].value+'">'+aOptions[i].text+'</option>';
    }
    if(!bLeaveExisting)
      g_sHTMLTemplate = g_sHTMLTemplate.replace(re, '<!--OBJ_' + sName + '--><select$1>'+sOptions+'</select$3><!--END_OBJ_' + sName + '-->');
    else
      g_sHTMLTemplate = g_sHTMLTemplate.replace(re, '<!--OBJ_' + sName + '--><select$1>$2'+sOptions+'</select$3><!--END_OBJ_' + sName + '-->');
  }
  else
  {
    var pSelect = getFormObject(sName, sFormName, pDocument);
    if(pSelect)
    {
      if(!bLeaveExisting)
      {
        for(var i = pSelect.options.length-1;i >= 0;i--)
          pSelect.options[i] = null;
      }
      for(var i=0;i<aOptions.length;i++)
        pSelect.options[i] = aOptions[i];
    }
    setSelectInputValue(sName, sValue, sFormName, pDocument);
  }
}

function getSelectOptions(sName, sFormName, pDocument)
{
  var aOptions = new Array();
  if(g_sHTMLTemplate)
  {
    var re = getRegExp('<!--OBJ_' + sName + '--><select(.*?)>(.*?)</select(.*?)><!--END_OBJ_' + sName + '-->', 'm');
    var aRet = re.exec(g_sHTMLTemplate);
    if(aRet)
    {
      var sOptions = aRet[2];
      var aTextOptions = sOptions.split('<option');
      for(var i=0;i<aOptions.length;i++)
      {
        var sTextOption = aTextOptions[i];
        var reOption = getRegExp('.*?value="(.*?)".*?>(.*?)</option');
        aRet = reOption.exec(sTextOption);
        aOptions.push(new Option(aRet[2], aRet[1]));
      }
    }
  }
  else
  {
    var pSelect = getFormObject(sName, sFormName, pDocument);
    if(pSelect)
    {
      for(i=0;i<pSelect.length;i++)
        aOptions.push(new Option(pSelect.options[i].text, pSelect.options[i].value));
      //aOptions = pSelect.options;
    }
  }
  return aOptions;
}

function setMultipleSelectOptions(sName, sFormName, aOptions, bLeaveExisting, bFireEvents, bSort, bExtendedSort )
{
  if( bSort )
  {
    if( bExtendedSort )
    {
      g_sExtendedSortSelectName = sName;
      aOptions.sort(extendedSortSelectOptions);
    }
    else
      aOptions.sort(sortSelectOptions);
  }
  setSelectOptions(sName+'_available', sFormName, aOptions, bLeaveExisting);
  setSelectOptions(sName+'_selected', sFormName, new Array(), bLeaveExisting);
  updateMultipleSelectSelection( sName, sFormName, null, bFireEvents );
}

function isMultipleSelect(sName, sFormName, pDocument)
{
  var pObj = getFormObject(sName+'_selected', sFormName, pDocument);
  return pObj ? true : false;
}

function addMultipleSelectInputValue( sName, sValue, sFormName, pDocument )
{
  var aValues = new Array();

  var aSelectedOptions = getSelectOptions( sName+'_selected', sFormName, pDocument );
  // ca renvoie des objets HTML, pas des chaines, donc on doit les transformer
  if( aSelectedOptions && aSelectedOptions instanceof Array )
  {
    for ( var nI = 0; nI < aSelectedOptions.length; nI++ )
      aValues.push( aSelectedOptions[ nI ].value );
  }

  var aNewValues = sValue.split(',');
  for ( var nJ = 0; nJ < aNewValues.length; nJ++ )
    aValues.push( aNewValues[ nJ ] );

  setMultipleSelectInputValue( sName, aValues, sFormName, pDocument );
}

function setMultipleSelectInputValue( sName, aValue, sFormName, pDocument, bFireEvents )
{
  if(!(aValue instanceof Array))
  {
    aValue = new Array(aValue);
  }
  var aOptions = new Array();
  var hAvailableOptions = new Array();
  var aSelectedOptions = getSelectOptions(sName+'_selected', sFormName, pDocument);
  for(var i=0;i<aSelectedOptions.length;i++)
    hAvailableOptions[aSelectedOptions[i].value] = aSelectedOptions[i];
  var aAvailableOptions = getSelectOptions(sName+'_available', sFormName, pDocument);
  for(i=0;i<aAvailableOptions.length;i++)
    hAvailableOptions[aAvailableOptions[i].value] = aAvailableOptions[i];
  // select needed options
  var hSelectedOptions = new Array();
  for(i=0;i<aValue.length;i++)
  {
    if(!hSelectedOptions[aValue[i]] && hAvailableOptions[aValue[i]])
    {
      var aOption = hAvailableOptions[aValue[i]];
      hAvailableOptions[aValue[i]] = null;
      hSelectedOptions[aValue[i]] = aOption;
    }
  }
  // construct selected and available lists
  aSelectedOptions = new Array();
  for(i in hSelectedOptions)
    if(hSelectedOptions[i])
      aSelectedOptions.push(hSelectedOptions[i]);
  aAvailableOptions = new Array();
  for(i in hAvailableOptions)
    if(hAvailableOptions[i])
      aAvailableOptions.push(hAvailableOptions[i]);
  
  // apply changes
  setSelectOptions(sName+'_available', sFormName, aAvailableOptions, false, true, false, pDocument);
  setSelectOptions(sName+'_selected', sFormName, aSelectedOptions, false, true, false, pDocument);
  updateMultipleSelectSelection(sName, sFormName, pDocument, bFireEvents );
}

function getMultipleSelectInputValue(sName, sFormName)
{
  var sValue = getInputValue(sName, sFormName);
  return new String(sValue).split('|');
}

function getButtonInputValue( inputName, formName, myDocument )
{
	var pButton = getDOMObject(inputName,myDocument);
	if(pButton && pButton.style.display != 'none')
		return true;
	return false;
}

function setButtonInputValue( inputName, value, formName, myDocument )
{
  var sValue = value != 0 ? 'inline' : 'none';
  if(g_sHTMLTemplate)
  {
    updateInputObjectStyleTag(inputName, 'display', sValue);
  }
  else
  {
	  var pButton = getDOMObject(inputName,myDocument);
	  if(pButton)
			pButton.style.display = sValue;
	}
}

function setButtonListInputValue( inputName, value, formName, myDocument)
{
  if( value )
  {
    var aValues = value.split("|");
    for(var i=0;i<aValues.length;i++)
    {
      setButtonInputValue(inputName+'_'+i, aValues[i], formName, myDocument);
    }
  }
}

function setCodeTextInputValue( inputName, value, formName, myDocument )
{
  var aValues;
  if(!value)
  {
    aValues = new Array('','');
  }
  else
  {
	  aValues = value.split('|');
	}
	setInputValue(inputName,aValues[0],formName,myDocument);
	if(aValues[1])
		setInputValue(inputName+'_text',aValues[1],formName,myDocument);
	else
		setInputValue(inputName+'_text','',formName,myDocument);
}

function setDatetimeInputValue( inputName, value, formName, myDocument )
{
  var aValues;
  if(!value)
  {
    aValues = new Array('','');
  }
  else
  {
    aValues = value.split(' ');
  }
  setInputValue(inputName,aValues[0],formName,myDocument);
  if(aValues[1])
     setInputValue(inputName+'_time',aValues[1],formName,myDocument);
  else
     setInputValue(inputName+'_time','',formName,myDocument);
}

/*
  This function formats a decimal amount:
  0 - the number to be formatted
  1 - the number of decimals
*/
function formatDecAmount( number, dec, dontRAZ2Zero )
{
  if( number == null || number == '' )
  {
    if ( dontRAZ2Zero )
    {
      return number;
    }
    number = 0;
  }
  if( dec == null )
  {
    dec = 2;
  }

  var isNegativ = parseFloat( number ) < 0 ? true : false;
  number = Math.abs(number);

  var iNumber = parseInt( Math.round( parseFloat( number ) * Math.pow( 10, dec ) ) );
  number = new String( isNaN(iNumber) ? 0 : iNumber );

  var len = number.length;
  var b4dot = ( len <= dec ) ? '0' : number.substring( 0, len - dec );

  var afterdot = ( len < dec ) ? (new String( '0000000000' )).substring( 0, dec - len ) + number : number.substring( len - dec, len );

  if( afterdot )
  {
    return (isNegativ ? '-' : '') + b4dot + '.' + afterdot;
  }
  else
  {
    return (isNegativ ? '-' : '') + b4dot;
  }
}

function reformatInputAmountPercent(sValue)
{
  if(isPercent(sValue))
  {
    var nValue = 0;
    try
    {
      nValue = parseInputPercent(sValue);
    }
    catch(ex) {}
    return formatInputPercent(nValue);
  }
  else
  {
    var nValue = 0;
    try
    {
      nValue = parseInputPrice(sValue);
    }
    catch(ex) {}
    return formatInputPrice(nValue);
  }
}

function reformatInputPercent(sValue, bNullIfUndef, precision)
{
  if( !sValue && bNullIfUndef )
  {
    return sValue;
  }
  else
  {
    return formatInputPercent(parseInputPercent(sValue), precision);
  }
}

function reformatInputAvaibilityPercent(sValue)
{
  if(isPercent(sValue))
    return formatInputPercent(parseInputPercent(sValue));
  else
    return formatInputInteger(parseInputInteger(sValue));
}

function formatInputPercent(nAmount, precision)
{
  if( precision == null )
  {
    return formatDecAmount(nAmount, 2) + '%';
  }
  else
  {
    return formatDecAmount(nAmount, precision) + '%';
  }
}

function formatPrintedPercent(nAmount)
{
  return formatDecAmount(nAmount, 2) + ' %';
}

function formatFixedPercent(nAmount)
{
  return formatDecAmount(nAmount, 2) + '%';
}

function parseInputPercent(sValue)
{
  sValue = new String(sValue);
  if( sValue.match( /\%/ ) )
    sValue = sValue.replace( /\%/, '' );
  var nValue = 1*sValue;
  if(isNaN(sValue))
    throw new CheckerException('LANG_malformed_percent');
  return nValue;
}

function parseFixedPercent(sValue)
{
  sValue = new String(sValue);
  if( sValue.match( /\%/ ) )
    sValue = sValue.replace( /\%/, '' );
  var nValue = 1*sValue;
  if(isNaN(sValue))
    throw new CheckerException('LANG_malformed_percent');
  return nValue;
}

function isPercent(sValue)
{
  sValue = new String(sValue);
  return sValue.match( /\%/ );
}

function formatInputPrice(nAmount)
{
  return formatDecAmount(nAmount, 2);
}

function formatPrintedPrice(nAmount, bJS)
{
  return formatDecAmount(nAmount, 2) + (bJS ? " €" : " &euro;");
}

function formatFixedPrice(nAmount)
{
  return formatDecAmount(nAmount, 2);
}

function parseInputPrice(sValue)
{
  sValue = new String(sValue);
  sValue = sValue.replace( /\s/g, '' );
  
  var nValue = parseFloat(sValue);
  if(isNaN(sValue))
    throw new CheckerException('LANG_malformed_price');
  return nValue;
}

function parseFixedPrice(sValue)
{
  sValue = new String(sValue);
  sValue = sValue.replace( /\s/g, '' );
 
  var nValue = parseFloat(sValue);
  //var nValue = Math.round(parseFloat(sValue),2);
 
  if(isNaN(sValue))
    throw new CheckerException('LANG_malformed_price');
  return nValue;
}

function parseFieldPrice(sFieldName, sFormName, dDocument, bCatchEx)
{
  try
  {
    return parseInputPrice(getInputValue(sFieldName, sFormName, dDocument));
  }
  catch(ex)
  {
    if(ex instanceof CheckerException)
      ex.setFormField(sFieldName, sFormName);
    if(bCatchEx && ex.showUser)
      ex.showUser();
    else
      throw ex;   
  }
}

function formatInputHour(sHour)
{
  return sHour;
}

function formatFixedHour(sHour)
{
  return sHour;
}

function parseInputHour(sValue)
{
  sValue = new String(sValue);
  var re = /^(\d+)(\:(\d+))?$/;
  var aRes;
  if(!sValue || sValue == "")
    return "";
  aRes = re.exec(sValue);
  if(aRes)
  {
    // attention, il faut utiliser parseFloat car parseInt("02") renvoie "" dans IE, je ne sais pas pour les autres
    var nHours = parseFloat(aRes[1]);
    var nMinutes = aRes[3] ? parseFloat(aRes[3]) : 0;
    if(nHours >= 0 && nHours < 24 && nMinutes >= 0 && nMinutes < 60)
    {
      var sHours = nHours <= 9 ? '0'+nHours : ''+nHours;
      var sMinutes = nMinutes <= 9 ? '0'+nMinutes : ''+nMinutes;
      return sHours+':'+sMinutes;
    }
  }
  throw new CheckerException('LANG_malformed_hour');
}

function parseFixedHour(sValue)
{
  sValue = new String(sValue);
  return parseInputHour(sValue);
}

function parseFieldHour(sFieldName, sFormName, dDocument, bCatchEx)
{
  try
  {
    return parseInputHour(getInputValue(sFieldName, sFormName, dDocument));
  }
  catch(ex)
  {
    if(ex instanceof CheckerException)
      ex.setFormField(sFieldName, sFormName);
    if(bCatchEx && ex.showUser)
      ex.showUser();
    else
      throw ex;   
  }
}

function formatInputQuantity(nAmount)
{
  return formatDecAmount(nAmount, 2);
}

function parseInputQuantity(sValue)
{
  sValue = new String(sValue);
  var nValue = parseFloat(sValue);
  if(isNaN(nValue))
    throw new CheckerException('LANG_malformed_quantity');
  return nValue;
}

function parseFixedQuantity(sValue)
{
  sValue = new String(sValue);
  var nValue = parseFloat(sValue);
  if(isNaN(nValue))
    throw new CheckerException('LANG_malformed_quantity');
  return nValue;
}

function parseFieldQuantity(sFieldName, sFormName, dDocument, bCatchEx)
{
  try
  {
    return parseInputQuantity(getInputValue(sFieldName, sFormName, dDocument));
  }
  catch(ex)
  {
    if(ex instanceof CheckerException)
      ex.setFormField(sFieldName, sFormName);
    if(bCatchEx && ex.showUser)
      ex.showUser();
    else
      throw ex;   
  }
}

function formatInputInteger(sValue)
{
  return String(Math.round(sValue));
}

function parseInputInteger(sValue)
{
  sValue = new String(sValue);
  var nValue = parseInt(sValue);
  if(isNaN(nValue) || Math.round(sValue) != sValue)
    throw new CheckerException('LANG_malformed_integer');
  return nValue;
}

function parseFieldInteger(sFieldName, sFormName, dDocument, bCatchEx)
{
  try
  {
    return parseInputInteger(getInputValue(sFieldName, sFormName, dDocument));
  }
  catch(ex)
  {
    if(ex instanceof CheckerException)
      ex.setFormField(sFieldName, sFormName);
    if(bCatchEx && ex.showUser)
      ex.showUser();
    else
      throw ex;   
  }
}

function parseFixedInteger(sValue)
{
  sValue = new String(sValue);
  return Math.round(1*sValue);
}

function parseFixedAge(sValue)
{
  if(sValue == "")
    return null;
  sValue = new String(sValue);
  var nValue = parseFloat(sValue);
  if(isNaN(nValue))
    throw new CheckerException('LANG_malformed_age');
  return nValue;
}

function parseInputAge(sValue)
{
  return parseFixedAge(sValue);
}

function formatFixedAge(nAmount)
{
  if(nAmount === null)
    return '';
  return formatDecAmount(nAmount, 1);
}

function formatInputAge(nAmount)
{
  return formatFixedAge(nAmount);
}

function formatPrintedAge(nAmount)
{
  return formatFixedAge(nAmount);
}

function parseFieldDate(sFieldName, sFormName, dDocument, bCatchEx, bSelectInputType)
{
  try
  {
    if( bSelectInputType )
      return parseDate(getSelectInputText(sFieldName, sFormName));
    else
      return parseDate(getInputValue(sFieldName, sFormName, dDocument));
  }
  catch(ex)
  {
    if(ex instanceof CheckerException)
      ex.setFormField(sFieldName, sFormName);
    if(bCatchEx && ex.showUser)
      ex.showUser();
    else
      throw ex;   
  }
}

function trim(s)
{
    return s.replace(/^\s+/g,'').replace(/\s+$/g,'');
} 

function parseFieldDateTime(sFieldName, sFormName, dDocument, bCatchEx)
{
  try
  {
    var pDate = parseDate(getInputValue(sFieldName, sFormName, dDocument));
    var sTime = getInputValue(sFieldName+'_time', sFormName, dDocument);
    var sTime = trim(sTime);
    var aTimeValues = sTime.split(/:/);
    if( aTimeValues[0] )
      pDate.setHours(aTimeValues[0]);
    if( aTimeValues[1] )
      pDate.setMinutes(aTimeValues[1]);
    return pDate;
  }
  catch(ex)
  {
    if(ex instanceof CheckerException)
      ex.setFormField(sFieldName, sFormName);
    if(bCatchEx && ex.showUser)
      ex.showUser();
    else
      throw ex;   
  }
}

function parseFieldCCNumber(sFieldName, sFormName, dDocument, sFormat)
{
  var sCCNum = getInputValue(sFieldName, sFormName, dDocument);
  if( sCCNum != "" )
  {
    if( new String(sCCNum).match( textFormats[ sFormat ] ) == null )
      throw new CheckerException('LANG_invalid_credit_card_number', null, sFieldName, sFormName, dDocument);
  }
  return sCCNum;
}

function parseField( sValue, sTextFormat, sLanguageVar )
{
  sValue = new String( sValue );
  if( sValue.match( textFormats[ sTextFormat ] ) == null )
    throw new CheckerException( sLanguageVar );
  else
    return 1;
}

function formatHTMLString(sString)
{
  sString = sString.replace(/\n/, '<br>');
  return sString;
}

function setHiddenLabelInputValue( inputName, value, formName, myDocument )
{
  // if value is an array, it contains html attributes to apply to span object
  if(value instanceof Array)
  {
    var sProperty;
    for(sProperty in value)
    {
      if(sProperty != "value")
      {
        setDOMObjectProperty(inputName, sProperty, value[sProperty], myDocument);
      }
    }
  }
  // get value
  var sValue = value instanceof Array ? value.value : value;
  // set value
  setInputValue( inputName, sValue, formName, myDocument );
  if(g_sHTMLTemplate && g_sHTMLTemplate != "")
  {
    g_sHTMLTemplate = g_sHTMLTemplate.replace(getRegExp('<span id="'+inputName+'_layer"(.*?)>.*<\\/span>','m'),'<span id="'+inputName+'_layer"$1>'+sValue+'</span>');
  }
  else
  {
    var pLayer = getLayer( inputName + '_layer' );
    if(pLayer && pLayer.innerHTML != sValue )
      pLayer.innerHTML = sValue;
  }
}

function setHiddenLabelProperty(sName, sFormName, sProperty, sValue, pDocument)
{
  setFormObjectProperty(sName, sFormName, sProperty, sValue, pDocument);
  setDOMObjectProperty(sName+'_layer', sProperty, sValue, pDocument);
}

function setLabelInputValue( inputName, value, formName, myDocument )
{
  // if value is an array, it contains html attributes to apply to span object
  if(value instanceof Array)
  {
    var sProperty;
    for(sProperty in value)
    {
      if(sProperty != "value")
      {
        setDOMObjectProperty(inputName, sProperty, value[sProperty], pDocument);
      }
    }
  }
  // get value
  var sValue = value instanceof Array ? value.value : value;
  if(g_sHTMLTemplate && g_sHTMLTemplate != "")
  {
    g_sHTMLTemplate = g_sHTMLTemplate.replace(getRegExp('<span id="'+inputName+'"(.*?)>.*<\\/span>','m'),'<span id="'+inputName+'"$1>'+sValue+'</span>');
  }
  else
  {
    var pLayer = getLayer( inputName );
    if(pLayer && pLayer.innerHTML != sValue )
      pLayer.innerHTML = sValue;
  }
}

g_sSelectedTab = '';

/**
 * Associated with tab object.
 * Used to change tab state.
 */
function activateTab(sTabsName,sTabID,bManageLayers)
{
  if ( getBrowser() == NETSCAPE )
    setDOMObjectProperty('globalcontent', 'style.display', 'none');

  try
  {
    if(g_sSelectedTab && g_sSelectedTab != sTabID && aTabsActions && aTabsActions[sTabsName] && aTabsActions[sTabsName][g_sSelectedTab]['onUnSelected'])
    {
      var f = new Function(aTabsActions[sTabsName][g_sSelectedTab]['onUnSelected']);
      if(f() === false)
        return;
    }
  
    var aLayers = Array();
    // get all layer names using tab names
    var oTabs = document.getElementById(sTabsName);
    if(oTabs.style.display == 'none')
      oTabs.style.display = 'block';
    aLayers = aTabsElements[sTabsName];
    for(var i=0;i<aLayers.length;i++)
    {
      // unactivate tab
      var oTabL = document.getElementById('tab_left_' + aLayers[i]);
      var oTabC = document.getElementById('tab_center_' + aLayers[i]);
      var oTabR = document.getElementById('tab_right_' + aLayers[i]);
  
      if(oTabL != undefined && oTabC != undefined && oTabR != undefined)
      {
        oTabL.src = aSmallTabsImages[0].src;
  //      oTabC.background = aSmallTabsImages[1].src;
        oTabC.style.backgroundImage = "url("+aSmallTabsImages[1].src+")";
        oTabR.src = aSmallTabsImages[2].src;
      }
      // hide layer
      if(bManageLayers)
        hideLayer(aLayers[i]);
    }
  
    // activate tab
    var oTabL = document.getElementById('tab_left_' + sTabID);
    var oTabC = document.getElementById('tab_center_' + sTabID);
    var oTabR = document.getElementById('tab_right_' + sTabID);
    if(oTabL != undefined && oTabC != undefined && oTabR != undefined)
    {
      oTabL.src = aLargeTabsImages[0].src;
  //    oTabC.background = aLargeTabsImages[1].src;
      oTabC.style.backgroundImage = "url("+aLargeTabsImages[1].src+")";
      oTabR.src = aLargeTabsImages[2].src;
    }
  
    // show layer
    if(bManageLayers)
      showLayer(sTabID);
  
    var sOldSelectedTab = g_sSelectedTab;
    g_sSelectedTab = sTabID;
    if(sOldSelectedTab != sTabID && aTabsActions && aTabsActions[sTabsName] && aTabsActions[sTabsName][sTabID]['onSelected'])
    {
      var f = new Function(aTabsActions[sTabsName][sTabID]['onSelected']);
      f();
    }
  }
  catch( pException )
  {
    throw pException;
  }
  finally
  {
    if ( getBrowser() == NETSCAPE )
      setDOMObjectProperty('globalcontent', 'style.display', '');
  }
}

function isTabSelected(sTab)
{
  return g_sSelectedTab == sTab;
}

function updateRooms( inputName, formName, startInputName, endInputName, blockInputName )
{
  emptyAllOptions( inputName, formName );

  var a = remoteCall( 'custom::remote::room_search',
                      getInputValue( 'campaign', formName ),
                      getInputValue( 'etab', formName ),
                      getInputValue( startInputName, formName ),
                      getInputValue( endInputName, formName ),
                      getInputValue( blockInputName, formName ),
                      getInputValue( 'block_type', formName ) );

  if( a == null )
  {
    return;
  }

  var obj = getFormObject( inputName, formName );
  for( var i = 0 ; i < a.length ; i++ )
  {
    obj.options[ i ] = new Option( a[ i ][ 1 ], a[ i ][ 0 ] );
    obj.options[ i ].style.backgroundColor = a[ i ][ 2 ];
  }
}

function updateAssignRooms( inputName, formName, startInputName, endInputName, assignInputName )
{
  emptyAllOptions( inputName, formName );

  var a = remoteCall( 'custom::remote::room_assign_search',
                      getInputValue( 'stay_id', formName ),
                      getInputValue( startInputName, formName ),
                      getInputValue( endInputName, formName ),
                      getInputValue( assignInputName, formName ) );

  if( a == null )
  {
    return;
  }

  var obj = getFormObject( inputName, formName );
  for( var i = 0 ; i < a.length ; i++ )
  {
    obj.options[ i ] = new Option( a[ i ][ 1 ], a[ i ][ 0 ] );
    obj.options[ i ].style.backgroundColor = a[ i ][ 2 ];
  }
}


function moveMultipleSelectLeft( sName, sFormName, bSorted, bExtendedSort, bNoFireEvents )
{
    var pAvailableMultipleSelect = getFormObject(sName+'_available', sFormName);
    var pSelectedMultipleSelect = getFormObject(sName+'_selected', sFormName);

  if(pSelectedMultipleSelect.selectedIndex == -1)
    return;
   var aSelectedOptions =  new Array();
    pAvailableMultipleSelect.selectedIndex = -1;


    var selectedDisplayedColumns = new Array();
    var aIdx = 0;
    var i;
    for ( i=0 ; i < pSelectedMultipleSelect.length; i++ )
    {
       if ( pSelectedMultipleSelect.options[i].selected )
       {
          //check if column can be made unavailable
          if ( !pSelectedMultipleSelect.options[i].text.match(/^\(\*\).*/) )
          {
             selectedDisplayedColumns[aIdx++] = i;
          }
       }
    }
    var aAvailableOptions = new Array();
    for(var i=0;i<pAvailableMultipleSelect.options.length;i++)
      aAvailableOptions.push(pAvailableMultipleSelect.options[i]);
  
    for ( i=0 ; i < selectedDisplayedColumns.length; i++ )
    {
      var pOption = new Option( pSelectedMultipleSelect.options[ selectedDisplayedColumns[i] ].text,
                                                            pSelectedMultipleSelect.options[ selectedDisplayedColumns[i] ].value );
       pOption.selected = true;
       aAvailableOptions.push( pOption );
    }
    if(bSorted)
    {
      if( bExtendedSort )
      {
        g_sExtendedSortSelectName = sName;
        aAvailableOptions.sort(extendedSortSelectOptions);
      }
      else
        aAvailableOptions.sort(sortSelectOptions);
    }
    
    setSelectOptions(sName+'_available', sFormName, aAvailableOptions);

    for ( i=0; i < selectedDisplayedColumns.length; i++ )
    {
       pSelectedMultipleSelect.options[ selectedDisplayedColumns[i] ] = null;
       for ( j=i; j < selectedDisplayedColumns.length; j++ )
       {
           selectedDisplayedColumns[j]--;
       }
    }
    
    updateMultipleSelectSelection( sName, sFormName, null, !bNoFireEvents ); // active onchange par defaut
}

function sortSelectOptions(a,b)
{
  if(a.text == b.text)
    return 0;
  if(a.text > b.text)
    return 1;
  return -1;
}

var g_sExtendedSortSelectName;

function moveMultipleSelectRight( sName, sFormName, bSorted, bExtendedSort, bNoFireEvents )
{
    var pAvailableMultipleSelect = getFormObject(sName+'_available', sFormName);
    var pSelectedMultipleSelect = getFormObject(sName+'_selected', sFormName);

  if(pAvailableMultipleSelect.selectedIndex == -1)
    return;
  pSelectedMultipleSelect.selectedIndex = -1;
   var selectedAvailableColumns = new Array();
   var aIdx = 0;
   var i;
   for ( i=0; i < pAvailableMultipleSelect.length; i++ )
   {
      if ( pAvailableMultipleSelect.options[i].selected )
      {
         selectedAvailableColumns[aIdx++] = i;
      }
   }
   
    var aSelectedOptions = new Array();
    for(var i=0;i<pSelectedMultipleSelect.options.length;i++)
      aSelectedOptions.push(pSelectedMultipleSelect.options[i]);
   
   for ( i=0; i < selectedAvailableColumns.length; i++ )
   {
      var pOption = new Option( pAvailableMultipleSelect.options[ selectedAvailableColumns[i] ].text,
                                                           pAvailableMultipleSelect.options[ selectedAvailableColumns[i] ].value );
      pOption.selected = true;
      aSelectedOptions.push( pOption );
   }
   for ( i=0; i < selectedAvailableColumns.length; i++ )
   {
      pAvailableMultipleSelect.options[ selectedAvailableColumns[i] ] = null;
      for ( j=i; j < selectedAvailableColumns.length; j++ )
      {
         selectedAvailableColumns[j]--;
      }
   }
    if(bSorted)
    {
      if( bExtendedSort )
      {
        g_sExtendedSortSelectName = sName;
        aSelectedOptions.sort(extendedSortSelectOptions);
      }
      else
        aSelectedOptions.sort(sortSelectOptions);
    }
    
    setSelectOptions(sName+'_selected', sFormName, aSelectedOptions);

   updateMultipleSelectSelection(sName, sFormName, null, !bNoFireEvents);
}

function moveMultipleSelectUp( sName, sFormName, bFireEvents )
{
    var pAvailableMultipleSelect = getFormObject(sName+'_available', sFormName);
    var pSelectedMultipleSelect = getFormObject(sName+'_selected', sFormName);

    var i;
    for ( i = 1; i < pSelectedMultipleSelect.length; i++ )
    {
        if ( pSelectedMultipleSelect.options[i].selected )
        {
            var option = new Option( pSelectedMultipleSelect.options[ i-1 ].text,
                                     pSelectedMultipleSelect.options[ i-1 ].value );
            pSelectedMultipleSelect.options[i-1] = new Option( pSelectedMultipleSelect.options[ i ].text,
                                                                 pSelectedMultipleSelect.options[ i ].value );
            pSelectedMultipleSelect.options[i-1].selected = true;
            pSelectedMultipleSelect.options[i] = option;
        }
    }

    updateMultipleSelectSelection( sName, sFormName, null, bFireEvents ); // pas d'evenement par defaut
}

function moveMultipleSelectDown( sName, sFormName, bFireEvents )
{
    var pAvailableMultipleSelect = getFormObject(sName+'_available', sFormName);
    var pSelectedMultipleSelect = getFormObject(sName+'_selected', sFormName);
    
    var i;
    for ( i = pSelectedMultipleSelect.length-2; i >= 0; i-- )
    {
        if ( pSelectedMultipleSelect.options[i].selected )
        {
            var option = new Option( pSelectedMultipleSelect.options[ i+1 ].text,
                                     pSelectedMultipleSelect.options[ i+1 ].value );
            pSelectedMultipleSelect.options[i+1] = new Option( pSelectedMultipleSelect.options[ i ].text,
                                                                 pSelectedMultipleSelect.options[ i ].value );
            pSelectedMultipleSelect.options[i+1].selected = true;
            pSelectedMultipleSelect.options[i] = option;
        }
    }

    updateMultipleSelectSelection( sName, sFormName, null, bFireEvents ); // pas d'evenement par defaut
}

function updateMultipleSelectSelection( sName, sFormName, pDocument, bFireEvents )
{
  var pSelectedMultipleSelect = getFormObject(sName+'_selected', sFormName, pDocument);
  if(!pSelectedMultipleSelect) return false;

  var aValue = new Array();

  for ( var i = 0; i < pSelectedMultipleSelect.length; i++ )
  {
    aValue.push(pSelectedMultipleSelect.options[i].value);
  }

  setInputValue(sName, aValue.join('|'), sFormName, pDocument);
  
  if( bFireEvents )
    fireOnChangeEvent( getFormObject( sName, sFormName, pDocument ) );
  
  updateColorListBox(sName, sFormName, pDocument);
  
  return true;
}

function updateColorListBox( sName, sFormName, pDocument)
{
//  var aOptionStyles = eval( "pDocument." + sName + "_styles" );

  var pSelectedMultipleSelect = getFormObject(sName+'_selected', sFormName, pDocument);
  if(!pSelectedMultipleSelect) return false;

  var pAvailableMultipleSelect = getFormObject(sName+'_available', sFormName, pDocument);  
  if(!pAvailableMultipleSelect) return false;

  //var pColorListe = eval( "pDocument." + sName + "_colorlist" );
  var pColorListe = getFormObject(sName+'_colorlist', sFormName, pDocument);  
  if(!pColorListe) return false;
  
  if(pColorListe.value != 'nocolor')
  {
    for ( var i = 0; i < pSelectedMultipleSelect.length; i++ )
    {
      if(pSelectedMultipleSelect.options[i].value == pColorListe.value)
        pSelectedMultipleSelect.options[i].style.backgroundColor = '#00FF00';
    }
  
    for ( var i = 0; i < pAvailableMultipleSelect.length; i++ )
    {
      if(pAvailableMultipleSelect.options[i].value == pColorListe.value)
        pAvailableMultipleSelect.options[i].style.backgroundColor = '#00FF00';
    }
  }  
  return true;
}

function extendedSortSelectOptions(a,b)
{
  if(g_MultipleSelectExtSort[g_sExtendedSortSelectName][a.value] == g_MultipleSelectExtSort[g_sExtendedSortSelectName][b.value])
    return 0;
  if(g_MultipleSelectExtSort[g_sExtendedSortSelectName][a.value] > g_MultipleSelectExtSort[g_sExtendedSortSelectName][b.value])
    return 1;
  return -1;
}

function updateDynamicPeriodCodes(sName, sCampInputName, sEtabInputName, sFormName)
{
  // on recherche le num etab et le num camp
  var sCampCode = getInputValue( sCampInputName, sFormName );
  var nEtabID = getInputValue( sEtabInputName, sFormName );
  // interogation serveur pour la liste des périodes
  var aOptions = new Array();
  try
  {
     var sPeriodsXML = remoteCall(
                         'custom::remote::periods',
                         'getPeriods',
                         sCampCode,
                         nEtabID);
     var dDoc = XmlUtils_getXMLDOM(sPeriodsXML);
     var xmlePeriods = XmlUtils_getChildElements(dDoc.documentElement, "period");
     g_MultipleSelectExtSort[sName] = new Array();
     for(var i=0;i<xmlePeriods.length;i++)
     {
        var pPeriod = new Period().fromXMLElement(xmlePeriods[i]);
        aOptions.push(new Option(pPeriod.getLabel(), pPeriod.getCode()))
        g_MultipleSelectExtSort[sName][pPeriod.getCode()] = datesDayDiff(pPeriod.getStartDate(), new Date(0))+'.'+datesDayDiff(pPeriod.getEndDate(), new Date(0));
     }
  }
  catch(ex)
  {
     if(ex.showUser)
        ex.showUser();
     else
        throw ex;
  }
  // update periods combo
  setMultipleSelectOptions(sName, sFormName, aOptions, false);
}

function updateEtabObsType( sName, sType, sFormName )
{
  if( sType == 0 ) // phrase auto pour une plage de date
  {
    showLayer( 'date_layer' );
    hideLayer( 'periods_layer' );
    enableInputChecker( sName+"_start_date" );
    enableInputChecker( sName+"_end_date" );
    disableInputChecker( sName+"_etab_obs_periods" );
  }
  else // phrase auto pour une période de vente
  {
    hideLayer( 'date_layer' );
    showLayer( 'periods_layer' );
    disableInputChecker( sName+"_start_date" );
    disableInputChecker( sName+"_end_date" );
    enableInputChecker( sName+"_etab_obs_periods" );
  }
}

function setCustomerLookupInputValue(sName, sValue, sFormName)
{
  var aValues;

  if(!sValue)
  {
    aValues = new Array('','');
    sValue = '';
  }
  else
  {
    aValues = sValue.split('|');
  }

  var oldValue = getInputValue(sName, sFormName).split('|')[0]; // ok?

  if ( aValues[0] != oldValue )
  {
      setCodeTextInputValue(sName + '_code', aValues[0], sFormName);
      customerLookupFindCustomer(sName, sFormName);
      aValues[1] = 0;
  }

  if ( aValues[0] != '' && aValues[1] != '' )
  {
//      setCodeSelectInputValue(sName + '_service', aValues[1], sFormName);
      setInputValue(sName + '_service', aValues[1], sFormName);
      setInputValue(sName + '_service_select', aValues[1], sFormName);
  }

  var sCode    = getInputValue(sName + '_code', sFormName);
  var sService = getInputValue(sName + '_service', sFormName);
  if ( sCode == '' )
      sValue = '';
  else
      sValue = sCode + "|" + sService;

  setInputValue(sName, sValue, sFormName);
}

function customerLookupOpenLookup(sName, sFormName, nCustomerType, nEtabID)
{
  var sURL = g_sCustomerLookupLink + "&formName=" + sFormName + "&fieldName=" + sName + "&etab_id=" + nEtabID;
  if(nCustomerType)
    sURL += "&customer_file_ids="+nCustomerType;
  var sCustomerCode = modal(sURL,'_blank', 'directories=no,fullscreen=no,height=600,location=no,menubar=no,resizable=yes,scrollbars=yes,status=no,toolbar=no,width=800');
  if ( sCustomerCode )
      setCustomerLookupInputValue(sName, sCustomerCode, sFormName);
}

function customerLookupFindCustomer(sName, sFormName)
{
  var sCode = getInputValue(sName + '_code', sFormName);
  try
  {
    if ( sCode != '' )
    {
      var aRes = remoteCall('custom::remote::reservation::customer',sCode);
      // if customer valid
      if(aRes)
      {
        // ok, customer found, get needed customer information
        var xmldDoc = XmlUtils_getXMLDOM(aRes);
        var pCustomer = new Customer().fromXMLElement(xmldDoc.documentElement);
        setInputValue(sName + '_code_text', pCustomer.getName(), sFormName);
        var aTmpServices = pCustomer.getServices();
        var aServices = new Array();
        // on n'affiche que le service n°0 pour les propriétaires
        if( aTmpServices != null && pCustomer.getClientTypeCode() == CLIENT_TYPE_PROPRI )
        {
          for( var i = 0 ; i < aTmpServices.length ; i++ )
          {
            var pService = aTmpServices[i];
            if( pService.getID() == 0 )
              aServices.push( pService );
          }
        }
        else
        {
          aServices = aTmpServices;
        }
        customerLookupSetServices(aServices, sName, sFormName);
        
        return;
      }
    }

    setInputValue(sName + '_code', null, sFormName);
    setInputValue(sName + '_code_text', null, sFormName);
    setInputValue(sName + '_service', null, sFormName);
    setInputValue(sName + '_service_select', null, sFormName);
    setSelectOptions(sName+'_service_select', sFormName, new Array(), false, false, false);
    setFormObjectProperty(sName+'_service', sFormName, "disabled", true);
    setFormObjectProperty(sName+'_service_select', sFormName, "disabled", true);
  }
  catch(ex)
  {
    if(ex instanceof CheckerException)
      ex.showUser();
    else
      throw ex;
  }
}

function customerLookupSetServices(aServices, sName, sFormName)
{
  var aOptions = new Array();
  for(var i = 0; i<aServices.length; i++)
  {
    aOptions.push(new Option(aServices[i].getName(), aServices[i].getID()));
  }

//  setCodeSelectInputValue(sName + '_service', aServices[0].getID(), sFormName);
  setInputValue(sName + '_service', aServices[0].getID(), sFormName);
  setInputValue(sName + '_service_select', aServices[0].getID(), sFormName);

  setSelectOptions(sName+'_service_select', sFormName, aOptions, false, false, false);
  setFormObjectProperty(sName+'_service', sFormName, "disabled", false);
  setFormObjectProperty(sName+'_service_select', sFormName, "disabled", false);
}

function customerLookupUpdateValue(sName, sFormName)
{
  var sCode    = getInputValue(sName + '_code', sFormName);
  var sService = getInputValue(sName + '_service', sFormName);

  setCustomerLookupInputValue(sName, sCode + '|' + sService, sFormName);
}


function updateNbDaysBefore(isDays)
{
  if(isDays > 0)
  {
    setDOMObjectProperty("nb_days_layer", "style.display", "");
    setDOMObjectProperty("date_layer", "style.display", "none");
  }
  else
  {
    setDOMObjectProperty("nb_days_layer", "style.display", "none");
    setDOMObjectProperty("date_layer", "style.display", "");
  }
}


/**
 * Appelé lors du changement de code client
 */
function updateAccountLookupValue( sName, sFormName, pDocument )
{
  // met a jour la liste des comptes disponibles pour ce client
  updateAccountLookupAccountList( sName, sFormName, pDocument );
  // met a jour le solde du compte
  updateAccountLookupBalanceAmount( sName, sFormName, pDocument );
}

/**
 * Appelé lors du choix d'un compte client par l'intérmédiaire du lookup
 */
function setAccountLookupInputValue( sName, nAccountID, sFormName, pDocument  )
{
  // met a jour la liste des comptes disponibles pour ce client
  updateAccountLookupAccountList( sName, sFormName, pDocument, nAccountID );
  // met a jour le solde et le client du compte
  updateAccountLookupBalanceAmount( sName, sFormName, pDocument);
}

/**
 * Met a jour le solde du compte client
 */
function updateAccountLookupBalanceAmount(sName, sFormName, pDocument)
{
  var pMessageLayer = getDOMObject( sName + '_message', pDocument );
  var nAccountID = getInputValue(sName, sFormName, pDocument);
  if( pMessageLayer && nAccountID > 0) 
  {
    var sBalance;
    // j'appel le serveur pour obtenir les informations sur ce compte
    var sCustomerCodeAndNum = findCustomerCodeAndService( nAccountID )
    if( sCustomerCodeAndNum )
    {
      var aValues = sCustomerCodeAndNum.split('|');
      var sCustomerCode = aValues[0];
      var nServiceID = aValues[1];
      sBalance = aValues[2];
    }

    // affichage du montant du compte
    pMessageLayer.innerHTML = getUserMessage('LANG_balance_field') + sBalance;
    setInputValue(sName+'_code', sCustomerCode, sFormName);
  }
  else
  {
    setInputValue(sName+'_code', '', sFormName);
    pMessageLayer.innerHTML = getUserMessage('LANG_balance_field') + "-";
  }
}

/**
 * Met a jour la liste des comptes de ce client
 * La mise a jour s'effectue
 *  - soit à partir de l'id de compte passé en paramètre (il a été sélectionné via le lookup)
 *  - soit à partir du code client
 */
function updateAccountLookupAccountList(sName, sFormName, pDocument, nAccountID)
{
  var pAccountSelect = getFormObject(sName, sFormName, pDocument);
  var sCustomerCode = getInputValue(sName + '_code', sFormName, pDocument);
  var aAccountOptions = new Array();
  var sCustomerName = "";
  try
  {
    if ( nAccountID > 0 || sCustomerCode != '' )
    {
      var sXMLRet = nAccountID > 0  ? remoteCall('custom::remote::account', 'findAccountsFromID', nAccountID) :
                                      remoteCall('custom::remote::account', 'findAccounts', sCustomerCode );
      if( sXMLRet )
      {
        var pXMLDoc = XmlUtils_getXMLDOM( sXMLRet );
        var pXMLRoot = pXMLDoc.documentElement;
  
        var pAccountElement = XmlUtils_getElementByTagName(pXMLDoc, 'accounts');
        sCustomerName = XmlUtils_getAttributeValue(pAccountElement, 'customer_name');
        sCustomerCode = XmlUtils_getAttributeValue(pAccountElement, 'customer_code');
        
        var aAccountsElements = XmlUtils_findChildrenFromCollTagName(pXMLDoc, 'accounts', 'account');
        for( var nI=0; nI < aAccountsElements.length; nI++ )
        {
          var pAccountEle = aAccountsElements.item(nI);
          var nID = XmlUtils_getElementTextByTagName(pAccountEle, 'id');
          var sAccountLabel = XmlUtils_getElementTextByTagName(pAccountEle, 'name');
          aAccountOptions.push( createSelectOption(nID, sAccountLabel, pDocument) );
        }
      }
    }
  }
  catch(ex)
  {
    if(ex instanceof CheckerException)
      ex.showUser();
    else
      throw ex;
  }
  if( aAccountOptions.length == 0 )
    aAccountOptions.push( createSelectOption(0, getUserMessage('LANG_customer_account_no_account'), pDocument) );
  setSelectOptions( sName, sFormName, aAccountOptions, false, false, false, pDocument);

  // on initialise le compte sur celui passé en param
  //  ou sur le premier de la liste
  if( aAccountOptions.length > 0)
    setSelectInputValue(sName, nAccountID > 0 ? nAccountID : aAccountOptions[0].value, sFormName, pDocument);
    
  setInputValue( sName + '_code_text', sCustomerName, sFormName, pDocument );        
  setInputValue( sName + '_code', sCustomerCode, sFormName, pDocument );        
}

function updateOwnerRoomList(sName, sFormName, nEtabID, sOwnerCustomerCode, nOwnerServiceID, sMultipleSelectName)
{
  try
  {
    var sXMLRet = remoteCall('custom::remote::rooms', 'getRooms', null, nEtabID);
    if( sXMLRet )
    {
      var pXMLDoc = XmlUtils_getXMLDOM( sXMLRet );
      var aRoomElements = XmlUtils_findChildrenFromCollTagName( pXMLDoc, 'rooms', 'room' );
      var aOptions = new Array();
      var aMultipleSelectOptions = new Array();
      for(var i=0;i<aRoomElements.length;i++)
      {
        var pRoom = new Room().fromXMLElement(aRoomElements.item(i));
        aOptions.push(new Option(pRoom.getNumber()+': '+pRoom.getName(), pRoom.getNumber()));
        if( sMultipleSelectName )
          aMultipleSelectOptions.push(new Option(pRoom.getNumber()+': '+pRoom.getName(), pRoom.getNumber()));
      }
      setSelectOptions(sName, sFormName, aOptions);
      if( sMultipleSelectName )
        setMultipleSelectOptions(sMultipleSelectName, sFormName, aMultipleSelectOptions);
    }
  }
  catch(ex)
  {
    if(ex instanceof CheckerException)
      ex.showUser();
    else
      throw ex;
  }
}

function findCustomerCodeAndService( nAccountID )
{
  try
  {
    if ( nAccountID != '' )
    {
      var sRet = remoteCall('custom::remote::account', 'findCustomerByAccount', nAccountID );
      if( sRet )
      {
        return sRet;
      }
    }
  }
  catch(ex)
  {
    if(ex instanceof CheckerException)
      ex.showUser();
    else
      throw ex;
  }
  return null;
}

function openAccountLookupPopup(sName, sFormName, sPaymentModeFieldName )
{
  var sURL = g_sAccountLookupLink;

  var nPaymentMode = sPaymentModeFieldName ? getInputValue( sPaymentModeFieldName, sFormName ) : '';
  if( nPaymentMode != '' && pConfig )
  {
    var nCustomerAccountPaymentMode = pConfig.getVarValue( 'customer_account_payment_mode' );
    var nPartnerAccountPaymentMode  = pConfig.getVarValue( 'partner_account_payment_mode' );
    
    if( nCustomerAccountPaymentMode != nPartnerAccountPaymentMode &&
        ( nPaymentMode == nCustomerAccountPaymentMode ||
          nPaymentMode == nPartnerAccountPaymentMode ) )
    {
      if( nPaymentMode == nCustomerAccountPaymentMode )
        nAccountType = INDIVIDUAL_ACCOUNT;
      else if( nPaymentMode == nPartnerAccountPaymentMode )
        nAccountType = PARTNER_ACCOUNT;

      sURL = sURL.replace( /ACCOUNT_TYPE/g, nAccountType );
    }
  }

  var nAccountID = modal(sURL + "&formName=" + sFormName + "&fieldName=" + sName,'_blank', 'directories=no,fullscreen=no,height=600,location=no,menubar=no,resizable=yes,scrollbars=yes,status=no,toolbar=no,width=800');

  if ( nAccountID )
    setAccountLookupInputValue( sName, nAccountID, sFormName );
}

function getDateComboValue( sName, sFormName )
{
  var nDay   = getInputValue( sName + '_f_day', sFormName );
  var nMonth = getInputValue( sName + '_f_month', sFormName );
  var nYear  = getInputValue( sName + '_f_year', sFormName );

  var pDate;
  
  if( nDay && nMonth && nYear )
    pDate = new Date( nYear, nMonth-1, nDay );
  
  return pDate;
}

function setDateComboValue( sName, pDate, sFormName )
{
  if( pDate )
  {
    var nDay   = pDate.getDate();
    var nMonth = pDate.getMonth()+1;
    var nYear  = pDate.getYear();

    setInputValue( sName + '_f_day', nDay, sFormName );
    setInputValue( sName + '_f_month', nMonth, sFormName );
    setInputValue( sName + '_f_year', nYear, sFormName );
  }
}

function updateOwnerPaymentdueDatesList( sName, sFormName, sCustomerCode, nServiceID, nEtabID )
{
  try
  {
    var sXML = remoteCall('custom::remote::customer::owner_paymentdue_dates', sCustomerCode, nServiceID, nEtabID );
    if( sXML )
    {
      var pXMLDoc = XmlUtils_getXMLDOM( sXML );
      var aNodes = XmlUtils_findChildrenFromCollTagName( pXMLDoc, "owner_paymentdue_dates", "paymentdue_date" );
      var aOptions = new Array();
      if( aNodes.length )
      {
        for(var i=0;i<aNodes.length;i++)
        {
          aOptions.push(new Option(XmlUtils_getElementTextByTagName(aNodes.item(i), "label"),
                                   XmlUtils_getElementTextByTagName(aNodes.item(i), "value")));
        }
      }
      else
      {
        aOptions.push(new Option(getUserMessage('LANG_no_next_owner_paymentdue_date'),""));
      }
      setSelectOptions(sName, sFormName, aOptions);
    }
  }
  catch(ex)
  {
    if(ex.showUser)
      ex.showUser();
    else
      throw ex;
  }
  
}

/**
 * Pour les tableaux scrollables avec les headers fixés,
 * cette fonction initialise les couches (div) avec les headers fix.
 */
function initHeaderDiv(bRowHeader, nNbHeaderRows)
{
  if( getBrowser() == NETSCAPE )
  {
    var pMasterDiv = getDOMObject("master_div");
    pMasterDiv.style.width="";
    pMasterDiv.style.height="";
    pMasterDiv.style.overflow="auto";
  }
  else
  {
    if( nNbHeaderRows > 0)
    {
      // 
      var pMasterDiv = getDOMObject("master_div");
      var pHeaderDiv = getDOMObject(bRowHeader ? "row_header_div" : "col_header_div");
      pHeaderDiv.style.display = '';
      
      // maintenant les divs sont directement mis en place dans la page HTML,
      //  bonne compression globalement le fichier fait 10%) et surtout pas de bloquage
      //  côté client.
      //pHeaderDiv.innerHTML = pMasterDiv.innerHTML;
      if( bRowHeader )
        pHeaderDiv.style.height = pMasterDiv.clientHeight;
      else
        pHeaderDiv.style.width = pMasterDiv.clientWidth;
      pHeaderDiv.style.left = findPosX(pMasterDiv, pHeaderDiv.offsetParent);
      pHeaderDiv.style.top = findPosY(pMasterDiv, pHeaderDiv.offsetParent);
  
      var pSrcTable = pMasterDiv.getElementsByTagName("table")[0];
      var pTable = pHeaderDiv.getElementsByTagName("table")[0];
      // pour les titres de ligne, on fixe la largeur de la pseudo table.
      //  sinon, IE essaie de comprimer la table pour la faire tenir dans l'espace horizontal restreint
      if( bRowHeader )
        pTable.style.tableLayout = "fixed";
      // parcour de la pseudo table
      var aRows = pTable.rows;
      var nWidth = 0;
      var nHeight = 0;
      var iMax = aRows.length;
      for(var i=0;i<iMax;i++)
      {
        // pour les titre de ligne
        //  on cache tout le le contenu de la table, et on note la taille des
        //  titres de ligne dans la table de référence
        if( bRowHeader )
        {
          aCells = aRows[i].cells;
          var jMax = aCells.length;
          for(var j=0;j<jMax;j++)
          {
            if( j>nNbHeaderRows-1 )
            {
               aCells[j].style.visibility = 'hidden';
            }
            else if( i==0 )
            {
               nWidth += pSrcTable.rows[i].cells[j].clientWidth;
               // on recopie la taille de cellule de la table de référence
               aCells[j].style.width = pSrcTable.rows[i].cells[j].clientWidth;
            }
          }
        }
        else
        {
          if( i>nNbHeaderRows -1 )
          {
             aCells = aRows[i].cells;
             for(var j=0;j<aCells.length;j++)
             {
                aCells[j].style.visibility = 'hidden';
             }
          }
          else
          {
             nHeight += 1*aRows[i].clientHeight+1;
          }
        }
      }
     if( bRowHeader )
        pHeaderDiv.style.width = nWidth;
      else
        pHeaderDiv.style.height = nHeight;
    }
  }
}

function clearDBFile(sName, sFormName, nFileID)
{
  try
  {
    if( confirmUserMessage('LANG_confirm_remove_odtfile') )
    {
      var bSuccess = remoteCall("custom::remote::db_file_remote",
                   "clearDBFile",
                   nFileID);
      if ( bSuccess )
      {
        alert(LANG_odtfile_delete_success);
        var pImage = getDOMObject( nFileID );
        pImage.src = pImage.inverseImageURL;
      }
      else{
        alert(LANG_odtfile_delete_failure);
      }
    }
  }
  catch(ex)
  {
    if(ex.showUser)
      ex.showUser();
    else
      throw ex;
  }
}

// dans la programmation d'envoi de traitement :
// pour MAJ des vues en fonction du listParam sélectionné
function getSharedViews( sListParamName )
{
  try
  {
    var aViews = remoteCall( "custom::remote::document_schedule",
                 "getSharedViews",
                 sListParamName );
    
    return aViews;
  }
  catch(ex)
  {
    if(ex.showUser)
      ex.showUser();
    else
      throw ex;
  }
}

function checkOwnerPeriodInputRoomNumbers(sInputFieldName, sFormName)
{
  var bMultiple = getInputValue('multiple_rooms', sFormName);
  if( bMultiple )
  {
    var aRoomNumbers = getInputValue( 'owner_room_numbers', sFormName);
    if( !aRoomNumbers || aRoomNumbers.length <= 0 )
    {
      showUserMessage('LANG_please_choose_a_or_multiple_rooms');
      return false;
    }
  }
  else
  {
    var sRoomNumber = getInputValue( 'owner_room_number', sFormName);
    if( !sRoomNumber )
    {
      showUserMessage('LANG_room_number_cannot_be_empty');
      return false;
    }
  }
  return true;
}

function showHideOwnerPeriodRoomLayers(sFormName)
{
  var bMultiple = getInputValue('multiple_rooms', sFormName);
  if( bMultiple )
  {
    showLayer('multiple_room_layer');
    hideLayer('simple_room_layer');
  }
  else
  {
    showLayer('simple_room_layer');
    hideLayer('multiple_room_layer');
  }
}


function setLinks( aLinksToUpdate, regExp, sReplaceString )
{
  for (i = 0; i < aLinksToUpdate.length; i++)
  {
    var pLink = aLinksToUpdate[i];
    var oldLink = new String ( pLink.href );
    pLink.href = oldLink.replace( regExp, sReplaceString );
  }
}

function updateTreatmentTemplateSenderMailState()
{
  var pText = getFormObject('trt_email_sender', 'listparam_form');
  var pCheck = getFormObject('trt_fl_email_sender_etab', 'listparam_form');
  if( pText )
  {
    if( pCheck && pCheck.checked )
      pText.disabled = true;
    else
      pText.disabled = false;
  }
}

function updateCityFromZipCode( pZip, sForm, sCity)
{
  var ZipLength=5;
  var pCity=getFormObject( sCity,  sForm);
  var sZip;
  var sRetCity;
  
  if(pZip && pCity)
  {
    sZip=getObjectValue(pZip);
    if(sZip)
    {
      var osZip=new String(sZip).replace(' ','');
      if(osZip.length==ZipLength)
      {
        try
        {
          sRetCity = remoteCall( "custom::remote::address",
                   "getCityFromZip",
                   osZip );
          if(sRetCity)
          {
            if(sRetCity!='')
              setObjectValue(pCity,sRetCity);
          }
        }
        catch(ex)
        {
          if(ex.showUser)
            ex.showUser();
          else
            throw ex;
        }
      }
    }
  }
}

function updateCitiesFromZipCode( pZip, sForm, sCity, sFormName)
{
  var ZipLength=5;
  var pCity=getFormObject( sCity,  sForm);
  var sLayerName = sFormName+'_layer_city';
  var sZip;
  var sRetCity;
  var sTableLink;
  var aCities = new Array();
  
  if(pZip && pCity)
  {
    sZip=getObjectValue(pZip);
    if(sZip)
    {
      var osZip=new String(sZip).replace(' ','');
      if(osZip.length==ZipLength)
      {
        try
        {
          sRetCity = remoteCall( "custom::remote::address",
                   "getCitiesFromZip",
                   osZip );
          if(sRetCity)
          {
            if(sRetCity != '')
            {
              aCities = sRetCity.split("|");
              if(aCities.length == 1 )
              {
                setObjectValue(pCity,sRetCity);
                //to do :cacher le lien layer
                hideLayer(sLayerName);
              }
              else
              {
                //to do construire les liens villes
                setObjectValue(pCity,'');
                
                var i = 0;
                sTableLink = getUserMessage('LANG_please_choose_a_city') + "<br><br>";
                while( i < aCities.length) 
                {
                  sTableLink += "<div style=\"float: left; width: 160px;\"><a href=\"javascript:updateCityField( '"+sCity+"', '"+aCities[i]+"', '"+sForm+"', '"+sLayerName+"');\">" + aCities[i] + "</a></div>";
                  i++;
                  if( i % 5 == 0 )
                  {
                    sTableLink += "<br>";
                  }
                }
                
                var pLayer = getLayer(sLayerName);
                // initialisation du contenu de la layer
                pLayer.innerHTML = sTableLink;
                // positionnement
                moveLayerToElement(pLayer, pCity, true);
                // on affiche la layer
                showLayer(sLayerName);
              }
            }
          }
        }
        catch(ex)
        {
          if(ex.showUser)
            ex.showUser();
          else
            throw ex;
        }
      }
    }
  }
}

function updateCityField(sCity, sLibCity, sForm, sLayerName)
{
  var pCity=getFormObject( sCity,  sForm);
  setObjectValue(pCity,sLibCity);
  pCity.onchange();
  hideLayer(sLayerName);
}

function updateTPVClientList(sName, sFormName, nEtabID)
{
  try
  {
    var sXMLRet = remoteCall('custom::remote::tpv', 'getTPVServices', nEtabID);
    if( sXMLRet )
    {
      var pXMLDoc = XmlUtils_getXMLDOM( sXMLRet );
      var aServiceElements = XmlUtils_findChildrenFromCollTagName( pXMLDoc, 'services', 'service' );
      var aOptions = new Array();
      for(var i=0;i<aServiceElements.length;i++)
      {
        var pService = new Service().fromXMLElement(aServiceElements.item(i));
        aOptions.push(new Option(pService.getLastname(), pService.getCustomerCode()+'|'+pService.getID()));
      }
      setSelectOptions(sName, sFormName, aOptions);
    }
  }
  catch(ex)
  {
    if(ex instanceof CheckerException)
      ex.showUser();
    else
      throw ex;
  }
}

function updateInputRoomTypeList(sName, sFormName, nEtabID)
{
  try
  {
    var sXMLRet = remoteCall('custom::remote::room_types', 'getAllTypes', nEtabID);
    if( sXMLRet )
    {
      var pXMLDoc = XmlUtils_getXMLDOM( sXMLRet );
      var aRoomTypeElements = XmlUtils_findChildrenFromCollTagName( pXMLDoc, 'room_types', 'roomtype' );
      var aOptions = new Array();
      var aMultipleSelectOptions = new Array();
      for(var i=0;i<aRoomTypeElements.length;i++)
      {
        var pRoomType = new RoomType().fromXMLElement(aRoomTypeElements.item(i));
        aOptions.push(new Option(pRoomType.getLabel(), pRoomType.getCode()));
      }
      setSelectOptions(sName, sFormName, aOptions);
    }
  }
  catch(ex)
  {
    if(ex instanceof CheckerException)
      ex.showUser();
    else
      throw ex;
  }
}

// remplit les variables de langue dans la popup à partir du champ hidden de la règle de promo
function extractLanguageVariable( sEncodedValue, nLanguageID )
{
  var reObject = getRegExp(nLanguageID+':(.*?);', 'm');
  var a = reObject.exec(sEncodedValue);
  return a ? decodeURIComponent(a[1]) : '';
}


// remplit les variables de langue dans la popup à partir du champ hidden de la règle de promo
function extractLanguageVariable( sEncodedValue, nLanguageID )
{
  var reObject = getRegExp(nLanguageID+':(.*?);', 'm');
  var a = reObject.exec(sEncodedValue);
  return a ? decodeURIComponent(a[1]) : '';
}


