// Fonctions de contrôle pour la saisie sur formulaire
// Nécessite form.js

////////////////////////////////////////////////////////////////////////////////
// Objet date
date.prototype.display = function () 
{
   if ( this.dval != null )
   {

      var year = this.dval.getFullYear();
      //if ( year < 2000) 
        //year = year + 1900;
    
      var day = this.dval.getDate();
      if ( day <10)
        day = "0"+day;
      var month = this.dval.getMonth()+1;
      if (month <10)
        month = "0"+month;
      this.ddisp.value=day + "/" + month + "/" + year; 
   }
   else
   {
      this.ddisp.value = "";
   }   
}
//
date.prototype.getISO = function () 
{
   if (this.dval != null) 
   {
      var year = this.dval.getYear();
      if ( year < 2000)
         year = year + 1900;
      var day = this.dval.getDate();
      if ( day <10)
         day = "0"+day;
      var month = this.dval.getMonth()+1;
      if (month <10)
         month = "0"+month;
      return year + "" + month + "" + day;
   }
   else
   {
      return "";
   }     
}
//
date.prototype.clear = function ()
{ 
  this.ddisp.value = "";
}
date.prototype.setDate = function (realDateISO)
{
   var annee = realDateISO.substring(0,4);
   var mois = realDateISO.substring(4,6);
   var jour = realDateISO.substring(6,8);
   if (jour && annee && mois)
   {
       var dateJJMMAAAA = jour+"/"+mois+"/"+annee;
       this.ddisp.value = dateJJMMAAAA;
   }
   else
   {
       this.ddisp.value = "";
   }
}
//
date.prototype.refresh = function (mess) 
{
   var val=0;
   var ok = 0;
   var flag = 0;
   
   if ( (this.ddisp.value == "") && (! this.required) )
   {
      // SAU 07.10.2005 : Prise en compte de la suppression 
      // du contenu de la zone de saisie.
      this.dval = null;
      return true;
   }
   var dateObj = DateUtil_guessDate(this.ddisp.value.trim());
   if ( ! dateObj )
   {
      if (mess) { alert (mess_control_date); }
      this.ddisp.focus(); 
      return false;
   }
   this.dval = dateObj;
   this.display(); 
return true; 
}
//
date.prototype.copy = function (dateSrc) 
{
    this.dval.setTime(dateSrc.dval.getTime());
    this.display(); 
}

date.prototype.getdiff = function (dateMax) 
{
   return (dateMax.dval.getTime()-this.dval.getTime())/86400000;
}

date.prototype.addDays = function(nbdays) 
{
  if (!this.refresh(true)) return;
  this.dval.setTime(this.dval.getTime()+nbdays*86400000);
  this.display();
}

date.prototype.addYears = function(nbdays) 
{
  if (!this.refresh(true)) return;
  this.dval.setTime(this.dval.getTime()+nbdays*86400000*(365.25));
  this.display();
}

date.prototype.setToday = function ()
{
  this.dval = new Date();
  this.display();
}
date.prototype.setTime = function(time)
{
  this.dval.setTime(time); 
}

date.prototype.getTime = function()
{
  return this.dval.getTime(); 
}

date.prototype.setFocus = function()
{
   if ( this.ddisp != null )
      this.ddisp.focus();
}

function date (disp, required)
{
 this.dval=null;
 if (disp!=null) 
 {
    if (disp.value != "") {  this.dval=new Date(disp.value); }
 }
 // 23.08.2005 : SAU si pas de valeur saisie dans le champ
 // On ne prend pas en compte la date courante par défaut
 //if (this.dval==null)
 //  this.dval=new Date();
 this.ddisp=disp;
 this.required = (required == null) ? false : ((required==1)?true:false);
 return this;
}
////////////////////////////////////////////////////////////////////////////////
// Objet Field
// path est un chemin de type frameName.formName.fieldName
// tdn 28/06/2006 Si à ce chemin correspond plusieurs nom de champ un message
// d'erreur est affiché. On peut passer path=frameName et inputId= id de l'élément
// input HTML/
function Field(path, inputId)
{
   this.path = path;
   var parts = path.split(".");
   if ( parts.length != 3 && inputId == null)
   {
      alert("Bad use of Field object : path=" + path + " inputId=" + inputId + "\n" +
      	"Path must be 'frameName.formName.fieldName', or path='frameName' and inputId is not null");
      return null;
   }
   this.frameName = parts[0];
   this.formName  = parts[1];
   this.elemName  = parts[2];
   
   var frame = findFrameWithinApp(this.frameName);
   if ( frame )
   {
      // L'id est spécifié, on le recherche en priorité
      if ( inputId != null )
      {
         var elem = frame.document.getElementById(inputId);
         if ( elem != null )
         {
            this.frame = frame;
            this.form  = elem.form;
            this.element = elem;
         }
         else
         {
            alert(mess_field_not_found + this.elemName + " id=" + inputId);
         }
         return;
      }
      var form = frame.document.forms[this.formName];
      if ( form )
      {
         for (var i=0; i<form.elements.length; i++)
         {
         	var elem = form.elements[i];
         	if ( elem.name == this.elemName )
         	{
         	   if ( this.element )
         	   {
         	      alert("There are several input elements with name " + this.elemName);
         	      return;
         	   }
               this.frame = frame;
               this.form  = form;
               this.element = elem;
         	}
         }//for
         if ( this.element )
         { 
            return;
         }
         else
         {
            alert(mess_field_not_found + this.elemName);
         }
      }
      else
      {
         alert(mess_form_not_found + this.frameName + "." + this.formName);
      }
   }
   else
   {
      alert(mess_frame_not_found + this.frameName);
   }
}
// Renvoie le nom de la frame
Field.prototype.getFrameName = function ()
{
   return this.frameName;
}
// Renvoie la frame
Field.prototype.getFrame = function ()
{
   return this.frame;
}
// Renvoie le nom du formulaire
Field.prototype.getFormName = function ()
{
   return this.formName;
}
// Renvoie le nom de l'élément
Field.prototype.getElementName = function ()
{
   return this.elemName;
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

// Selectionne toutes les valeurs sauf emptyValue (vaut "0" par défaut)
function inputSelectAllOptions(formName, listeName, emptyValue)
{
   var liste = frmCheckField(formName, listeName);
   if ( liste && liste.options )
   {
      if ( emptyValue == null ) emptyValue = "0";
      for (i=0; i<liste.options.length; i++)
      {
         if (liste.options[i].value != emptyValue)
         {
            liste.options[i].selected = true;
         }
      }
      
      // sau 16.08.2008 : Cas 656 / Saisie champ lié multivalué via inputgrid / 
      // Non prise en compte de la suppression du dernier lien de la liste.
      // ==> S'il n'y a pas d'option dans la liste, on rajoute une option vide, 
      // pour permettre de vider le champ
      if ( liste.options.length == 0 )
      {
         // Option vide, sélectionnée
         var opt = new Option("","");
         opt.selected = true;   
         
         // Ajoute l'option
         liste.options[0] = opt;
      }
   }
}

// Supprime un élément d'un tableau
function deleteElement(array, delindex)
{
   var size = array.length;
   var validNo = (delindex != "NaN");
   var inRange = ( (delindex >= 0) && (delindex < size) );

   if (validNo && inRange)
   {
      if(array.remove)
      {
         // méthode propre à IE
         array.remove(delindex);
      }
      else
      {
         // pour les autres navigateurs
         for(var j = delindex; j < size-1; j++)
         {      
            array[j] = array[j+1];
         }
         array.length = size-1;
      }
   }
}

// Supprime un élément d'un tableau d'options
// On ne pas utiliser deleteElement qui ne fonctionne pas
// correctement sous Mozilla
function deleteListOption(array, delindex)
{
   var size = array.length;
   var validNo = (delindex != "NaN");
   var inRange = ( (delindex >= 0) && (delindex < size) );

   if (validNo && inRange)
   {
      if(array.remove)
      {
         // méthode propre à IE
         array.remove(delindex);
      }
      else
      {
         // pour les autres navigateurs
         for(var j = delindex; j < size-1; j++)
         {      
            array[j].value = array[j+1].value;
            array[j].text  = array[j+1].text;
            array[j].title  = array[j+1].title //cma 20-07-2011, correction bug#20682
            array[j].selected = array[j+1].selected;
         }
         array.length = size-1;
      }
   }
}

// Permet de supprimer des éléments contenus dans une liste
// tdn 29/06/2006 : le recherche par son id si spécifie, sinon par le nom
function inputRemoveSelectedOptions(formName, fieldName, fieldId)
{
   var elt = frmCheckField( formName, fieldName, fieldId)
   if ( elt && elt.options )
   {
      listRemoveSelectedOptions(elt);
   }
}
function listRemoveSelectedOptions(elt)
{    
   var len    = elt.options.length;
   for (var i=len-1; i >= 0; i--)
   {
      if (elt.options[i].selected)
      {
         deleteListOption(elt.options, i);
      }
   }
}

// Supprime toutes les options d'une liste
function listRemoveAllOptions(elt)
{
   listRemoveAllOptionFrom(elt,0); 
}

/**
 * Supprime toutes les options d'un select ayant un index >= fromIndex
 * @param {Select} elt select contenant les options
 * @param {int} fromIndex Index de la première option supprimée
 */
function listRemoveAllOptionFrom(elt,fromIndex)
{
   for (var i=elt.options.length; i >=fromIndex; i--)
   {
      deleteElement(elt.options, i);
   } 
}

/**
 * Déplace les options sélectionnées d'un select source à la fin de la liste des
 * options d'un select destinataire
 * Si l'option de vérification de l'unicté des valeurs dans la liste destinataire
 * est active alors les doublons ne sont pas déplacés vers la liste destinataire
 * @author sau
 */
function listMoveToListSelectedOption(formName, listSourceName, listSourceId, listDestName, listDestId, checkUnicity)
{
   var hasNotMovedSeletedOption = false;
   
   // Liste source 
   var listSource = frmCheckField(formName, listSourceName, listSourceId);
   if ( listSource == null )
      return;

   var listDest = frmCheckField(formName, listDestName, listDestId);
   if ( listDest == null )
      return;
      
   // Vérifie qu'un élément est sélectionné dans la liste source
   if ( listSource.options.selectedIndex >= 0 )
   {
      // Non déplacement des élements déjà présents dans la liste destinataire
      var listDestValues = new Array();
      if ( checkUnicity )
      {
         for (var j=0; j< listDest.options.length; j++)
         {
            listDestValues[listDest.options[j].value] = true;
         }
      }   
   
      // Recopie dans la liste destinataire la ou les sélections.
      for (var i = 0; i < listSource.options.length;  i++)
      {
         if ( listSource.options[i].selected )
         {
            if (    checkUnicity 
                &&  listDestValues[listSource.options[i].value] )
            {
                hasNotMovedSeletedOption = true;       
                continue;
            }    
            
            var opt = new Option(listSource.options[i].text,listSource.options[i].value);
            var title = listSource.options[i].title;
            if (    title != null 
                &&  title.length > 0)
               opt.setAttribute("title", listSource.options[i].title);
            
            // Ajoute l'option à la fin de la liste destinataire
            listDest.options[listDest.options.length] = opt;
            
            // Ajoute la valeur à la liste destinataire
            listDestValues[listSource.options[i].value] = true;
            
            // Supprime l'option de la liste source
            deleteListOption(listSource.options, i);
            // ==> Suite à suppression, l'option suivante à le même indice
            i--;           
         }
      }
   }
   else
   {
      // Aucun élément n'est sélectionné dans la liste !
      alert(sysGetMessage("input.list.no.selected.option"));
   }
   
   if ( hasNotMovedSeletedOption )
   {
      // Certains éléments déjà présents dans la liste destinataire n'ont pas été déplacés
      var key = "input.list.some.items.were.already.in.the.target.list.and.have.not.been.moved";         
      alert(sysGetMessage(key));
   }
}

/**
 * Déplace d'une position vers le HAUT les options sélectionnées d'un select
 * Après déplacement les éléments restent sélectionnés.
 * @author sau
 */
function listMoveUpSelectedOption(formName, listId, listName)
{
   var moveUp = true;
   listMoveUpOrDownSelectedOption(formName, listId, listName, moveUp);
}

/**
 * Déplace d'une position vers le BAS les options sélectionnées d'un select
 * Après déplacement les éléments restent sélectionnés.
 * @author sau
 */
function listMoveDownSelectedOption(formName, listId, listName)
{
   var moveUp = false;
   listMoveUpOrDownSelectedOption(formName, listId, listName, moveUp);
}

/**
 * Déplace d'une position vers le haut les options sélectionnées d'un select
 * Après déplacement les éléments restent sélectionnés.
 * @author sau
 */
function listMoveUpOrDownSelectedOption(formName, listId, listName, moveUp)
{
   // Liste 
   var list = frmCheckField(formName, listName, listId);
   if ( list == null )
      return;

   // Vérifie qu'un élément est sélectionné dans la liste
   if (    list.options != null
       &&  list.options.selectedIndex >= 0 )
   {  
      var len = list.options.length;
      
      // Descendre
      // ==> On parcours les options dans l'ordre d'indice décroissant
      var incIndex = 1;
      var startIndex = len - 1;
      
      // Monter 
      // ==> On parcours les options dans l'ordre d'indice croissant
      if ( moveUp )
      {
         incIndex = -1;
         startIndex = 0
      }   
      
      var cpt = len;
      for ( var i = startIndex; cpt > 0; i-=incIndex ) 
      {
         cpt--;
         if ( list.options[i].selected )
         {
            if ( moveUp )
            {
               // On ne peut pas monter de 1 l'option d'indice 0
               if ( i == 0 )
                  return;
            }
            else
            {      
               // On ne peut pas descendre de 1 la dernière option
               if ( i == (len - 1) )     
                  return;
            }      

            var optToMove = list.options[i];
            var opt       = list.options[i + incIndex];
            
            list.options[i]            = new Option("", "");
            list.options[i + incIndex] = optToMove;
            list.options[i]            = opt;
         }
      }   
   }
   else
   {
      // Aucun élément n'est sélectionné dans la liste !
      alert(sysGetMessage("input.list.no.selected.option"));
   }
}

// Vide un champ lié monovalué
function inputEmptyLinkField(formName, fieldName)
{
   var elt = frmCheckField( formName, fieldName)
   if ( elt )
      elt.value = "";
   elt = frmCheckField( formName, fieldName + "_EVERDISP")
   if ( elt )
      elt.value = "";
}

//
//
function isANumber (str)
{
   if ( str == "" ) return true;
   var num = parseFloat(str);
   return  ! isNaN(num);
/*   
   for (var i=0; i<str.length; i++){
       var n = parseInt(str.charAt(i));
       if (isNaN(n)) { return false; }
 }
return true;
*/
}
function toNumber(str)
{  
   // sau 30.03.2007 : parseFloat prend uniquement la partie entière 
   // si le séparateur est la virgule !!
   if (    str != null
       &&  str != undefined
       &&  str.length > 0 ) 
      str = str.replace(/\,/, '.');
   
   var num = parseFloat(str);
   if (isNaN(num)) return 0;
   return num;
}


// Contrôle le nombre de sélection max dans une liste
function inputControlListMultiple(frmName, field_name, no_msg, field_label, multi_maxi)
{
   var fld_msg = field_name;
   if ( field_label != '' )
   {
     fld_msg = field_label;
   }
   var elt = frmCheckField(frmName, field_name);
   if ( elt && elt.options )
   {
      var nb_selected = 0;
      for (var j=0; j< elt.options.length; j++)
      {
         if (elt.options[j].selected ) { nb_selected ++; }
      }
      if ( nb_selected > multi_maxi )
      {
         if ( ! no_msg) 
         { 
            alert(mess_control_liste_multi + " " + fld_msg + "\n" + mess_control_liste_multi2 + " " + multi_maxi);
            elt.focus();
         }
         return false;
      }
      return true;
   }
   return false;
}

//
function inputControlDecimal(formName, fieldName, fieldLabel, precision)
{
   var isDecimal = false;
   var value = "";
   var field;
   var formulaire = document.forms[formName];

   if ( ! formulaire )
   {
      alert(mess_form_not_found + formName);
      return false;
   }
   
   // Récupération de la valeur saisie
   for (var i=0;i<formulaire.elements.length;i++)
   {
      var elt = formulaire.elements[i];
      var elt_type = elt.type;
      if (elt.name == fieldName)
      {
         field = elt;
         if ( (elt_type == 'text') || (elt_type == 'hidden') || (elt_type == 'select-one')) //cma - ajout de elt_type == 'select-one'  
         {																					//pour prendre le type "select-one" en considerasion 
            value = elt.value;
            break;
         }
      }
   }
   var showErrorMessage = true;
   isDecimal = inputCtrlDecimal(value, showErrorMessage, fieldLabel);
   
   if ( isDecimal )
   {
      // Application de l'arrondi à precision décimales   
      field.value = getDataCtrlDecimal(value, precision)
   }   
   else   
   {
      // Le nbre saisi n'est pas un décimal
      // On positionne le focus dans la zone de saisie
      field.focus();
      return false;
   }
   return true;  
}

// Applique le contrôle ean_isbn
function inputControlEanIsbn(formName, fieldName, fieldLabel, audibleAlert)
{
   var isDecimal = false;
   var value = "";
   var field;
   var formulaire = document.forms[formName];

   if ( ! formulaire )
   {
      alert(mess_form_not_found + formName);
      return false;
   }
   
   // Récupération de la valeur saisie
   for (var i=0;i<formulaire.elements.length;i++)
   {
      var elt = formulaire.elements[i];
      var elt_type = elt.type;
      if (elt.name == fieldName)
      {
         field = elt;
         if ( (elt_type == 'text') || (elt_type == 'hidden') )
         {
            value = elt.value;
            break;
         }
      }
   }
   var showMessage = true;
   var formatedValue=null;
   var data = inputCtrlEanIsbn(value, showMessage, fieldLabel, audibleAlert);
   if(data!=null)
   {
      formatedValue = data.formatedValue;
   }
   if ( formatedValue == null )
     formatedValue = "";
   
   // Formatage éventuel de la valeur saisie
   field.value = formatedValue;
   
   // On renvoie tjrs true, car le ctrl n'est pas bloquant
   return true;
}

function inputControlDateFormat15(formName, field_name, mess)
{
   var value = "";
   var field;
   var formulaire = document.forms[formName];

   if ( ! formulaire )
   {
      alert(mess_form_not_found + formName);
      return false;
   }
   
   for (var i=0;i<formulaire.elements.length;i++)
   {
      var elt = formulaire.elements[i];
      var elt_type = elt.type;
      if (elt.name == field_name)
      {
         field = elt;
         if ( (elt_type == 'text') || (elt_type == 'hidden') )
         {
            value = elt.value;
            break;
         }
         else if ( (elt_type == 'checkbox') || (elt_type == 'radio') )
         {
            value = elt.value;
         }
         else if ( (elt_type == 'select-one') || (elt_type == 'select-multiple') )
         {
            for (var j=0; j< elt.options.length; j++)
            {
               if (elt.options[j].selected)
               {
                  value = elt.options[j].value;
               }
            }
         }
      }
   }
   if ( ! isANumber(value) )
   {
      alert(mess_control_integer);
      field.focus();
      return false;
   }
   if (value.length != 4)
   {
      alert(mess_control_date_format_15);
      field.focus();
      return false;  
   }
   return true;
}


//
function inputControlInteger(formName, field_name, fieldLabel)
{
   var value = "";
   var field;
   var formulaire = document.forms[formName];

   if ( ! formulaire )
   {
      alert(mess_form_not_found + formName);
      return false;
   }
   
   for (var i=0;i<formulaire.elements.length;i++)
   {
      var elt = formulaire.elements[i];
      var elt_type = elt.type;
      if (elt.name == field_name)
      {
         field = elt;
         if ( (elt_type == 'text') || (elt_type == 'hidden') )
         {
            value = elt.value;
            break;
         }
         else if ( (elt_type == 'checkbox') || (elt_type == 'radio') )
         {
            value = elt.value;
         }
         else if ( (elt_type == 'select-one') || (elt_type == 'select-multiple') )
         {
            for (var j=0; j< elt.options.length; j++)
            {
               if (elt.options[j].selected)
               {
                  value = elt.options[j].value;
               }
            }
         }
      }
   }

   var showMessage = true;
   if ( ! inputCtrlInteger(value, showMessage, fieldLabel) )
   {
      field.focus();
      return false;
   }
   return true;
}

//
function inputControlLenMin(formName, fieldName, len, fieldId)
{
   var elt = frmCheckField(formName, fieldName, fieldId);
   if ( elt )
   {
      if ( elt.value == "") return true;
      if ( elt.value.length >= len ) return true;
      var f0 = mess_control_lenmin;
      alert(f0 + " [" + len + "]");
      elt.focus();
   }
   return false;
}

//
function inputControlScript(formName, fieldName, fieldId, fieldLabel, script, audibleAlert)
{
   var elt = frmCheckField(formName, fieldName, fieldId);
   if ( elt )
   {  
      var showMessage = true;
      return inputCtrlExecuteScript(elt.value, showMessage, script, fieldLabel, audibleAlert)
   }
   return false;
}

//
function inputControlValMax(formName, fieldName, val)
{
   var elt = frmCheckField(formName, fieldName);
   if ( elt )
   {
      // Pas de valeur saisie 
      if (elt.value == "" )
         return true;
         
      if (elt.value <= val )
         return true;
      var f0 = mess_control_valmax;
      alert(f0 + " [" + val + "]");
      elt.focus();
   }
   return false;
}

//
function inputControlValMin(formName, fieldName, val)
{
   var elt = frmCheckField(formName, fieldName);
   if ( elt )
   {
      // Pas de valeur saisie 
      if (elt.value == "" )
         return true;

      if (elt.value >= val )
         return true;
      var f0 = mess_control_valmin;
      alert(f0 + " [" + val + "]");
      elt.focus();
   }
   return false;
}

//
function inputControlMajus(formName, fieldName)
{
   var elt = frmCheckField(formName, fieldName);
   if ( elt )
   {
      elt.value = elt.value.toUpperCase();
   }
}

//
function inputControlMinus(formName, fieldName)
{
   var elt = frmCheckField(formName, fieldName);
   if ( elt )
   {
      elt.value = elt.value.toLowerCase();
   }
}

/**
 * @author pru: ajoute le champ timeField si le champ time et requis
 * il est simplement concaténé a la date
 */
function inputSetDateISO(frmName, dateObj, fieldName,timeFieldId)
{
   var dateField = frmCheckField(frmName, fieldName);
   
   
   var timeValue = null;
   if(timeFieldId!=null)
   {
      var fieldTime = document.getElementById(timeFieldId);
      if(fieldTime!=null)
         timeValue= fieldTime.value;
   }
   
   if ( dateField )
   {
      dateField.value = dateObj.getISO();
      if(timeValue!=null)
         dateField.value+=timeValue;
   }
}

// Ouvre la fenêtre assistant de saisie
// tableName peut être au format source.nomTable
// ** tdn 04/11/2005 fieldFrom est au format : sourceOrig:tableOrig:fieldOrig pour appliquer
// sql_command
// ** sau 10/01/2006 : ajout de la variable filter pour appliquerle contrôle 
// sql_command du type sql_command=NOM_CHAMP_NOTICE_AUTORITE=$NOM_CHAMP_FORMULAIRE$
// avec $NOM_CHAMP_FORMULAIRE$ est remplacé par la valeur du champ NOM_CHAMP_FORMULAIRE,
// présent dans le formulaire
// ** sau 02.06.2006 : ajout de l'attribut isLink qui permet s'il est positionné à 'true'
// de renseigner le champ lié par le recordId de la notice liée
// ** sau 20.07.2006 : ajout de l'attribut onunloadLinkAssist qui permet de passer la fonction
// javascript a exécuter sur le onunload de l'assistant de saisie
// ** pru 16/10/2007 : ajout d'un attribut permettant de détecter les champs composite (isCompositeField)
// ** pru 16/10/2007 : l'url générer comprend un grand nombre de paramètre pour permettre l'utilisation d'assitant
//                     différent n'utilisant ou ne comprenant pas tout les paramètres sous le même nom

function inputCallLinkAssist(formName, action, tableName, dest, multimax, fieldFrom, filter, isLink, onunloadLinkAssist,isCompositeField)
{
   // Ajoute automatiquement le paramètre source si nécessaire
   var sourceName = null; 
   var parts = tableName.split(".");
   if ( parts.length == 2 )
   {
      sourceName = parts[0];
      tableName = parts[1];
   }
   var frame = this.name;
   var cgi = action;
   //Verifie si il n'existe pas deja des parametres.
   if( action.indexOf("?") == -1 )
   {
      cgi += "?";
   }
   else if( action.indexOf("&")!= (action.lenght-1) )
   {
         cgi += "&";
   }
   
   if ( sourceName != null )
      cgi += "source=" + myEscape(sourceName) + "&";
     
   cgi += "tableName=" + myEscape(tableName)
       + "&targetInput=" + myEscape( frame + "." + formName + "." + dest)
       + "&fieldFrom=" + myEscape(fieldFrom)
       + "&isLink=" + myEscape(isLink)
       + "&onunloadLinkAssist=" + myEscape(onunloadLinkAssist);

   cgi +="&table=" + myEscape(tableName)
       + "&fieldId=" + dest;
   
   if(fieldFrom != null )
   {
      var fieldId = fieldFrom.split(':');
      if(fieldId.length>2) //si ce n'est pas le cas fieldFrom est mal formé
      {
         if(fieldId[0].length != 0)
            cgi += "&curSource=" + myEscape(fieldId[0]);
         if(fieldId[1].length != 0)
            cgi += "&curTable=" + myEscape(fieldId[1]);
         if( fieldId[2].length != 0)
            cgi += "&fieldName=" + myEscape(fieldId[2]);
      }
   }
   if(isCompositeField!=null && isCompositeField.length != 0 )
   {
   cgi += "&isComposite="+isCompositeField;
   } 
   else
   {
      cgi += "&isComposite=false";
   }
       
   // Si pas de filtre, on interroge par a%
   if ( filter.length == 0 )    
   {
      cgi += "&criteria=" + myEscape("a");
      cgi += "&filter=";
   }   
   else  // Présence d'un filtre sql
   {
      // sql_command=nom_champ=$NOM_CHP_1$ AND ...
      // ==> Parties impaires == NOM_CHP_N
      var filterParts = filter.split("$");
      var filter = "";
      for ( var i=0; i < filterParts.length; i++ )
      {
         filter += filterParts[i];         
         i++;
         if ( i < filterParts.length )
         {
            var fieldName = filterParts[i];
            fieldName = StringUtil_trim(fieldName);
            var field = frmCheckField(formName, fieldName);            
            filter += field.value;
         }   
         
      }
      cgi += "&criteria=";
      cgi += "&filter=" + myEscape(filter);       
   }
      
   if ( multimax > 1 )
      cgi += "&multimax=" + myEscape(multimax);
   
   var tmp = action.split('/');
   
   var actionId = tmp[tmp.length-1];
   actionId=actionId.split('.')[0];
   var winName = "win_inputlink"+myEscape(actionId);
   // Ouvre la fenêtre   
   sysOpenWindow(winName, cgi,false,"0,0,725,505");
}

//Ouvre une nouvelle fenêtre pour exécuter l'action en paramètre
//formNane est le formulaire où se trouve le champ dest
//requête à executer
function openWindowForAction(formName, action, dest,requete)
{
   // Ajoute automatiquement le paramètre source si nécessaire
   var frame = this.name;
   var cgi = action;
   //Verifie si il n'existe pas deja des parametres.
   if( action.indexOf("?") == -1 )
   {
      cgi += "?";
   }
   else if( action.indexOf("&")!= (action.lenght-1) )
   {
         cgi += "&";
   }
      
   cgi += "targetInput=" + myEscape( frame + "." + formName + "." + dest);
   cgi += "&queryName="+requete;
   var h        = 450;
   var w        = 350;
   var top_pos  = 400;
   var left_pos = 400;

   // Ouvre la fenêtre   
   var winName = "win_inputlink" + sysGetAppName();
   sysOpenWindow(winName, cgi);
}

// formName : nom du formulaire d'origine
// field_name : nom de la liste du formulaire d'origine contenant les valeurs à
//              rapatrier
// destFieldPath : chemin nom du champ destination
// ** sau 02.06.2006 : ajout de l'attribut isLink qui permet s'il est positionné 
// à 'true' de renseigner le champ lié par le recordId de la notice liée
function frmRetrieveLinks(formName, action, p0, fieldName, p1, destFieldPath,
   p2, multimax, p3, linkSource, p4, linkTableName, p5, isLink)
{
   var field = new Field(destFieldPath);

   // Normalise le nom de champ
   if ( fieldName.indexOf(".") == 0 )
      fieldName = fieldName.substring(1);
   
   if ( ! field )
      return;

   // Valeur sélectionnée dans la liste
   var list = frmCheckField(formName, fieldName);
   if ( ! ( list && list.options) )
   {
      alert(mess_wrong_field_type + " liste : " + formName + "." + fieldName);
      return;
   }
      
   var end_single_selection = false;
   var input_type = field.element.type;
   var hasSelections = false;
      
   // On ajoute toutes les valeurs sélectionnées dans la liste
   for (var j=0; (j< list.options.length) && (!end_single_selection); j++)
   {
      if (list.options[j].selected)
      {
         hasSelections = true;
         var realVal = list.options[j].value;
         var dispVal = list.options[j].text;
         
         // Contruction du recordId de la notice liée
         var recId = new RecordId(realVal);
         if ( ! recId.isValid() )
         {
	         recId.setSource(linkSource);
	         recId.setTable(linkTableName);
	         recId.setInternalId(realVal);
	      }   
         
         // Présence du ctrl link ou link=NOM_TABLE;
         // Valeur réelle == recordId
         if ( isLink == "true" )
         {
            realVal = recId.getRecordId();
         }   
         
         // pour un champ simple
         if ( (input_type == 'hidden') || (input_type == 'text') )
         {
            field.element.value = realVal;
             
            var input_disp = field.element.name + "_EVERDISP";
            if ( field.form.elements[input_disp] )
               field.form.elements[input_disp].value = dispVal;
            end_single_selection = true;
            
            // Heritage des données
            var key = field.getFormName() + "." + field.getElementName();
            var LinkedFieldArray = field.getFrame().LinkedFields;
            var linkedData=null;
            if(LinkedFieldArray!=null)
                linkedData= field.getFrame().LinkedFields[key];
            // Il y des champs qui héritent de données de la notice d'autorité 
            if ( linkedData != null )
            {
               // Recherche de l'enregistrement lié
               var xmlDoc = XMLUtil_LoadRecord(recId.getRecordId());
               
               // Héritage des données
               if ( xmlDoc != null)
               {
                  //var debug = XMLUtil_serialize(xmlDoc.documentElement);
                  //appendDebug(debug);

                  for (var fName in linkedData)
                  {
                     // Vérification de la présence du champ dans le formulaire de saisie
                     var fieldPath = field.getFrameName();
                     fieldPath    += ".";
                     fieldPath    += field.getFormName();
                     fieldPath    += ".";
                     fieldPath    += fName;
                     
                     var fieldLinkedData = new Field(fieldPath); 
                     if ( fieldLinkedData != null )
                     {
                        var fieldAutorityName = linkedData[fName];
                        fieldLinkedData.element.value = getRecordFieldValue(xmlDoc, fieldAutorityName);
                        // appendDebug(fieldPath + " " + getRecordFieldValue(xmlDoc, fieldAutorityName));                     
                        
                        // sau 05.05.2007 : Tente de positionner le focus sur l'élément
                        setFocus(fieldLinkedData.element);
                     }
                  }
               }
            }
         }
         // pour un champ multivalué
         else if ((input_type=='select-one') || (input_type=='select-multiple'))
         {
            // vérifie que la liste de destination ne contient pas déjà la valeur
            var already_exists = false;
            for( var k=0; (k<field.element.options.length) && (!already_exists) ; k++ )
            {
               already_exists = ( field.element.options[k].value == realVal );
            }
            if ( ! already_exists )
            {
               if ( field.element.options.length <= multimax)
               {
                  field.frame.listAppendOption(field.element, realVal, dispVal);
               }
               else
               {
                  alert( mess_control_liste_multi2 + " " + multimax);
                  return;
               }
            }
         }
      }
   }
   if ( ! hasSelections )
   {
      alert(mess_select_first);
      return;
   }
   // Ferme automatiquement si sélection réussie pour champ lié simple
   if ( ! isANumber( multimax) ||  ( multimax <= 1 ) )
   {
      window.close();
   }
}

// Renvoie la valeur réelle d'un champ de l'enregistrement 
// passé en paramètre
// Si champ présent plusieurs fois dans la notice on retourne 
//   la valeur du premier.
// Si champ non trouvé renvoie une chaîne vide
function getRecordFieldValue(recordDoc, fieldName)
{
   var ret = "";
   
   if (     recordDoc != null  
        &&  fieldName != null 
        &&  fieldName.length > 0 )
   {     
      // Si le nom réel du champ commence par un chiffre, on ajoute _
      if ( !isNaN(fieldName.charAt(0)) )
         fieldName = "_" + fieldName;
      
      var elements = recordDoc.getElementsByTagName(fieldName);
      if ( elements && (elements.length >= 1 ) )
      {
         var nodeText = XMLUtil_getElementText(elements[0]);
         if ( nodeText != null )
            ret = nodeText.nodeValue;
      }
      //else
      //   alert("Champ non trouvé dans le record courant :" +fieldame);
   }
   return ret;
}

// Privé
// Teste l'existence d'une valeur dans une liste déroulante 
function listIsOptionDefined(list, value)
{
   for(var i=0 ; i < list.options.length ; i++)
   {
      if(list.options[i].value == value){return true;}
   }
   return false;
}

// Privé
// Ajout d'une OPTION dans un élément SELECT si cette valeur n'est pas déjà définie.
// Cette fonction doit être appelée dans la frame où se situe le SELECT
// (sinon problème dans IE)
// - emptyValue = code de l'élément bidon à enlever, vaut "0" par défaut
// noCheckDouble (true/false) false by default
// Renvoie l'Option ajouté ou null si aucun
function listAppendOption( list, val, disp, emptyValue,title, noCheckDouble)
{
   var len = list.options.length;
   var toadd = true;
   
   if ( ! (noCheckDouble == true)) {
	   if( listIsOptionDefined(list, val))
	   {
		   toadd = false;
	   }
   }

   if( toadd == true)
   {
      // Ecrase l'option bidon si elle existe
      if( (len == 1) )
      {
         if ( emptyValue == null ) emptyValue = "0";
         if ( list.options[0].value == emptyValue)
         {
            list.options[0].value = val;
            list.options[0].text = disp;
            list.options[0].title = title;
            return list.options[0];
         }
      }
      // Nouvelle valeur
      var newOption = new Option(disp, val);
      newOption.title=title;
      list.options[len] = newOption;
      return newOption;
   }
   return null;
}

function listDeleteOption( list, val)
{
   var len = list.options.length;
   var ret=false;
      // Ecrase l'option bidon si elle existe
   for(var i=0 ; i < list.options.length ; i++)
   {
      if(list.options[i].value == val)
      {
      list.options[i] = null;
      ret=true;
      }
   }
   return ret;
}

// Sélectionne toutes les valeurs sauf emptyValue (vaut "0" par défaut)
function listSelectAll(liste, emptyValue)
{
   if ( liste && liste.options )
   {
      if ( emptyValue == null ) emptyValue = "0";
      for (i=0; i<liste.options.length; i++)
      {
         if (liste.options[i].value != emptyValue)
         {
            liste.options[i].selected = true;
         }
      }
   }
}

//Mise à jour du schemaData à partir des elements de la liste
//frameName, nom de la frame appelante
//fieldName, nom du champ dans le schemaData
//fieldId, Id du champ dans le schemaData
function thesaurusListToSchemaData(frameName, fieldName, fieldId)
{
   //Récupération des éléments de la liste
   var frame = findFrameWithinApp(frameName);
   // tdn 29/06/2006 l'élément input est trouvé par son id unique
   var fieldList = new Field(frameName, fieldId + "_input");
   
   var inputValue = "";
   var inputDisplay = "";
   
   for (var j=0; j< fieldList.element.options.length; j++)
   {
      if (j == 0)
      {
         inputValue = fieldList.element.options[j].value;
         inputDisplay = fieldList.element.options[j].innerHTML;
      }
      else
      {
         inputValue = inputValue + MULTIPLE_VALUE_SEP + fieldList.element.options[j].value;
         inputDisplay = inputDisplay + MULTIPLE_VALUE_SEP + fieldList.element.options[j].innerHTML;
      }         
   }       
   
   //Mise à jour du schemaData
   var schemData = frame.INPUT_VIEW.schemaData;             
   var fieldData = schemData.getFieldByNameAndId(fieldName, fieldId); 
   
   // Mise à jour du schéma de données
   if (fieldData)
   {
      schemData.setFieldValue(fieldData, inputValue);
      schemData.setFieldDisplayValue(fieldData, inputDisplay);
      
   }                  
}

//Fonction qui recherche les NOMCHAMP_THESAURUS_LIST d'un document.
//Pour chaque élément correspondant :
//Positionne le champ NOMCHAMP avec les valeurs réélles de la liste séparées par un \n
function thesaurusListsToHidden(formName)
{
   var formElements = document.forms[formName].elements;
   for (var i=0; i< formElements.length; i++)
   {
      var fieldName = formElements[i].name;
      var parts = fieldName.split("_THESAURUS_LIST");
      if ( parts.length == 2 )
      {
         var hiddenFieldName = parts[0];
         var vhiddenFieldName = document.getElementById(hiddenFieldName);
         if (vhiddenFieldName)
         {
            var field = new Field("win_data." + formName + "." + fieldName);
            for( var k=0; k<field.element.options.length ; k++ )
            {
               if (k == 0)
                  vhiddenFieldName.value = field.element.options[k].value;
               else
                  vhiddenFieldName.value = vhiddenFieldName.value + "\n" + field.element.options[k].value;
            }
         }
         else
         {
            alert(hiddenFieldName+" introuvable !");         
            return(false);
         }
      }      
   }
   return(true);
}

// Pour un champ lié, d'un formulaire donnée, cette fonction contient 
// une liste de correspondances entre les champs de la notice courante 
// et le contenu du champ de la notice d'autorité à hériter
function addToLinkedField(formName, fieldName, linkFieldName, fieldAutorityName)
{
   var key = formName + "." + linkFieldName;
   var linkedData = LinkedFields[key];
   if ( linkedData == null )
   {
      linkedData = new Array();
      linkedData[fieldName] = fieldAutorityName;
      LinkedFields[key] = linkedData;
   }   
   else
      linkedData[fieldName] = fieldAutorityName;   
}

// CONTROLE : compute
// ------------------
// Pour un champ qui dispose du contrôle compute, cette fonction parse 
// l'expression régulière et complète la liste des champs qui sont pris en 
// compte dans un contrôle compute
// Limitation : dans un contrôle compute, il ne peut pas y avoir un champ qui 
// lui même contrôle sur compute.
function addToFieldsInCompute(formName, fieldName, computeExpr, precision)
{
   if (   computeExpr != null
       && computeExpr.length > 0 )
   {
      var computeDef = new ComputeDef(fieldName, computeExpr, precision); 
      
      //appendDebug("Contrôle compute sur le champ :  " + fieldName);
      //appendDebug("   compute=" + computeDef.getDisplayExpression());
      
      // Liste des champs
      var fieldList = computeDef.getFieldList();
      if ( fieldList )
      {
         for ( var fieldNameInCompute in fieldList )
         {
            var key = formName + "." + fieldNameInCompute;
          
            // Liste des champs associés à un contrôle compute
            var computeDefList = FieldsInCompute[key];
            if ( computeDefList == null )
            {
               computeDefList = new Array();
               FieldsInCompute[key] = computeDefList;
            }   
            computeDefList[computeDefList.length] = computeDef;
         }
      }
   }
}

// Mise à jour des champs contrôlés par compute
function updateComputeWithField(formName, fieldName)       
{
   var key = formName + "." + fieldName;
   var computeDefList = FieldsInCompute[key];
   
   // Le champ n'est pas pris en compte dans un contrôle compute
   if ( computeDefList == null )
   {
      //appendDebug(fieldName + " n'est pas pris en compte dans un champ contrôlé par compute");
      return; 
   }   

   // Parcours de la liste des définitions des contrôles compute associés au 
   // champs passé en paramètre
   for ( var i = 0; i < computeDefList.length ; i++)
   {
      var computeDef = computeDefList[i];
      var computeFieldName = computeDef.getFieldName();
      var precision = computeDef.getPrecision();

      //appendDebug("Application ctrl compute sur champ : " + computeFieldName);
      //appendDebug("   compute=" + computeDef.getDisplayExpression());
      //appendDebug("   precision=" + precision);
      
      // Remplacement dans l'expression des noms des champs par leur valeur
      // présentes dans la grille de saisie
      // Puis, evaluation de l'expression
      var fieldDefValue = 0;
      var computeValue  = computeDef.evaluate(formName, fieldDefValue);
      
      // Application du contrôle precision dans le cas des décimaux
      if ( precision > 0 )
         computeValue = getDataCtrlDecimal(computeValue, precision);
      
      // Teste si le champ contrôlé par compute est présent dans la grille de saisie
      var computeFieldElem = frmGetField(formName, computeFieldName);
      computeFieldElem.value = computeValue;
   }
}

//-----------------------------------------
// Objet de description du contôle compute
function ComputeDef(fieldName, expression, precision)
{
  // Le champ sur lequel porte le contrôle compute
  this.fieldName = fieldName;
  // L'expression telle que saisie dans le contrôle
   this.expressionDef = new ExpressionDef(expression);
  // Provient du contrôle precision
  this.precision = precision;
  
  return this;
}
ComputeDef.prototype.getFieldName = function()
{
  return this.fieldName;
}
ComputeDef.prototype.getDisplayExpression = function()
{
   return this.expressionDef.getDisplayExpression();
}
ComputeDef.prototype.getFieldList = function()
{
   return this.expressionDef.getFieldList();
}
ComputeDef.prototype.getPrecision = function()
{
  return this.precision;
}
ComputeDef.prototype.evaluate = function(formName, fieldDefValue)
{
   return this.expressionDef.evaluateWithFormValues(formName, fieldDefValue);
}
//---------------------------
//Objet de description d'une expression logique ou de calcul 
// contenant des champs de la notice en variables
function ExpressionDef(expression)
{
	
   // Expression modifiée pour être comprise en javascript
   this.expression = null;
   // L'expression telle que saisie dans le contrôle
   this.displayExpression = null;
   // Liste des champs présents dans l'expression
   this.fieldList = null;
   // Liste des champs NORMALISES présents dans l'expression 
   this.normalizeFieldList = null;
   
   // Initialisation
   this.init(expression);
   return this;
}
ExpressionDef.prototype.init = function(expression)
{
   // Expression affichée dans message d'erreur (Suppression des entités codées)
   this.displayExpression = XMLUtil_replaceCodeEntities(expression);
   
   // Expression modifiée pour être comprise en javascript
   // Remplacement des opérateurs 
   // =   ==> ==
   // and ==> &&
   // or  ==> ||
   // not ==> !=
   this.expression = _replaceOperInExpression(this.displayExpression);
   
   // Initialisation de la liste des champs présents dans l'expression 
   this.fieldList = _getExpressionFieldList(this.expression);
   
   // Liste des champs normalisés 
   if ( this.fieldList )
   {
     this.normalizeFieldList = new Array();
     for (var fieldName in this.fieldList )
     {
        var normFieldName = normalizeFieldName(fieldName); 
        this.normalizeFieldList[normFieldName] = normFieldName;
     }
   }     
}
//Expression telle que saisie dans le contrôle
ExpressionDef.prototype.getDisplayExpression = function()
{
   return this.displayExpression;
}
//Liste des champs présents dans l'expression
ExpressionDef.prototype.getFieldList = function()
{
   return this.fieldList;
}
//Liste des champs NORMALISES présents dans l'expression
ExpressionDef.prototype.getNormalizeFieldList = function()
{
   return this.normalizeFieldList;
}
//Evaluation de l'expression
ExpressionDef.prototype.evaluate = function(fieldValueList)
{
   var expression = this.expression;
   if ( fieldValueList )
   {        
      for ( var fieldName in fieldValueList )
      {
         var fieldValue = fieldValueList[fieldName]; 
         expression = _replaceInExpression(expression, fieldName, fieldValue);
      }
   }      
   
   var result;
   try
   {
      // Evaluation de l'expression
      result = eval(expression);  
   }
   catch (exception)
   {
      alert("Error on evaluate expression: ["+ this.displayExpression +"]\n[" + expression+"]");
   }

   return result;
}
// Evaulation de l'expression à partie des valeurs du formulaire
ExpressionDef.prototype.evaluateWithFormValues = function(formName, fieldDefValue)
{
   var fieldValueList = _getFieldValueList(formName, this.fieldList, fieldDefValue);
   return this.evaluate(fieldValueList);
}

//---
// Dans l'expression, remplace des opérateurs 
// and ==> &&
// or  ==> ||
// not ==> !=
// = non précédé de !,<,>,= ou ; (for entity ending by ;) par ==
function _replaceOperInExpression(expr)
{
   if (   expr == null 
       || expr.length == 0 )
       return expr;

   // Remplacement de = non précédé de !,>,<,= ou une entité (ce termine par;) par ==
   var regExp = new RegExp("[^<>!=;]=", "g");
   expr=expr.replace(regExp,"==");
    
   var toReplace = new Array();
   toReplace["and"] = "&&";
   toReplace["AND"] = "&&";
   toReplace["or"]  = "||";
   toReplace["OR"]  = "||"; 
   toReplace["not"] = "!=";
   toReplace["NOT"] = "!=";
   
   for( var wordToReplace in toReplace )
   {
      var by = toReplace[wordToReplace];
      expr = _replaceInExpression(expr, wordToReplace, by);
   }
   
   return expr;
} 

// Renvoie la liste des champs présents dans l'expression
function _getExpressionFieldList(expr)
{ 
   if (   expr == null 
       || expr.length == 0 )
       return expr;
   
   // Remplacement du mot clé null par un espace    
   expr = _replaceInExpression(expr, "null", " ");
       
   var fieldList = null;
   while ( expr != "" )
   {
      // Noms de champs composés des caractères [a-z][A-Z][0-9]_
      var match = expr.match(/^(\W*)(\w*)(.*)$/);
      var fieldName = match[2];
      
      // Les noms de champs ne peuvent pas être des nombres (les constantes)
      if ( isNaN(fieldName) )
      {
         if ( fieldList == null )
            fieldList = new Array();
         fieldList[fieldName] = fieldName;
      }   
      expr = match[3];
   }
   
   return fieldList;
}

// Dans l'expression passée en paramètre remplace toutes les occurences du mot 
// word1 par le mot word2 
function _replaceInExpression(expr, wordToReplace, by)  
{
   if (   expr == null 
       || expr.length == 0 )
       return expr;
       
   // Mot au début de l'expression
   var regExp = new RegExp("^(\\W*)("+wordToReplace +")(\\W+)");
   expr = expr.replace(regExp, "$1"+by+"$3");
   // Mot dans l'expression
   regExp = new RegExp("(\\W+)("+wordToReplace +")(\\W+)", "g");
   expr = expr.replace(regExp, "$1"+by+"$3");
   // Mot à la fin de l'expression
   regExp = new RegExp("(\\W+)("+wordToReplace +")(\\W*)$");
   expr = expr.replace(regExp, "$1"+by+"$3");
   
   return expr;
}

//Renvoie un tableau dont l'indice correspond au nom du champ et la valeur 
// correspond au contenu du champ
function _getFieldValueList(formName, fieldList, fieldDefvalue)
{
   var fieldListValue = new Array();
      
   if ( fieldList )
   {      
      var form = document.forms[formName];
      if ( form == null )
      {
         alert(mess_form_not_found + formName);
         return;
      }
 
      for ( var fieldName in fieldList )
      {
         var fieldElem = frmCheckField(formName, fieldName, null /*fieldId*/);
         var fieldValue = fieldDefvalue;
         
         if ( fieldElem  )
         {
            fieldValue = getFieldValue(form, fieldName, fieldDefvalue);
            if ( fieldValue == "")
               fieldValue = fieldDefvalue;
         }
         else
         {      
            var mess = "Le champ " + fieldName;
            mess += " utilisé dans l'expression " + initialExpr;
            mess += " doit être ajouté à la grille de saisie.";
            alert(mess);
         }
       
         fieldListValue[fieldName] = fieldValue;
         
         //appendDebug(" " + fieldName + " : fieldValue =" + fieldValue);           
      }
   }   
   return fieldListValue;
}   

// CONTROLES : check_input et check_input_trigger
// ----------------------------------------------
// Pour un champ qui dispose du contrôle check_input, cette fonction parse 
// l'expression et complète la liste des champs qui sont pris en 
// compte dans un contrôle check_input
function addToFieldsInCheckInput(formName, fieldName, checkInputExpr, checkInputTriggerExpr)
{
   if (   checkInputExpr != null
       && checkInputExpr.length > 0 )
   {
      var checkInputTriggerDef = null;
      if (    checkInputTriggerExpr != null 
          &&  checkInputTriggerExpr.length > 0 )
      {    
         checkInputTriggerDef = new CheckInputDef(fieldName, checkInputTriggerExpr); 
      }   
      
      var checkInputDef = new CheckInputDef(fieldName, checkInputExpr, checkInputTriggerDef);
      
      // Liste des champs qui disposent du ctrl check_input
      var formCheckInputDefList = CheckInputFields[formName];
      if ( formCheckInputDefList == null )
      {
         formCheckInputDefList = new Array();
         CheckInputFields[formName] = formCheckInputDefList;
      }   
      formCheckInputDefList[formCheckInputDefList.length] = checkInputDef;
      
      //appendDebug("Contrôle check_input sur le champ :  " + fieldName);
      //if ( checkInputTriggerDef )
      //   appendDebug("   check_input_trigger=" + checkInputTriggerDef.getDisplayExpression());
      //appendDebug("   check_input=" + checkInputDef.getDisplayExpression());
            
      // Liste des champs
      var fieldList = checkInputDef.getFieldList();
      if ( fieldList )
      {
         for ( var fieldNameInCheckInput in fieldList )
         {
            var key = formName + "." + fieldNameInCheckInput;
          
            // Liste des champs associés à un contrôle check_input
            var checkInputDefList = FieldsInCheckInput[key];
            if ( checkInputDefList == null )
            {
               checkInputDefList = new Array();
               FieldsInCheckInput[key] = checkInputDefList;
            }   
            checkInputDefList[checkInputDefList.length] = checkInputDef;
         }   
      }
   }
}

// Prise en compte de la valeur du champ pour les contrôles check_input
function checkInputWithField(formName, fieldName)       
{
   var key = formName + "." + fieldName;
   var checkInputDefList = FieldsInCheckInput[key];
   
   // Le champ n'est pas pris en compte dans un contrôle check_input
   // if ( checkInputDefList == null ) { return true;}
   
   return checkInputOnDefList(formName, checkInputDefList);
}   

// Application de tous les check_input
function checkInput(formName)
{
   var checkInputDefList = CheckInputFields[formName];
   
   // Il n'y a pas de contrôle check_input associés aux champs de la grille 
   // de saisie
   //if ( checkInputDefList == null ) {return true;}
   
   return checkInputOnDefList(formName, checkInputDefList);
}

function checkInputOnDefList(formName,checkInputDefList)
{
   // Pas de contrôles  
   if ( checkInputDefList == null )
      return true;
   
   // Parcours de la liste des définitions des contrôles compute associés au 
   // champs passé en paramètre
   var fieldDefValue = "null";
   for ( var i = 0; i < checkInputDefList.length ; i++)
   {
      var checkInputDef = checkInputDefList[i];
      var checkInputTriggerDef = checkInputDef.getCheckInputTriggerDef();
      
      var triggerEvalResult = true;
      if ( checkInputTriggerDef )
      {
         triggerEvalResult = checkInputTriggerDef.evaluate(formName, fieldDefValue);
	   }
	   
	   if ( triggerEvalResult )
	   {
	      // Evaluation de l'expression
         if ( ! checkInputDef.evaluate(formName, fieldDefValue) )
	        {
	           // L'expression de vérification n'est pas vérifiée :\n
	           // checkInputDef.getDisplayExpression());
	           var msg = sysGetMessage("control.check.input");
	           alert(msg + checkInputDef.getDisplayExpression());
	           return false;
	        }   
	      }
   }
       
   return true;
}

//-----------------------------------------
// Objet de description du contôle check_input
function CheckInputDef(fieldName, expression, checkInputTriggerDef)
{
  // Le champ sur lequel porte le contrôle check_input
  this.fieldName = fieldName;
  this.expressionDef = new ExpressionDef(expression); 
  // Objet de description de du contrôle check_input_trigger, associé au contrôle 
  // check_input
  this.checkInputTriggerDef = checkInputTriggerDef;
  
  return this;
}
CheckInputDef.prototype.getFieldName = function()
{
  return this.fieldName;
}
CheckInputDef.prototype.getDisplayExpression = function()
{
  return this.expressionDef.getDisplayExpression();
}
CheckInputDef.prototype.getFieldList = function()
{
   return this.expressionDef.getFieldList();
}
CheckInputDef.prototype.getCheckInputTriggerDef = function()
{
  return this.checkInputTriggerDef;
}
CheckInputDef.prototype.evaluate = function(formName, fieldDefValue)
{
   return this.expressionDef.evaluateWithFormValues(formName, fieldDefValue);
}
//---------------------------

/**********************
 * Etend la classe primitive Date 
 *********************/
// Renvoie aaaammjj
Date.prototype.getISO = function () 
{
  var year = this.getCurrentYear();
  var month = this.getCurrentMonth();
  var day = this.getDate();
  if ( day < 10 )
     day = "0"+day;
  if (month < 10 )
     month = "0"+month;
  return year + "" + month + "" + day;
}
 
 // Renvoie l'année en cours
Date.prototype.getCurrentYear = function()
{
   return this.getFullYear();
}
// Renvoie l'année suivante
Date.prototype.getNextYear = function() 
{
   return this.getFullYear() + 1;
}
// Renvoie l'année précédente
Date.prototype.getPreviousYear = function() 
{
   return this.getFullYear()- 1;
}
// Renvoie le numéro du mois en cours
Date.prototype.getCurrentMonth = function()
{
   return this.getMonth() + 1;
}
// Renvoie le numéro du mois suivant
Date.prototype.getNextMonth = function()
{
   if (this.getMonth() < 11) 
      this.setMonth(this.getMonth() + 1);
   else 
   {
      this.setMonth(0);
      this.setFullYear(this.getFullYear() + 1);
   }
    return this.getMonth() + 1;
}
// Renvoie le numéro du mois précedent
Date.prototype.getPreviousMonth = function()
{
   if (this.getMonth()) this.setMonth(this.getMonth() - 1);
   else {
       this.setMonth(11);
       this.setFullYear(this.getFullYear() - 1);
   }
   return this.getMonth() + 1;
}
// Ajoute un nombre de jour, 1 par défaut
Date.prototype.addDays = function(increment)
{
   if ( ! increment) increment = 1;
   this.setDate(this.getDate() + increment);
   return this.getDate();
}
// Ajoute un nombre de mois, 1 par défaut
Date.prototype.addMonth = function(increment)
{
   if ( ! increment) increment = 1;
   for(var i = 1; i<= increment; i++)
      this.getNextMonth();
   return this.getCurrentMonth();
}
// Ajoute un nombre d'année, 1 par défaut
Date.prototype.addYear = function(increment)
{
   if ( ! increment) increment = 1;
   for(var i = 1; i<= increment; i++)
      this.getNextYear();
   return this.getCurrentYear();
}

// Ajoute soit un nombre de jour, un nombre de mois et un nombre d'années
Date.prototype.add = function(nb_years, nb_month, nb_days)
{ 
   this.addYear(nb_years);
   this.addMonth(nb_month);
   this.addDays(nb_days);
}
// Compare 2 dates
Date.prototype.equalsTo = function(d)
{ 
   if ((this.getDay() == d.getDay()) && (this.getMonth() == d.getMonth()) 
        && (this.getFullYear() == d.getFullYear()))
      return true;
   else 
      return false;  
}

// Définie isArray car sous IE sysInstanceOf ne marche pas
/* Provoque dysfonctionnement si on parcourt un tableau avec for .. in !
Array.prototype.isArray = function()
{
   return true;
}
*/

// Renvoie le format visible d'une date
// - dateVal : aux formats de DateUtil_guessDate
// Par défaut, renvoie jj/mm/aaaa
// tdn 07/07/2005
function DateUtil_getVisibleFormat(dateVal)
{
   var ret = "";
   var dateObj = DateUtil_guessDate(dateVal);
   if (dateObj)
   {
      var yy = dateObj.getCurrentYear();
      var mm = dateObj.getCurrentMonth();
      if ( mm < 10 ) mm = "0" + mm;
      var dd = dateObj.getDate();
      if ( dd < 10 ) dd = "0" + dd
      ret = dd + "/" + mm + "/" + yy;
   }
   return ret;
}
// Renvoie le format ISO aaaammjj d'une date
// - dateVal : aux formats de DateUtil_guessDate
// tdn 07/07/2005
function DateUtil_getISOFormat(dateVal)
{
   var ret = "";
   var dateObj = DateUtil_guessDate(dateVal);
   if (dateObj)
   {
      var yy = dateObj.getCurrentYear();
      var mm = dateObj.getCurrentMonth();
      if ( mm < 10 ) mm = "0" + mm;
      var dd = dateObj.getDate();
      if ( dd < 10 ) dd = "0" + dd
      ret = yy + "" + mm + "" + dd;
   }
   return ret;
}

// Renvoie un Date() à partir de l'objet spécifié, null si dateVal est null ou invalide
// - dateVal : peut être une Date(), une chaîne ISO aaaammjj, ou une chaîne visible
//    un tableau contenant jj,mm,aaaa
function DateUtil_guessDate(dateVal)
{
   var dd,mm,yy;
   if ( ! dateVal ) return null;
   // Date()
   if ( sysInstanceOf(dateVal, Date) ) return dateVal;
   // Array()
   var isArray = false;
   try
   { 
      isArray = sysInstanceOf(dateVal, Array); // marche par avec IE
   } 
   catch(e)  { }
   if ( !isArray )
   {
      try
      {
         //isArray = dateVal.isArray();
         isArray = (dateVal.length == 3);
      }
      catch(e){}
   }
   if (isArray)
   {
      if (dateVal.length == 3)
      {
         dd = dateVal[0];
         mm = dateVal[1];
         yy = dateVal[2];
      }
   }
   else // chaîne simple ou nombre
   {
      dateVal = "" + dateVal;
      if ( dateVal.length == 8 ) // aaaammjj ?
      {
         yy = dateVal.substring(0,4);
         mm = dateVal.substring(4,6);
         dd = dateVal.substring(6,8);
      }
      else if ( dateVal.length == 10 ) // jj/mm/aaaa ?
      {
         var parts = dateVal.split("/");
         yy = parts[2];
         mm = parts[1];
         dd = parts[0];
      }
   }
   
   var ret = null;
   var ok = 0;
   if ( yy && mm && dd )
   {
      var val = parseInt(dd, 10); 
      if ( isANumber(dd) && 0<val && val<32 )
      {
         dd = val;
         ok ++;
      }
      val = parseInt(mm,10);
      if ( isANumber(mm) && 0<val && val<13 )
      {
         mm = val - 1;
         ok ++;
      }
      val = parseInt(yy,10);
      if ( isANumber(yy) && 0<val  )
      {
         yy = val;
         ok ++;
      }
   }
   if ( ok == 3 )
   {
      ret = new Date();
      ret.setDate(1);
      ret.setYear(yy);
      ret.setMonth(mm);
      ret.setDate(dd);
   }
   return ret;
}

// Vérifie si la date specifiée est valide : 
//   renvoie true si la date est valide false sinon
// - dateVal : peut être une Date(), une chaîne ISO aaaammjj, ou une chaîne visible
//    un tableau contenant jj,mm,aaaa
function DateUtil_checkDate(dateVal)
{
   var dd,mm,yy;
   if ( ! dateVal )
   {
      return false;
   }
   // Date()
   if ( sysInstanceOf(dateVal, Date) ) 
   {
      dd=dateVal.getDate();
      mm=dateVal.getMonth() + 1;
      yy=dateVal.getFullYear();
   }
   // Array()
   var isArray = false;
   try 
   { 
      isArray = sysInstanceOf(dateVal, Array); // marche par avec IE
   } catch(e)  { }
   if ( !isArray ) 
   {
      try {
         //isArray = dateVal.isArray();
         isArray = (dateVal.length == 3);
      } catch(e){}
   }
   if (isArray) 
   {
      if (dateVal.length == 3) 
      {
         dd = dateVal[0];
         mm = dateVal[1];
         yy = dateVal[2];
      }
   } 
   else 
   { // chaîne simple ou nombre
      dateVal = "" + dateVal;
      if ( dateVal.length == 8 ) // aaaammjj ?
      {
         yy = dateVal.substring(0,4);
         mm = dateVal.substring(4,6);
         dd = dateVal.substring(6,8);
      } 
      else if ( dateVal.length == 10 ) // jj/mm/aaaa ?
      {
         var parts = dateVal.split("/");
         yy = parts[2];
         mm = parts[1];
         dd = parts[0];
      } 
      else 
      {
         return false;
      }
   }
   
   if(mm == 1 || mm == 3 || mm == 5 || mm == 7 || mm == 8 || mm == 10 || mm == 12)
   {
      if(dd > 31)
      {
         return false;
      }
   } 
   else if(mm == 4 || mm == 6 || mm == 9 || mm == 11)
   {
      if(dd > 30)
      {
         return false;
      }
   } 
   else if(mm == 2) 
   {
      if (!isLeapYear(yy) && dd > 28)
      {
         return false;
      } 
      else if(isLeapYear(yy) && dd > 29)
      {
         return false;
      }        
   }
   else
   {
      return false;
   }   
   
   return true;
}


// Teste si une année est bisextile
function isLeapYear(yearVal)
{ 
   if (((yearVal % 4)==0) && ((yearVal % 100)!=0) || ((yearVal % 400)==0))
   {
      return true;
   } 
   else
   {
      return false;
   }
}

/**
 * retourne un tableau contenant l'index de toutes les
 * options selectionnées
 * @param listElement: element dom de type select
 **/
function getAllSelectedIndex(listElement)
{
   var arrayOfIndex = new Array;
   var len    = listElement.options.length;
   for (var i=0; i<len; i++)
   {
      if (listElement.options[i].selected)
      {
         arrayOfIndex.push(i);
      }
   }
   return arrayOfIndex;
}

/**
 * Cette methode permet d'intervertir les options aux index index1 et index2
 * de la liste selectElement.
 * @param selectElement htmldom representant un select
 * @param index1, index d'une option de selectElement
 * @param index2, index d'une option de selectElement
 **/
function revertOptions(selectElement,index1, index2)
{
     var Option1 = selectElement.options[index1];
     var Option2 = selectElement.options[index2];
     selectElement.options[index1]=new Option("", "");
     selectElement.options[index2]=Option1;
     selectElement.options[index1]=Option2;
}

//Fonction générique permettant le déplacement des éléments sélectionnés de la liste source vers la liste cible
function moveListElement(listSource, listDest)
{     
   //Vérifier que un élément est sélectionné dans la liste source
   //Recherche de l'élément sélectionné dans la liste source (ou des éléments sélectionnés)
   //Recopie dans la liste cible de la ou des sélections.
   var selectedIndex = listSource.options.selectedIndex;
   if (selectedIndex >= 0)
   {
      var option = new Option(listSource.options[selectedIndex].text,listSource.options[selectedIndex].value);
      option.title=listSource.options[selectedIndex].title;
      var lenDest = listDest.options.length;
      listDest.options[lenDest] = option;
      listSource.options[selectedIndex]=null;
      selectedIndex = listSource.options.selectedIndex;
      while (selectedIndex >= 0)
      {
         option = new Option(listSource.options[selectedIndex].text,listSource.options[selectedIndex].value);
         option.title=listSource.options[selectedIndex].title;
         lenDest = listDest.options.length;
         listDest.options[lenDest] = option;
         listSource.options[selectedIndex]=null;
         selectedIndex = listSource.options.selectedIndex;    
      }
   } 
}

/**
 * Cette method monte ou descende un element option dans une list
 * @param formName null
 * @param action null
 * @param p0 null
 * @param listName nom de la liste
 * @param moveUp si true l'option monte
 * 
 */
function moveOption(formName, action, p0, listName,moveUp)
{
   var step;
   if(moveUp)
   {
      step=-1;
   } else
   {
      step=1;
   }
   var listElement = document.getElementById(listName);
   var options = listElement.options;
   
   var arrayOfSelectedIndex = getAllSelectedIndex(listElement);
   var lastIndex = arrayOfSelectedIndex.length-1;
   for(var i=0;i<arrayOfSelectedIndex.length;i++)
   {
      //moveUp et la ligne si dessous permettent de gérér proprement le déplacement
      //d'une multi-sélection avec des vides lorsque l'on atteind les extrémiter.
      var indexSelected = (moveUp)?arrayOfSelectedIndex[i]:arrayOfSelectedIndex[lastIndex-i];
      if(indexSelected==(listElement.length-1) && !moveUp)
      {
          return;
      }
      if(indexSelected==0 && moveUp)
      {
          return;
      }
     
     revertOptions(listElement,indexSelected,indexSelected+step);
   }
}

/**
 * sélectionne une valeur dans une liste
 * @param listName: nom de la liste
 * @param optionValue: valeur de l'option à sélectionner
 */
function selectOption(listName,optionValue)
{
   var listElement = document.getElementById(listName);
   if(listElement==null)
      return;
   var options = listElement.options;
   var index=-1;
   for(var i=0;i<options.length;i++)
   {
      if(options[i].value==optionValue)
      {
         index = i;
         break;
      }
   }
   listElement.selectedIndex=index;
   
}

// Ouvre l'assistant de saisie sur les dates exclues
function openExcludedDateAssistant(fieldId)
{
   var excludedField = document.getElementById(fieldId);
   if ( excludedField )
   {
      var excludedContent = excludedField.value;
      var baseUrl = sysGetAppBaseUrl();
      var action = baseUrl+"jsp/admin/excludeddate/assist_excluded_dates.jsp";
      action += "?fieldId="+fieldId+"&excludedContent="+excludedContent+
      			"&paramSubscription="+true;
      var winName = "excluded_dates";
      var options = "toolbar=0,location=0,directories=0,menuBar=0,scrollbars=yes,resizable=yes"
      var windowStyle = "height=300px, width=575px, top=200px, left=200px" + options;        
      //alert("actionAfter before openWindows = " + action);
      window.open(action ,winName,windowStyle);
   }
   else
   {
      alert("openExcludedDateAssistant field not found id=" + fieldId);
   }
}

// Cas 68 Ajout d'un item à une liste
// - inputWindowName : nom de la fenêtre appelante
// - listSoruce : source la liste
// - listName : nom de la liste
// - tableName,fielName : table et champ en cours de saisie
// - fieldId : id du champ en cours de saisie
// - inputId : id de l'élément HTML en cours de saisie
function openInputListAppendItem(inputWindowName, 
   listSource, listName, tableName, fieldName, fieldId, inputId)
{
   var action = sysGetAppRoot() + "/jsp/system/input/input_list_append_item.jsp?";
   action += "listSource=" + listSource;
   action += "&listName=" + listName;
   action += "&tableName=" + tableName;
   action += "&inputWindow=" + inputWindowName;
   action += "&fieldName=" + fieldName;
   action += "&fieldId=" + fieldId;
   action += "&inputId=" + inputId;
   action += "&init=true";
   var sp = sysGetWindowContext("win_input_list_append");
   if ( sp == null )
   {
      sp = new SizeAndPos("0,0,450,450");
      sp.center();
   }
   var win = window.open(action, "win_input_list_append",
      "toolbar=0,location=0,directories=0,menuBar=0,scrollbars=yes,resizable=yes,status=yes" +
      ",width=" + sp.w + ",height=" + sp.h +
      ",top=" + sp.y + ",left=" + sp.x);  
   win.focus();
}

/**
 * Permet l'ouverture de l'assistant sur datation
 */
function callDatation(formName,fieldName,fieldId,fieldNameEnd,elemIdEnd)
{   
   var datationAction = sysGetAppRoot() + "/jsp/tools/assist_datation.jsp?fieldName=";
   if(fieldName!=null)
      datationAction += fieldName;
   
   datationAction += "&fieldId=";
   if(fieldId!=null)
       datationAction +=fieldId
   datationAction += "&fieldNameEnd=" ;
   if(fieldNameEnd!=null)
      datationAction += fieldNameEnd;
   
   datationAction += "&fieldIdEnd="
   if(elemIdEnd!=null)
       datationAction += elemIdEnd;
   
   var winName = "win_inputdatation" + sysGetAppName();
   sysOpenWindow(winName, datationAction);
}

