//---------------------------
// Fonctions getDataCtrlNomContrôle :
// A partir des données saisies ces fct renvoient la valeur réelle du champ 
// sur lequel s'applique le contrôle 'Nom contrôle'.
//  - NomFonction : valeur retournée   
//  - getDataCtrlDate(inputValue) : date au format ISO
//  - getDataDecimal(inputValue, precision) : 
//       ==> nombre décimal avec "precison" décimale et arrondi automatique
//  - getDataCtrlSelectListeMultiple(fieldElt, schemaField)
//       ==> valeur réelle d'une liste multivaluée 
//           avec prise en cpte du séparateur 
//  - getDataCtrlMarc(inputValue) : valeur codée de l'article mis entre crochets
//                              ou  valeur saisie sans les doubles crochets
//  - getDataCtrlToMajus(inputValue) : valeur passée en majuscules
//  - getDataCtrlToMinus(inputValue) : valeur passée en minuscules    
//---------------------------

// Renvoie :
// - le format ISO de la date passée en paramètre
// - la valeur passée en paramètre si elle ne représente pas une date
function getDataCtrlDate(inputValue) 
{
   // Pas de valeur saisie, on retourne une chaîne vide 
   if (inputValue.length == 0)
      return "";

   // Valeur réelle à retourner
   var valueData = inputValue;   
   
   // Suppression des espaces de début et de fin
   inputValue = StringUtil_trim(inputValue);
 
   if ( inputCtrlDate(inputValue, false, null) ) // pas de message si Pb
   { 
      // Date saisie au format iso : aaaammjj
      if  ( inputValue.length == 8 )
         return inputValue;
           
      // Les séparateurs de saisie possibles : le slash ou le point
      // Formats de saisie :  jj/mm/aaaa  ou  jj.mm.aaaa    
      var parts = inputValue.split("/");
      
      if (parts.length != 3)
        parts = inputValue.split(".");
        
      valueData = parts[2] + parts[1] + parts[0];   
   }
   return valueData;    
}

// Renvoie : 
//  - un nombre décimal avec application d'un arrondi automatique 
// à "precison" décimales
//  - la valeur passée en paramètre si elle ne correspond pas à un nombre
function getDataCtrlDecimal(inputValue, precision) 
{
   if ( ! isNaN(inputValue) ) inputValue = "" + inputValue;
   // Pas de valeur saisie, on retourne une chaîne vide 
   if (inputValue.length == 0)
      return "";

   // Valeur réelle à retourner
   var valueData = inputValue;   

   if ( inputCtrlDecimal(inputValue, false, null) ) // pas de message si Pb
   { 
      // 2 décimales par défaut
      if (precision == null  ||  precision.length == 0 )
         precision = 2;

      // Les séparateurs de saisie possibles : la vigule ou le point
      // Formats de saisie :  
      // 10,25  ou  10.25 ou ,25 (pour 0,25) ou .20 (pour 0,20)    
      var parts = inputValue.split(".");
      if (parts.length != 2)
         parts = inputValue.split(",");
      
      // Partie entière
      if ( parts[0] == null  || parts[0].length == 0)
         parts[0] = "0";
      
      // Partie décimale
      if ( parts[1] == null  ||  parts[1].length == 0) 
      {
         parts[1] = "0";
         for (i=2; i<=precision; i++)
           parts[1] += "0";
      }
      else if ( parts[1].length < precision )
      {
         for (i=parts[1].length + 1; i<=precision; i++)
           parts[1] += "0";
      }
      else   
      { 
         var f = parseFloat("0." + parts[1]);        
         parts[1] = Math.round(f * Math.pow(10, precision));
         // @author ckh 15/03/05
         // L'arrondissement de la partie décimale produit un reste
         // Ex: 2.9999 rencoie 2.100 car Math.round(0.99*100) = 100, pas 99         
         if ( (String)(parts[1]).length > precision )
         {              
            parts[0] = (String)(parseInt(parts[0]) + 1);
            parts[1] = "0";
         }
         //Si la valeur est inférieur à 10, il faut rajouter un zéro devant
         f = parseFloat(parts[1]);
         if ( (f > 0 ) && (f < 10) )
         {
            var tmp ='';
            for (i=0; i<precision - 1; i++)            
               tmp += "0"; 
            parts[1] = tmp + parts[1];
         }
         
         // Si la valeur décimale est de 2 zéros ou plus
         f = parseFloat("0." + parts[1]);
         if ( f == 0 )
         {
            for (i=2; i<=precision; i++)            
               parts[1] += "0"; 
         }
      }
      valueData = parts[0] + "." + parts[1];             
   }   
   return valueData; 
}


// Renvoie la valeur réelle et le display d'un champ multivalué contrôlé sur liste codée
// Liste réalisée avec les balises HTML : SELECT et OPTION 
// Renvoie null si aucune valeur sélectionnée
function getDataCtrlSelectListeMultiple(fieldElt, schemaField) 
{
   var ret = null;
   // Valeur réelle à retourner
   var valueData = "";  
   var  display = "";

   // Si ce n'est pas une liste à base de balise HTML SELECT
   // on renvoie une chaîne vide
   if ( fieldElt.tagName != "SELECT" )
      return ret;

   // Aucune sélection dans la liste, on retourne une chaîne vide
   if (fieldElt.selectedIndex == -1)
      return ret;
   
   // Séparateur par défaut : le slash 
   var separ0 = schemaField.getAttribute("separ0");
   if (separ0 == null)
      separ0 = "/";
   
   // Séparateur des données réelles
   var separData = separ0;

   // Champ appartenant à un schema composite : pas de séparateur de données
   if ( schemaField.schema.compositeField != null ) 
      separData = "";
   // Champ lié : MULTIPLE_VALUE_SEP (défini dans system.js) est le séparateur 
   //    - entre clés 
   //    - entre les displays des notices
   else if ( schemaField.getLinkTable() )
   {   
      separData = MULTIPLE_VALUE_SEP;
      separ0 = MULTIPLE_VALUE_SEP;
   }   

   // Parcours des elt de la liste
   for (var j=0; j< fieldElt.options.length; j++)
   {
      if (fieldElt.options[j].selected )
      { 
         if ( valueData != "" ) { valueData += separData; }
         if ( display != "" ) { display += separ0; }

         // csi 230507 
         // Pour une forme rejetée (term A utilisé pour term B),
         // value est de la forme recordId_FIELD_RS_REJECT_term B
         // Cette valeur doit être découpée pour fournir recordId (dans valueData) et
         // display rapatrié (dans display)
         var initValue = fieldElt.options[j].value;         
         var parts = initValue.split("_FIELD_RS_REJECT_");
         if (parts.length == 2)
		 {
		    valueData += parts[0];
		    display += parts[1];	    
		 }
		 else
		 {
	        valueData += fieldElt.options[j].value;
	        display += fieldElt.options[j].title;  // Label non tronqué		    
		 }
         // fieldElt.options[j].text  <=> label tronqué
      }      
   }
   ret = new Array(2);
   ret[0] = valueData;
   ret[1] = display;
   
   return ret; 
}

// Renvoie :
//   - la valeur à enregister càd la valeur réelle d'un champ 
// qui dispose du contrôle marc
//   - la valeur passée en paramètre si elle est déja au format marc
// Pour prendre en compte la saisie d'un crochet ouvrant ou fermant, 
// l'utilisateur doit les doubler.
function getDataCtrlMarc(inputValue)
{
   // Pas de valeur saisie, on retourne une chaîne vide 
   if (inputValue.length == 0)
      return "";

   var value = StringUtil_trim(inputValue);
   // Valeur réelle à retourner
   var valueData = value;

   // Cas où inputValue est déja une donnée au format marc
   var posStart = value.indexOf('_FS_');
   if (posStart != -1) // Présence de _FS_
   {
      var str = value.substring(0, posStart);
      // Vérifie que les premiers caractères avant _FS_ sont des nombres
      if ( !isNaN(str) && (str.length >= 1) )
        return valueData; 
   }
        
   // Formatage de la donnée saisie selon le contrôle marc   
   // Position premier '[' 
   var posOpen = value.indexOf('[');
   // Position premier ']'
   var posClose = value.indexOf(']');
   if (    posOpen == 0       // '[' positionné en tête de la donnée   
        && posClose != -1 )   // Présence du ']' dans la donnée
   {
      if (    value.charAt(posOpen + 1) == "[" 
          &&  value.charAt(posClose + 1) == "]" )
           
      {
         // Cas ou les crochets sont doublés pour leur prise en compte
         // Pas d'application du contrôle marc
         valueData  = "0_FS_" + value.substring(posOpen +1, posClose);
         valueData += value.substring(posClose +1);
      }
      else
      {
         // Contrôle marc
         var article  = StringUtil_trim(value.substring(posOpen +1 , posClose));
         if (article.charAt(article.length -1) != "'")  
         article += " ";
         var title = StringUtil_trim(value.substring(posClose+1));
         // Traitement de valueData
         // NbCaractèresMisEntreCrochets_FS_ValeurMiseEntreCrochets 
         // et suite de la donnée saisie
         // Exemple :
         // "4_FS_Les logiciels de gestion" est la valeur codée de   
         // "[Les ]logiciels de gestion"        
         valueData = article.length + "_FS_" + article + title;      
      }   
   }
   else  
   {
      // Ajout de 0_FS_ en tête
      valueData = "0_FS_" + value;  
   } 
   return valueData;
}

// Renvoie la chaîne passée en paramètres en majuscules
function getDataCtrlToMajus(inputValue)
{
   return inputValue.toUpperCase();
}   

// Renvoie la chaîne passée en paramètres en minuscules
function getDataCtrlToMinus(inputValue)
{
   return inputValue.toLowerCase();
}   

//---------------------------
// Fonctions getDisplayDataCtrlNomContrôle :
// A partir de la valeur réelle du champ ces fct renvoient la valeur 
// visible du champ, sur lequel s'applique le contrôle 'Nom contrôle'.
//  - NomFonction  : valeur retournée   
//  - getDisplayDataCtrlDate(isoDate) : date au format jj/mm/aaaa
//  - getDisplayDataCtrlListe(schemaField, listeValue)
//       ==> libellé des éléments la liste avecle séparateur défini 
//           dans ctrl sépar0 
//  - getDisplayDataCtrlMarc(marcValue) : valeur visible
//---------------------------

// A partir d'une date au format ISO : aaaajjmm 
// Renvoie :
//   - la date au format jj/mm/aaaa
//   - la valeur passée en paramètre si elle ne correspond pas à une date ISO
function getDisplayDataCtrlDate(isoDate) 
{
   // Pas de valeur saisie on retourne une chaîne vide
   if ( isoDate.length == 0 )
     return "";

   // Valeur visible à retourner
   var valueView = isoDate;
   
   if (    isoDate.length == 8
        && inputCtrlDate(isoDate, false, null) ) // pas de message si Pb
   {
      // Le jour
      valueView = isoDate.substring(6);
      // Le mois
      valueView += "/" + isoDate.substring(4,6);
      // L'année
      valueView += "/" + isoDate.substring(0,4);
   }
   return valueView;   
}

// A partir du schema d'un champ disposant du ctrl liste, 
// et de sa valeur réelle, cette fonction renvoie une chaine 
// de caractères correspondant au libellés avec utilisation 
// du séparateur paramétrés avec le ctrl separ0 
function getDisplayDataCtrlListe(schemaField, listeValue) 
{
   // Pas de valeur réelle on retourne une chaine vide
   if (listeValue == null  ||  listeValue.length == 0)
      return "";
   
   // Valeur visible à retourner
   var valueView = "";
     
   // Liste des codes de la valeur réelle du champ
   var codes = new Array();

   // Récupération de la liste   
   var liste = schemaField.getAttribute("liste");
   var schemaDesc = schemaField.schema;  
   var list = schemaDesc.getList(liste);

   // Séparateur de la donnée visible
   // Le slash par défaut 
   var separ0 = schemaField.getAttribute("separ0");
   if ( separ0 == null )  { separ0 = "/" };

   // Champ appartenant à un schema composite : pas de séparateur de données
   // réelle entre les codes de liste
   if ( schemaField.schema.compositeField != null ) 
   {
      if ( list ) 
      {
         var codeLength = 0; 
         for (var key in list)
         {
            codeLength = key.length;
            break;
         }
         var oneCode = "";
         for (var j=0; j<listeValue.length; j++)
         {
            for (var i=j; i< j+codeLength && i< listeValue.length; i++)
            {
               oneCode += listeValue.charAt(i);
            }
            j += codeLength - 1;             
            codes[codes.length] = oneCode;
            oneCode = "";
         }
      }   
   }
   else
   {
      // Liste des codes de la valeur réelle du champ
	  //pru 03/09/2008: Cas 416 
	  //   Les codes (valeurs réelles sont séparées par MULTIPLE_VALUE_SEP)
      codes = listeValue.split(MULTIPLE_VALUE_SEP);  
   }   

   for (var i=0; i<codes.length; i++)
   {
      if (valueView != "")  { valueView += separ0; }
      // Code non trouvé dans la liste
      if ( list[codes[i]] == null )
      {
         // TODO : localisation avec une variable 
         valueView += codes[i];
         valueView += " code inconnu dans ";
         valueView += liste; 
      }   
      else
         valueView += list[codes[i]];
   }   
   return valueView;   
}

// A partir de la valeur réelle d'un champ disposant du contrôle marc,
// cette fonction renvoie la valeur à afficher dans la vue marc
function getDisplayDataCtrlMarc(marcValue)
{
   // Pas de valeur saisie on retourne une chaîne vide
   if ( marcValue.length == 0 )
     return "";

   // Valeur visible à retourner
   var valueView = marcValue;
   // Renvoie la valeur visible à partir de '4_FS_les logiciels'
   // soit 'les logiciels'
   var posStart = marcValue.indexOf('_FS_');
   var nbCar = 0;
   if (posStart != -1) // Présence de _FS_
   {
      var str = marcValue.substring(0, posStart);
      // Vérifie que les premiers caractères avant _FS_ sont des nombres
      if ( !isNaN(str) && (str.length >= 1) )
      { 
         // Nbre de caractères de la donnée entre crochets
         nbCar = parseInt(str);
         posStart = posStart + 4;  // _FS_  <== 4 caractères, posStart sur le premier         
         valueView = marcValue.substring(posStart, posStart + nbCar);
         valueView += marcValue.substring(posStart + nbCar); 
      }       
   }
   return valueView;
}

//---------------------------
// Fonctions getInputDataCtrlNomContrôle :
// A partir de la valeur réelle du champ ces fct renvoient la valeur 
// à saisir, pour obtenir cette valeur réelle, sur le champ sur lequel 
// s'applique le contrôle 'Nom contrôle'.
//  - NomFonction  : valeur retournée   
//  - getInputDataCtrlMarc : 
//--------------------------- 


// A partir de la donnée réelle d'un champ disposant du contrôle marc,
// cette fct renvoie la valeur à saisir pour l'obtenir
function getInputDataCtrlMarc(value)
{ 
   // Pas de valeur saisie on retourne une chaîne vide
   if ( value.length == 0 )
     return "";

   // Valeur visible à retourner
   var inputValue = value;
   // Renvoie la valeur saisie à partir de '3_FS_les logiciels'
   // soit '[les ]logiciels'
   var posStart = value.indexOf('_FS_');
   var nbCar = 0;
   if (posStart != -1) // Présence de _FS_
   {
      var str = value.substring(0, posStart);
      // Vérifie que les premiers caractères avant _FS_ sont des nombres
      if ( !isNaN(str) && (str.length >= 1) )
      { 
         // Nbre de caractères de la donnée entre crochets
         nbCar = parseInt(str);
         posStart = posStart + 4;  // _FS_  <== 4 caractères, posStart sur le premier
         inputValue = "";
         if ( nbCar > 0 ) // Cas n_FS_
         {  
            // Mise entre crochet des n caractères       
            inputValue = "[" + value.substring(posStart, posStart + nbCar);
            inputValue += "]";
            inputValue += value.substring(posStart + nbCar);
         }
         else  // Cas où 0_FS_
         {
            // Double les crochets si il y a présence de données entre crochets
            // en tête de la donnée.
            var posOpen = value.indexOf('[');   // Position premier '['
            var posClose = value.indexOf(']');  // Position premier ']'
            if (    posOpen == posStart // '[' positionné en tête de la donnée   
                 && posClose != -1 )    // Présence du ']' dans la donnée
            {
               // Cas où  0_FS_[crochet à conserver] blabla
               inputValue  = "[" + value.substring(posOpen, posClose);
               inputValue += "]" + value.substring(posClose);
            }
            else // Cas où : 0_FS_Pas de données entre crochet
            {
               inputValue += value.substring(posStart);
            }
         }            
      }       
   }
   return inputValue;
}

//---------------
// Fonctions inputCtrlNomContrôle :
// Elles renvoient :
//   - true lorsque le contrôle 'NomContrôle' s'applique avec succés.
//   - false + message (ou non) lorsque le contrôle 'Nom Contrôle' 
//       ne s'applique pas avec succès.
// inputCtrlDate(inputValue, showMessage, fieldLabel) : 
//   ==> true si inputValue au format jj/mm/aaaa ou jj.mm.aaaa
// inputCtrlDecimal(inputValue, showMessage, fieldLabel)
//   ==> true si inputValue est un nbre décimal (séparateur point ou virgule)
//       ou un nbre entier
// inputCtrlInteger(inputValue, showMessage, fieldLabel) : 
//   ==> true si inputValue est un nombre entier
// inputCtrlLenMin(inputValue, showMessage, len, fieldLabel) : 
//   ==> true si inputValue a une longeur >= à len
// inputCtrlMultipleMultMaxi(inputValue, schemaField, showMessage, fieldLabel)
//   ==> true si le nbe d'éléments sélectionnés <= mult_maxi
//       true si le chp ne dipose pas du ctrl multiple                                   
// inputCtrlOblig(inputValue, showMessage, fieldLabel) :
//   ==> true si inputValue est a une longeur > 0
// inputCtrlValMaxi(inputValue, showMessage, valMaxi, fieldLabel ) :
//   ==> true si inputValue est un entier <= valMaxi
// inputCtrlValMini(inputValue, showMessage, valMini, fieldLabel )
//   ==> true si inputValue est un entier >= valMini
//----------------

function getVerificateCtrl(inputValue, schemaField, showMessage, fieldLabel)
{        
   // Affichage des messages true ou false
   //var showMessage = true;
   if ( fieldLabel == null  ||  fieldLabel.length == 0)
      fieldLabel = schemaField.getAttribute("screen_name");

   var result = true;
   var is_date = ( schemaField.getAttribute("date") == "true" );
   var is_decimal = ( schemaField.getAttribute("decimal") == "true" );
   var is_integer = ( schemaField.getAttribute("integer") == "true" );
   var len_mini = schemaField.getAttribute("len_mini");
   var liste = schemaField.getAttribute("liste");
   var is_multiple = ( schemaField.getAttribute("multiple") == "true" );
   var mult_maxi = schemaField.getAttribute("mult_maxi");     
   var is_oblig = ( schemaField.getAttribute("oblig") == "true" );
   var val_maxi = schemaField.getAttribute("val_maxi");
   var val_mini = schemaField.getAttribute("val_mini");
   var script = schemaField.getAttribute("script");
   var audible_alert = schemaField.getAttribute("audible_alert");

   if ( is_date )
      if ( ! inputCtrlDate(inputValue, showMessage, fieldLabel) )
         return false;
   if ( is_decimal )
      if ( ! inputCtrlDecimal(inputValue, showMessage, fieldLabel) )
         return false;
   if ( is_integer && !is_date )
      if ( ! inputCtrlInteger(inputValue, showMessage, fieldLabel) )
         return false;
   if ( len_mini != null )
      if ( ! inputCtrlLenMin(inputValue, showMessage, len_mini, fieldLabel) )
         return false;
   // Liste multiple      
   if ( liste != null  &&  is_multiple )
      if ( ! inputCtrlMultipleMultMaxi(inputValue, schemaField, showMessage, fieldLabel) )
         return false;
   if ( is_oblig )
      if ( ! inputCtrlOblig(inputValue, showMessage, fieldLabel) )
         return false;   
   if ( val_maxi != null )
      if ( ! inputCtrlValMaxi(inputValue, showMessage, val_maxi, fieldLabel) )
         return false;
   if ( val_mini != null )
      if ( ! inputCtrlValMini(inputValue, showMessage, val_mini, fieldLabel) )
         return false;
   if( script != null)
      if ( ! inputCtrlExecuteScript(inputValue, showMessage, script, fieldLabel, audible_alert) )
         return false;
         
   return result;
}   

function inputCtrlExecuteScript(inputValue, showMessage, script, fieldLabel, audible_alert)
{
   var scriptObjet = eval("new "+script+"()");
   return scriptObjet.execute(inputValue, fieldLabel, showMessage, audible_alert);
}

// Renvoie le message d'erreur sous le format :
//   - Champ : label du champ ( en fonction du mode choisi)
//   - Valeur saisie : valeur saisie dans la zone de saisie associée au champ (non affichée pour tous les contrôles)
//   - Message d'erreur 
function inputCtrlGetMessageError(fieldLabel, fieldDisplayValue, errorMessage, arg)
{
   var message = _getFormatedMessage(fieldLabel, fieldDisplayValue, errorMessage, arg);
   alert(message);   
}

// Renvoie le message à confirmer sous le format :
//   - Champ : label du champ ( en fonction du mode choisi)
//   - Valeur saisie : valeur saisie dans la zone de saisie associée au champ (non affichée pour tous les contrôles)
//   - Message d'information
function inputCtrlGetConfirmMessage(fieldLabel, fieldDisplayValue, errorMessage, arg)
{
   var message = _getFormatedMessage(fieldLabel, fieldDisplayValue, errorMessage, arg);
   return confirm(message);
}

// Privée
function _getFormatedMessage(fieldLabel, fieldDisplayValue, errorMessage, arg)
{
   var message = "";
   if ( fieldLabel != null  &&  fieldLabel.length > 0)
      message += mess_control_input_field + fieldLabel + "\n" ;

   if ( fieldDisplayValue != null  &&  fieldDisplayValue.length > 0)
      message += mess_control_input_value + fieldDisplayValue + "\n" ;
   
   message += "\n" + errorMessage;
   if ( arg != null )
      message += arg;
      
   return message;
}

// 
function inputCtrlDate(inputValue, showMessage, fieldLabel) 
{
   // Pas de valeur saisie 
   if (inputValue.length == 0)
      return true;

   // Suppression des espaces de début et de fin
   inputValue = StringUtil_trim(inputValue);

   // Les séparateurs de saisie possibles : le slash ou le point
   // Formats de saisie :  jj/mm/aaaa  ou  jj.mm.aaaa ou aaaammjj    
   var parts = inputValue.split("/");
   if (parts.length != 3)
     parts = inputValue.split("."); 
   
   // Date saisie au format ISO
   if (    parts.length != 3
       &&  inputCtrlInteger(inputValue, false, null) // pas de message si Pb     
       &&  inputValue.length == 8  )
   {
      parts[0] = inputValue.substring(6);   // jj
      parts[1] = inputValue.substring(4,6); // mm
      parts[2] = inputValue.substring(0,4); // aaaa  
   }       
   
   var isOk = false;
   
   if ( parts.length == 3 )
   {
	  // sau 29.01.2009 BUG#735 : Saisie dans un champ de type date : formatage 
	  // automatique erroné de Flora si saisie erronée au format jj/mm/aa
      // ==> Test de la Longueur des données saisies  jj, mm, aaaa
      if (   parts[0].length == 2 
          && parts[1].length == 2
          && parts[2].length == 4 )
    	  isOk = true;
      
      // jj, mm, aaaa doivent être des entiers
      if ( isOk )
      {
	      for ( var i = 0; i <parts.length ; i++ )
	      {
	         if ( ! inputCtrlInteger(parts[i], false, null) ) // pas de message si Pb
	         {
	            isOk = false;
	            break;
	         }
	      }
      }
   }
   
   // Ce n'est pas une date correcte
   if (    ! isOk
       ||  ! DateUtil_checkDate(parts) )
   {
      if (showMessage)
         inputCtrlGetMessageError(fieldLabel, inputValue, mess_control_date2, null);
      return false;
   }
return true; 
}

// 
function inputCtrlDecimal(inputValue, showMessage, fieldLabel) 
{
   if ( ! isNaN(inputValue) ) inputValue = "" + inputValue;
   // Pas de valeur saisie 
   if (inputValue.length == 0)
      return true;

   // Valeur négative : suppression du premier caractère
   if ( inputValue.charAt(0) == "-" )
      inputValue = inputValue.substr(1);
      
   var val = 0;
   var ok = 0;      

   // Les séparateurs de saisie possibles : la vigule ou le point
   // Formats de saisie :  
   // 10,25  ou  10.25 ou ,25 (pour 0,25) ou .20 (pour 0,20)    
   var parts = inputValue.split(".");

   if (parts.length != 2)
     parts = inputValue.split(",");

   // Cas d'un nombre décimal         
   if (parts.length == 2)
   {
      // Partie entière
      if ( parts[0].length == 0  &&  parts[1].length > 0 ) 
         ok++;
      else
      {    
         val = parseInt(parts[0],10); 
         if ( inputCtrlInteger(parts[0], false, null)  &&  0<=val )
            ok ++;
      }      
      // Partie décimale 
      if (parts[1].length == 0  &&  parts[0].length > 0 ) 
         ok++;
      else
      {        
         val = parseInt(parts[1],10);
         if ( inputCtrlInteger(parts[1], false, null) &&  0<=val )
            ok ++;
      }      
   }
   // Cas d'un nombre entier
   else if ( parts.length == 1 )
   { 
      if ( inputCtrlInteger(parts[0], false, null)  &&  0<=val )
         ok = 2;
   }      

   if ( ok != 2 ) 
   {
      if (showMessage) 
         inputCtrlGetMessageError(fieldLabel, inputValue, mess_control_decimal, null);
      return false;
   }
return true; 
}

/**
 * Object retourne par inputCtrlEanIsbn et contenant la valeur passé en arguement
 * (cf.inputValue) formatée et la valeur convertie correspondante.
 * Si la valeur original est un ISBN ou un ISSN la valeur convertie est un EAN
 * Si la valeur original est un EAN la valeur convertie est un ISBN ou un ISSN
 */
function IsbnData()
{
   var formatedValue;
   var convertedValue;
}

// Applique le contrôle ean_isbn
// Renvoie :
//  Un objet de type IsbnData contenant :
//            - l'isbn/issn./ean formaté (avec présence des tirets) si la valeur passée en 
//              paramètre est un ISBN 10 ou 13  ou un ISSN
//            - la convertion de ce isbn/issn/ean (cf. IsbnData)
//             ou          
//            - l'isbn/issn corrigé s'il y a seulement une erreur du chiffre de contrôle 
//              et que l'utilisateur a confirmé cette proposition de correction
//            - la convertion de ce isbn/issn/ean corrigé (cf. IsbnData)
//             ou
//            - la valeur passée en paramètre et affiche un message d'erreur si la valeur 
//              passée en paramètre ne représente pas un isbn/issn/ean
//            - la convertion vide ("")
function inputCtrlEanIsbn(inputValue, showMessage, fieldLabel, audibleAlert) 
{  
   var result = new IsbnData();
   result.formatedValue=inputValue;
   result.convertedValue="";
   
   if (   inputValue == null 
       || inputValue.length == 0)
      return result;
      
   // Appel à servlet InputManager :
   var action = sysGetAppRoot() + "/servlet/InputManager";
   action += "?action=checkISBN&isbn="
   action += inputValue;
   
   var xmlDoc = XMLUtil_LoadXML(action);
   
   // Les erreurs remontées sont liées au format de l'isbn, pas à un problème 
   // de l'appli d'ou l'action null.
   var errorMessage = XMLUtil_IsError(xmlDoc)
   if ( errorMessage != null )
   {
      var correctIsbnElems = xmlDoc.getElementsByTagName("correctIsbn");
      var convertedValueElems = xmlDoc.getElementsByTagName("convertedValue");
      if (    correctIsbnElems != null 
          &&  correctIsbnElems.length > 0)
      {
         var correctISBN = correctIsbnElems[0].getAttribute("value");
         var correctedValue = "";
         if(convertedValueElems != null && convertedValueElems.length > 0)
            correctedValue = convertedValueElems[0].getAttribute("value");
            
         // La clef de contrôle de cet identifiant n'est pas correcte.
         // Voulez-vous la modifier automatiquement ?
         if(   correctISBN != null 
            && correctISBN.length != 0 )
         {
            if ( audibleAlert == "true" )
               sysBeep();
               
            var confirmMessage = sysGetMessage("control.isbn.correction.request");
            if ( inputCtrlGetConfirmMessage(fieldLabel, inputValue, confirmMessage, null) )
	         {
               result.formatedValue = correctISBN;
               result.convertedValue = correctedValue;
	         }
	      }   
      }
      else
      {
         // Affichage d'un message d'erreur
         if ( showMessage )
         {
            if ( audibleAlert == "true" )
               sysBeep();
            
            inputCtrlGetMessageError(fieldLabel, inputValue, errorMessage, null);
         }   
      }
   }
   else
   {
      // Isbn correct / formaté
      var isbnElems = xmlDoc.getElementsByTagName("isbn");
      if (    isbnElems != null 
          &&  isbnElems.length > 0 )
      {
         result.formatedValue=isbnElems[0].getAttribute("value");
         result.convertedValue=isbnElems[0].getAttribute("convertedValue");
      }
   }
   return result;
}

// 
function inputCtrlInteger(inputValue, showMessage, fieldLabel)
{
   // Pas de valeur saisie 
   if (inputValue.length == 0)
      return true;

   for (var i=0; i<inputValue.length; i++)
   {
       var n = parseInt(inputValue.charAt(i));
       if (isNaN(n))
       {
          if (showMessage)
             inputCtrlGetMessageError(fieldLabel, inputValue, mess_control_integer, null);
          return false;
       }   
   }       
   return true;
}

//
function inputCtrlLenMin(inputValue, showMessage, len, fieldLabel)
{
   // Pas de valeur saisie 
   if (inputValue.length == 0)
      return true;

   if ( inputValue.length >= len ) 
      return true;
   if (showMessage)
      inputCtrlGetMessageError(fieldLabel, inputValue, mess_control_lenmin, len);
   return false;
}

// Contrôle le nombre de sélections max dans une liste 
// créé via les balises SELECT et OPTION
function inputCtrlSelectListeMultiple(fieldElt, schemaField, showMessage, fieldLabel)
{
   var is_multiple = ( schemaField.getAttribute("multiple") == "true" );
   
   // Si ce n'est pas une liste à base de balise HTML SELECT
   // ou si la liste n'est pas multiple
   // on renvoie true
   if ( fieldElt.tagName != "SELECT"  ||  !is_multiple )
      return true;

   // Valeur par défaut de mult_maxi = 16    
   var mult_maxi = schemaField.getAttribute("mult_maxi");           
   if ( mult_maxi == null )
      mult_maxi="16";
   
   if ( fieldElt && fieldElt.options )
   {
      var nb_selected = 0;
      for (var j=0; j< fieldElt.options.length; j++)
      {
         if (fieldElt.options[j].selected ) { nb_selected ++; }
      }
      
      if ( nb_selected > parseInt(mult_maxi, 10) )
      {
         if ( showMessage ) 
         {  
            if ( fieldLabel == null  ||  fieldLabel.length == 0)
               fieldLabel = schemaField.getAttribute("screen_name");         
            inputCtrlGetMessageError(fieldLabel, null, mess_control_liste_multi2, mult_maxi);
         }
         return false;
      }
      return true;
   }
   return false;
}

// A partir de la valeur réelle du champ, contrôle que le nombre maximal
// de sélections n'est pas dépassé 
function inputCtrlMultipleMultMaxi(inputValue, schemaField, showMessage, fieldLabel)
{
   if (inputValue.length == 0)
      return true;

   // Si le champ contrôlé n'est pas contrôlé sur multiple
   // on renvoie true      
   var vmult_maxi = getValueCtrlMultMaxi(schemaField);
   if ( vmult_maxi == null)  // null si pas le contrôle 'multiple'
      return true;
   
   // Séparateur par défaut : le slash 
   var separ0 = schemaField.getAttribute("separ0");
   
   // Champ lié :  MULTIPLE_VALUE_SEP est le séparateur entre clés
   if ( schemaField.getLinkTable() )  
      separ0 = MULTIPLE_VALUE_SEP;
   else if ( separ0 == null )
      separ0 = "/";

   // Liste des codes de la valeur réelle du champ
   var codes = inputValue.split(separ0);  
   if ( codes  &&  codes.length > vmult_maxi )
   {
      if ( showMessage ) 
      {  
         if ( fieldLabel == null  ||  fieldLabel.length == 0 )
            fieldLabel = schemaField.getAttribute("screen_name");         
         inputCtrlGetMessageError(fieldLabel, null, mess_control_liste_multi2, vmult_maxi);
      }
      return false;
   }
   return true;
}

// 
function inputCtrlOblig(inputValue, showMessage, fieldLabel)
{
   if (inputValue.length == 0)
   {
      if (showMessage)
         inputCtrlGetMessageError(fieldLabel, null, mess_control_oblig, null); 
      return false;
   } 
   return true;   
}

//
function inputCtrlValMaxi(inputValue, showMessage, valMaxi, fieldLabel )
{
   // Pas de valeur saisie 
   if (inputValue.length == 0)
      return true;

   // Vérification que la donnée saisie est un nombre entier
   if ( inputCtrlInteger(inputValue, true, fieldLabel) )
   {
      var val = parseInt(inputValue);
      if ( val <= valMaxi )
         return true;
      if (showMessage)
         inputCtrlGetMessageError(fieldLabel, inputValue, mess_control_valmax, valMaxi);
   }
   return false;
}

//
function inputCtrlValMini(inputValue, showMessage, valMini, fieldLabel)
{
   // Pas de valeur saisie 
   if (inputValue.length == 0)
      return true;

   // Vérification que la donnée saisie est un nombre entier
   if ( inputCtrlInteger(inputValue, showMessage, fieldLabel) )
   {
      var val = parseInt(inputValue);
      if ( val  >= valMini )
         return true;
      if (showMessage)   
         inputCtrlGetMessageError(fieldLabel, inputValue, mess_control_valmin, valMini);
   }
   return false;
}


//-----------
// Cette fct renvoie : 
// - null si pas crtl 'multiple'
// - 16 si ctrl multiple et (pas ctrl mult_maxi ou ctrl mult_maxi non correct)
// - la valeur du ctrl mult_maxi 
function getValueCtrlMultMaxi(schemaField)
{
   var is_multiple = (schemaField.getAttribute("multiple") == "true");
   
   // Si pas ctrl 'multiple' on retourne "null"
   if (! is_multiple )
     return null;
   
   var mult_maxi = schemaField.getAttribute("mult_maxi");
   // Valeur par défaut, lorsque ctrl multiple 
   // et pas ctrl mult_maxi 
   var vmult_maxi = 16;
   
   if (    mult_maxi != null  &&  mult_maxi.length !=0
        && inputCtrlInteger(mult_maxi, false, null) )
   {
      // Présence du ctrl 'mult_maxi' avec une valeur numérique
      vmult_maxi = parseInt(mult_maxi, 10);
   }   
   return vmult_maxi;
}


//pattern Factory
/**
 * Instance unique de la factory
 **/
var m_componentFactory;

/**
 * utiliser getComponentFactoryInstance
 **/
function ComponentFactory()
{ 
//    this.m_lastId = 0;
}

/**
 * @return l'instance de la factory (singleton)
 **/
function getComponentFactoryInstance()
{
    if(m_componentFactory==null)
    {
       m_componentFactory = new ComponentFactory();
    }
    return m_componentFactory;
}

/**
 * @return un identifiant unique pour les composants
 **/
//ComponentFactory.prototype.getNextId=function(className,initialData)
//{
//    var newId = this.m_lastId++;
//    return "UIComponent_"+newId;
//}

/** 
 * Note la forme de l'id et le nom de l'element créer dépendent du composant.
 * 
 * @param className: classe du composant à instantié
 * @param fieldName: nom du composant instantiée
 * @param params: paramètre du composant
 * @param elementID: identifiant unique pour le composant.
 * @return un composant de type UIComponent
 **/
ComponentFactory.prototype.getComponent=function(className, sourceName, tableName, fieldName, params, elementID)
{
    var component = eval("new "+className+"()");
    if(component.constructor==UIComponent)
    {
        component.setId(elementID);
        component.init(sourceName,tableName,fieldName,params);
        return component;
    }
    return null;
}

///////////////// UIComponent mother class ///////////////////////////////////

/**
 * Classe mère des composants générant du code html
 **/
function UIComponent()
{
   this.m_params;
   this.m_id;
   this.m_sourceName;
   this.m_tableName;
   this.m_fieldName;
   this.m_langDir="ltr";
   this.img_path = null;
}

/**
 * Initialise le composant graphique avec le paramètre
 * Les paramètres : liste et initValue sont positionnés par inputWidget.js
 * @param initialData: Array de paramètres. valeur initial permettant d'initialiser le composant.
 **/
UIComponent.prototype.init = function (sourceName,tableName,fieldName,params)
{
   this.m_params=params;
   this.m_sourceName=sourceName;
   this.m_tableName=tableName;
   this.m_fieldName=fieldName;
}

/**
 * Donne un identifiant unique au composant
 **/
UIComponent.prototype.setId = function (id)
{
    this.m_id=id;
}

/**
 * Configure le nom du champ
 **/
UIComponent.prototype.setFieldName = function (fieldName)
{
    this.m_fieldName=fieldName;
}



/**
 * Configure la direction de lecture
 **/
UIComponent.prototype.setLangDir = function (langDir)
{
    this.m_langDir=langDir;
}

/**
 * @return un objet de type tag capable de générer le code html
 * correspondant à l'objet UIComponent
 **/
UIComponent.prototype.getWidget = function ()
{
   return null;
}

/**
 * @return le chemin complet d'un image
 **/
UIComponent.prototype.getImageURL = function (relativePath)
{
   if(this.img_path==null)
   {
      this.img_path="icons/css/";
      if ( typeof(sysGetSystemFrame)!="undefined" )
         this.img_path += getUserCss()+"/";
      else
         this.img_path += "default/";
   }
   return this.img_path+relativePath;
}

/**
 * @return validation de la donnée contenue par le composant sur le submit
 * peut être redéfinie par la composant
 **/
UIComponent.prototype.validateOnSubmit = function ()
{
   return true;
}

///////////// LISTENER      //////////////////////////////////////
/**
 * Object notified when assistant change value
 */

function CompomentListener(compomentName,compomentid)
{
   this.m_fieldName = compomentName;
   this.m_fieldId =   compomentid;
}

/**
 * Méthode du listener appellé lorsqu'un élément change. Cette méthode
 * n'est malheureusement pas utilisé par tous le s composant. le concept
 * a été introduit après que plusieurs composant est déjà été créé.
 *
 * @param value nouvelle valeur
 * @param htmlElementSource Element DOM correspondant à l'élément HTML impacté
 */
CompomentListener.prototype.valueChanged = function (value,htmlElementSource)
{
   var view = null;
   if(typeof(getView)!="undefined")
      view=getView();
   try
   {
      //il existe une vue, on lock la vue pour empêcher son enregistrement tant que les
      //contrôle sur le champ en cour de modification n'ont pas été effectuées
      if(view!=null)
      {
         view.lockView();
      }
      
      var codeResult = this.toOverride(value,htmlElementSource);
      if( codeResult!=false )
      {
         updateData(value,this.m_fieldName, this.m_fieldId);// pour saisie std
         if(view!=null)
          {
            //pru: 27/02/2008, ajout de la méthode permettant de vérifier les autres contrôles
             view.checkControls(this.m_fieldName, this.m_fieldId);
             view.updateData(this.m_fieldName, this.m_fieldId,true);
             view.showInputFieldDisplayValue(this.m_fieldId);
          }
       }
   }
   catch(exception)
   {
      //Un probleme est survenue pendant le traitement
   }
   if(view!=null)
   { 
      view.unLockView();
   }
}


/**
 * Méthode à surcharger pour effectuer un traitement avant lors de la mise à jour
 * du champ
 * @param value, nouvelle valeur
 * @param htmlElementSource, element contenant le valeur saisie
 * @return retourne false si le traitement doit être stoppé
 */
CompomentListener.prototype.toOverride = function (value,htmlElementSource)
{
}

/** tableau contenant les listeneurs de la page*/
var m_listener_array = new Array();

/**
 * lie le listener listener au composant d'id compoment_id.
 * Il ne peut y avoir qu'un listener pour un composant.
 * On ne garde que le dernier ajouté
 */
function addListener(compoment_id,listener)
{
   if(compoment_id!=null)
   {
      m_listener_array[compoment_id]=listener;
   }
}

/**
 * @return le listener pour ce composant ou null
 */
function getListener(compoment_id)
{
   return m_listener_array[compoment_id];
}

/**
 * Notify le listener configurer pour elementSource.
 * @param l'élément dom représentant l'élément html de saisie
 */
function onValueChange(elementSource)
{
   var listener = getListener(elementSource.id);
   if(listener!=null)
   {
      listener.valueChanged(getElementValue(elementSource,false),elementSource); 
   }
}

/**
 * Met a jour la valeur du composant identifier par targetInputId
 * avec value. Le listener lié a ce composant est notifié.
 * Appellé depuis plusieurs assistant de saisie (jsp)
 * @param value string
 * @param htmlElementSource element html DOM
 */
function updateValue(targetInputId,value,htmlElementSource)
{
   var target = null;
   if(htmlElementSource!=null)
      target = htmlElementSource;
   else
      target = document.getElementById(targetInputId);
   if(target != null)
      HTMLUtil_setElementValue(target,value);
   var listener = m_listener_array[targetInputId];
   //pru, il exist des fonctions native tels que sort de base dans les array
   //si l'on a un champ sort cela pose pb
   if(listener!=null && typeof(listener)!='function')
   {
      listener.valueChanged(value,htmlElementSource);
   }
}

/**
 * Met a jour la valeur du composant identifier par targetInputId
 * avec value. Le listener lié a ce composant est notifié.
 * Appellé depuis plusieurs assistant de saisie (jsp)
 * Uniquement avec des assistants sur liste 
 * @param value Array
 */
function updateListValue(targetInputId,value)
{
   var target = document.getElementById(targetInputId)
   if(target != null)
      HTMLUtil_setSelectValues(target,value);
   var listener = m_listener_array[targetInputId];
   //pru, il exist des fonctions native tels que sort de base dans les array
   //si l'on a un champ sort cela pose pb
   if(listener!=null && typeof(listener)!='function')
   {
      listener.valueChanged(value,target);
   }
}

/**
 * update sur liste, supprime les anciennes valeurs puis ajoute les
 * nouvelles
 * @param target, html select receiving data
 * @param array containing option value
 */
 function HTMLUtil_setSelectValues(target,values)
 {
    var elt_type = target.type;
    if ( (elt_type == 'select-one') || (elt_type == 'select-multiple') )
    {
       listRemoveAllOptions(target);
       for(var i=0;i<values.length;i++)
       {
          var value = values[i];
          var newOption = new Option(value, value);
          target.options[target.options.length] = newOption;
       }
    } else
    {
       var value = "";
       if(values.length>0)
          value+=values[0];
       for(var i=1;i<values.length;i++)
       {
          value+=MULTI_VALUE_SEP; //cf. form.js
          value+=values[i];
       }
       HTMLUtil_setElementValue(target,value);
    }
 }
///////// RADIO BUTTON //////////////////////////////////////////

/**
 * key component name
 * value component id.
 * contient les noms des composants et les id respectif par ordre de création.
 * Les composants ne sont pas tous enregistrés seul grouping a field choice le sont
 * pour l'instant
 */
var m_componentRegistry=new Array();
var m_componentCreationOrder= new Array();

function register(name,id)
{
	var lastIndex = m_componentCreationOrder.length;
	m_componentRegistry[lastIndex]=id;
	m_componentCreationOrder[lastIndex]=name;
}

function getLastFieldForName(name)
{
	for(var i=m_componentCreationOrder.length;i>=0;i--)
	{
		var tmpName = m_componentCreationOrder[i];
		if(name == tmpName)
		{
			var id = m_componentRegistry[i];
			return document.getElementById(id);
		}
	}
	return null;
}


/**
 * UIComponent Utilisé pour utiliser un script de validation en plus des contrôles
 * habituelle
 * Les paramètres requit sont : 
 *    script --> Nom du script à appeller. 
 **/
ScriptValidation.prototype = new UIComponent();

function ScriptValidation()
{
   this.parent = UIComponent;
   this.parent();
   this.listener=null;
}

/**
 * @return un objet de type input appellant un script sur l'action onchange
 * en plus des contrôles habituel.
 **/
ScriptValidation.prototype.getWidget = function ()
{

    var scriptObjet = null;
    var className  = null;
    var size       = null;
    var inputName  = null;
    var initValue  = null;
    var screenName = null;
    var attribs = new Array();
    
    for(var param in this.m_params)
    {
      if(param=="script")
         scriptObjet = this.m_params["script"];
      if(param=="className")
         className = this.m_params["className"];
      if(param=="size")
         size = this.m_params["size"];
      if(param=="inputName")
         inputName = this.m_params["inputName"];
      if(param=="initValue")
         initValue = this.m_params["initValue"];
      if(param=="screenName")
         screenName = this.m_params["screenName"];
      if(param.indexOf("att:")==0)
      {
         attribs[param.substring(4)]=this.m_params[param];
      }
    }

    
    
    if(className==null)
      className="marc";
                     
    if(size==null)
       size=MAX_INPUT_SIZE;
   
    var inputId = this.m_id+"_input";
    if(inputName==null)
       inputName=inputId;
       
   var widget = new Tag("div").att("id",this.m_id+"_input")
                    .att("class", "marc").att("valign", "middle")
                    .att("size", MAX_INPUT_SIZE).att("dir",this.m_langDir);
    
   var tag = new Tag("input").att("id",this.m_id).att("name", inputName).att("type","text")
          .att("class", className).att("dir",this.m_langDir).att("size", size)
          .att("onchange", "onValueChange(this)");
    //les attributs sont écrase par ceux du contrôle original
    //inputName, className et size sont filtrer par l'appelant.
    for(var attName in attribs)
    {
      if(attName!="onchange")
      {
         tag.att(attName,attribs[attName]);
      }
      else
      {
         var lastEvent = tag.tagAttributes[attName];
         tag.att(attName,attribs[attName]+";"+lastEvent);
      }
    }
          
    if(initValue!=null && initValue!="")
    {
      tag.att("value", initValue);
    } 
    widget.setBody(tag.text());
    this.listener = new ScriptValidationListener(this.m_fieldName,this.m_id,scriptObjet,screenName);
    addListener(this.m_id,this.listener);
    
    return widget;
}

/**
 * Appelle le script de validation. méthode devant être appellée par le formulaire
 * contenant le composant
 */
ScriptValidation.prototype.validateOnSubmit = function ()
{
   if(this.listener!=null)
   {
      var elementSource = document.getElementById(this.m_id);
      if(elementSource!=null)
      {
         var value = getElementValue(elementSource,false);
         this.listener.toOverride(value,elementSource);
      }
   }
   return true;
}

/**
 * Listener appellé après modification du champ
 */
ScriptValidationListener.prototype = new CompomentListener();

function ScriptValidationListener(compomentName,compomentid,scriptObjet,screenName)
{
   this.parent = CompomentListener;
   this.parent(compomentName,compomentid);
   this.scriptObjet = scriptObjet;
   this.screenName=XMLUtil_replaceEntities(screenName);
}

/**
 * Appelle l'execution d'un script contenant deux paramètres 
 * Le premier est l'élément html contenant la valeur
 * le second est le screen name du champ
 */
ScriptValidationListener.prototype.toOverride = function (value,htmlElementSource)
{
   var scriptObjet = "new "+this.scriptObjet+"()";
   var objetJs = eval(scriptObjet);
   return objetJs.execute(htmlElementSource,this.screenName);
   
}

/**
 * UIComponent générant des radios boutons
 * Les paramètres requit sont : 
 *    liste --> liste des valeurs disponible. Positionné dans inputWidget.js
 *    initValue --> valeur initial. Positionné dans inputWidget.js
 **/
RadioComponent.prototype = new UIComponent();

function RadioComponent()
{
   this.parent = UIComponent;
   this.parent();
}

/**
 * @return un objet de type tag capable de générer des radios boutons
 **/
RadioComponent.prototype.getWidget = function ()
{
    var list = this.m_params["liste"];
    var initValue = this.m_params["initValue"];

    var widget = new Tag("div").att("id",this.m_id+"_input")
                     .att("class", "marc").att("valign", "middle")
                     .att("size", MAX_INPUT_SIZE).att("dir",this.m_langDir);
    var body = "";
    if(list!=null) 
       var input_id = 0;
       for (var key in list)
       {
           input_id++;
           var unique_id = this.m_fieldName+input_id;
           var value= list[key];
           var labelTag = new Tag("label").att("for",unique_id).att("style","vertical-align: middle;").att("dir",this.m_langDir);
           labelTag.setBody(value);
           var tag = new Tag("input").att("type","radio")
                         .att("name", this.m_id+this.m_fieldName).att("id",unique_id)
                         .att("value", key).att("style","vertical-align: middle;").att("dir",this.m_langDir)
                         .att("onChange", "updateData('"+key+"','"+this.m_fieldName+"','"+this.m_id+"')");

           if(initValue != null && initValue == key )
           {
              tag.att("checked","checked");
              if(initValue == null)
                  initValue = key;
           }
           body+= tag.text()+labelTag.text();
        }
     widget.setBody(body);
   return widget;
}


///////////////// FILECHOOSER UI class ///////////////////////////////////

/**
 * UIComponent générant des radios boutons
 * Les paramètres requit sont : 
 *    set --> identifiant du set contenant les fichiers accessible cf resource.xml
 *    initValue --> valeur initial. Positionné dans inputWidget.js
 **/
FileChooserComponent.prototype = new UIComponent();

function FileChooserComponent()
{
   this.parent = UIComponent;
   this.parent();
}

/**
 * @return un objet de type tag capable de générer un champ texte permettant de saisir un nom de fichier
 **/
FileChooserComponent.prototype.getWidget = function ()
{
    var setFieldName = this.m_params["set"];
    var initValue = this.m_params["initValue"];
    if(initValue==null)
      initValue="";
    var className = this.m_params["className"];
    if(className==null)
       className="marcReadOnly";
    var size =      this.m_params["size"];
    if(size==null)
      size = MAX_INPUT_SIZE;
    var inputName = this.m_params["inputName"];
       
    if(setFieldName==null)
        setFieldName="";
    var widget = new Tag("div").att("class", "marc").att("valign", "middle")
                               .att("size", MAX_INPUT_SIZE).att("dir",this.m_langDir);
    var body = "";
    var inputId = this.m_id+"_input";
    if(inputName==null)
       inputName=inputId;
             
    var tag = new Tag("input").att("name", inputName).att("id",inputId).att("readonly", "readonly")
          .att("value", initValue).att("class", className).att("dir",this.m_langDir)
          .att("title", initValue )
          .att("size", size );
    if(typeof(getView)!="undefined")
    {
       tag.att("onChange", "getView().updateData('"+this.m_fieldName + "','" + this.m_id+"', true);getView().showInputFieldDisplayValue('" + this.m_id +"') ;")
          .att("onKeyUp", "getView().showInputFieldDisplayValue('" + this.m_id +"')")
          .att("onMouseOver", "getView().showInputFieldDisplayValue('" + this.m_id +"')")
          .att("onMouseOut", "getView().hideInputFieldDisplayValue()");
    }
    body+=tag.text();
                         
   var img = new Tag("img").att("src", this.getImageURL("tools/assist_file.gif"));
         img.att("class", "ImgInput").att("border", "0").att("title", sysGetMessage("assistant.fileChooser")); 
   // tdn 27/07/2007 Ajoute le paramètre forceReload s'il a été spécifié dans le controle
   var forceReload = "false";
   if ( this.m_params["forceReload"] == "true" )
   {
      forceReload = "true";
   };         
   var boutonTag = 
            new Tag("a").setBody(img.text())
             .att("href", "javascript:displayFileChooser('"+inputId+"','"+setFieldName+"', false, false," + forceReload + ")");         
                         
    body+=boutonTag.text();
    
   addListener(inputId,new FileChooserListener(this.m_fieldName,this.m_id,inputId));
    
    widget.setBody(body);
    return widget;
}

FileChooserListener.prototype = new CompomentListener();

function FileChooserListener(compomentName,compomentid,displayId)
{
   this.parent = CompomentListener;
   this.parent(compomentName,compomentid);
   this.displayId = displayId;
}

FileChooserListener.prototype.toOverride = function (value,htmlElementSource)
{
    var target = document.getElementById(this.displayId);
    if(target!=null)
      target.setAttribute("title",value);
}


///////////////////// CHECKBOX ///////////////////////////////////

/**
 * UIComponent générant des check box
 * Les paramètres requit sont : 
 *    liste     --> liste des valeurs disponibles
 *    initValue --> valeur initial. Positionné dans inputWidget.js
 *    separator --> peut être null, définie le sépareur pour le champ composé. s'il est
 *                  null, la taille des sous champs est deduite de la taille de la première
                    clef de la liste.
 **/
CheckBoxComponent.prototype = new UIComponent();

function CheckBoxComponent()
{
   this.parent = UIComponent;
   this.parent();
}


/**
 * @return un objet de type tag capable de générer des check box
 **/
CheckBoxComponent.prototype.getWidget = function ()
{
    var list = this.m_params["liste"];
    var initValue = this.m_params["initValue"];
    var keySize=null;
    var separator = this.m_params["separator"];

    if(separator==null)
        separator="";
    //parse la valeur initial pour la transformer en tableau
    var initValuesArray = null;
    if(initValue == null)
    {
        initValuesArray=new Array();
    }
    else if(separator.length!=0)
    {
        initValuesArray = initValue.split(separator);
    }
    else
    {
       //S'il n'existe pas de séparator c'est la taille de la
       //première clef de la liste qui permet de délimiter les champs
       var keySize = 0;
       for (var k in list)
       {
          keySize = k.length;
          break;
       }
       
       initValuesArray=new Array();
       var counter = 0;
       var tmpKey="";
       for(var i=0;i<initValue.length;i++)
       {
          if( counter < (keySize-1) )
          {
             tmpKey+=initValue[i];
             counter++;
          }
          else
          {
             tmpKey+=initValue[i];
             initValuesArray[tmpKey]="";
             counter=0;
             tmpKey="";
          }
       }
    }
    
    
    //génération du code HTML
    var widget = new Tag("div").att("id",this.m_id+"_input")
                     .att("class", "marc").att("valign", "middle")
                     .att("size", MAX_INPUT_SIZE).att("dir",this.m_langDir);
                     
    var body = "";
    if(list!=null)
    {
       for (var key in list)
        {
            var unique_id = this.m_fieldName+this.m_id;
            var value= list[key];
            var labelTag = new Tag("label").att("for",unique_id).att("style","vertical-align: middle;").att("dir",this.m_langDir);
            labelTag.setBody(value);
            var tag = new Tag("input").att("type","checkbox")
                         .att("name", unique_id).att("id",unique_id)
                         .att("value", key).att("style","vertical-align: middle;").att("dir",this.m_langDir)
                         .att("onChange", "checkAction('"+separator+"','"+this.m_fieldName+"','"+this.m_id+"')");

            if(initValuesArray[key] != null )
            {
                tag.att("checked","checked");
                if(initValue == null)
                    initValue = key;
            }
            body+= tag.text()+labelTag.text();
        }
    }
    widget.setBody(body);
    return widget;
}

///////////////////// BOOLEAN COMPOMENT ///////////////////////////////////

/**
 * UIComponent générant une check box
 * Les paramètres requit sont : 
 *    liste     --> liste des valeurs disponibles la premières compte pour true, la seconde pour false
 *                  Si la case est coché on retroune la première valeur, sinon la seconde.
 *                  On ne tiens pas compte des valeurs en plus des 2 premières.
 *                  Si la liste compte moin de deux valeurs, les valeurs par défaut sont "true","false"
 *    initValue --> valeur initial. Positionné dans inputWidget.js
 *   
 **/
BooleanComponent.prototype = new UIComponent();

function BooleanComponent()
{
   this.parent = UIComponent;
   this.parent();
}


/**
 * @return un objet de type tag capable de générer une check box
 **/
BooleanComponent.prototype.getWidget = function ()
{
   var list = this.m_params["liste"];
   var initValue = this.m_params["initValue"];
    
    
    //génération du code HTML
   var widget = new Tag("div").att("id",this.m_id+"_input")
                    .att("class", "marc").att("valign", "middle")
                    .att("size", MAX_INPUT_SIZE).att("dir",this.m_langDir);
                     
    var body = "";
    if(list!=null)
    {
       //index=0 => true
       //index=1 => false
       var trueFalse = new Array();
       var counter=0;
       for (var key in list)
       {
           var unique_id = this.m_fieldName+this.m_id;
           trueFalse[counter]=key;
           counter++;
           //on ne lit que les deux premières valeures
           if(counter>1)
              break;
       }
       if(counter==0)
       {
          trueFalse[0]="true";
          trueFalse[1]="false";
       }
       if(counter==1)
       {
          trueFalse[1]="false";
       }
       var tag = new Tag("input").att("type","checkbox")
                    .att("name", unique_id).att("id",unique_id)
                    .att("value", key).att("style","vertical-align: middle;").att("dir",this.m_langDir)
                    .att("onChange", "boolAction('"+this.m_fieldName+"','"+this.m_id+"','"+trueFalse[0]+"','"+trueFalse[1]+"')");
        if(initValue == trueFalse[0] )
       {
           tag.att("checked","checked");
       }
       body+= tag.text();
   }
   else
   {
      body+="<!--No list set for compoment: BooleanComponent-->";
   }
   
   widget.setBody(body);
   return widget;
}


///////////////////// Long Text ///////////////////////////////////

/**
 * UIComponent générant un champ text avec assistant de saisie pour le champ long
 * Les paramètres requit sont : 
 *    initValue --> valeur initial. Positionné dans inputWidget.js
 **/
LongTextComponent.prototype = new UIComponent();

function LongTextComponent()
{
   this.parent = UIComponent;
   this.parent();
}

/**
 * @return un objet de type tag capable de générer un champ texte avec un assistant de 
 * saisie pour les textes longs
 **/
LongTextComponent.prototype.getWidget = function ()
{
    var initValue = this.m_params["initValue"];

    var widget = new Tag("div").att("class", "marc").att("valign", "middle").att("size", MAX_INPUT_SIZE).att("dir",this.m_langDir);
    var body = "";
    var inputId = this.m_id+"_input";
                         
    var tag = new Tag("input").att("name", inputId).att("id",inputId)
          .att("value", initValue).att("class", "marc").att("dir",this.m_langDir)
          .att("size", MAX_INPUT_SIZE);
    if(typeof(getView)!="undefined")
    {
       tag.att("onChange", "getView().updateData('"+this.m_fieldName + "','" + this.m_id+"', true);getView().showInputFieldDisplayValue('" + this.m_id +"') ;")
          .att("onKeyUp", "getView().showInputFieldDisplayValue('" + this.m_id +"')")
          .att("onMouseOver", "getView().showInputFieldDisplayValue('" + this.m_id +"')")
          .att("onMouseOut", "getView().hideInputFieldDisplayValue()");
    }
    body+=tag.text();
                         
   var img = new Tag("img").att("src", this.getImageURL("tools/assist_saisie_off.gif"));
         img.att("class", "ImgInput").att("border", "0").att("title", sysGetMessage("assistant.long_text_input"));
         
  addListener(inputId,new CompomentListener(this.m_fieldName,this.m_id));

   //Valeur par défault null s'il n'y en a pas
   var defaultValue=this.m_params["def_value"];
   if(defaultValue==null)
      defaultValue="";
   var boutonTag = 
            new Tag("a").setBody(img.text())
             .att("href", "javascript:displayLongText('"+inputId+"','"+defaultValue+"')");         
                         
    body+=boutonTag.text();
    
    widget.setBody(body);
    return widget;
}

///////////////////// spin area ///////////////////////////////////

/**
 * UIComponent générant un composant spin
 * Les paramètres requit sont : 
 *    initValue --> valeur initial. Positionné dans inputWidget.js
 *    step --> Value incremented to the spin number
 *    negative --> si true alors la valeur du spin peut être négative
 **/
SpinArea.prototype = new UIComponent();

function SpinArea()
{
   this.parent = UIComponent;
   this.parent();
}


/**
 * @return génère le code HTML pour créer un spin area
 **/
SpinArea.prototype.getWidget = function ()
{
    var initValue = this.m_params["initValue"];
    var step = this.m_params["step"];
    var className = this.m_params["className"];
    if(className==null)
      className="marcReadOnly";
      
    var inputName = this.m_params["inputName"];
    var size = this.m_params["size"];
    if(size==null)
      size=MAX_INPUT_SIZE;
    
    var acceptNegative = this.m_params["negative"];
    
    if(step==null || isNaN(step))
        step = 1;
    else
        step = Number(step);
        
    if(acceptNegative==null)
       acceptNegative=true;
    else
       acceptNegative = (acceptNegative=="true");
    
    if(initValue==null || isNaN(initValue))
        initValue=0;
        
    var widget = new Tag("div").att("class", "marc").att("valign", "middle").att("size", MAX_INPUT_SIZE).att("dir",this.m_langDir);
    var body = "";
    var inputId = this.m_id+"_input";
    if(inputName==null)
      inputName=inputId;
    var tag = new Tag("input").att("name", inputName).att("id",inputId).att("readonly", "readonly")
          .att("value", initValue).att("class", className).att("dir",this.m_langDir)
          .att("size", size);
    if(typeof(getView)!="undefined")
    {
       tag.att("onChange", "getView().updateData('"+this.m_fieldName + "','" + this.m_id+"', true);getView().showInputFieldDisplayValue('" + this.m_id +"') ;")
          .att("onKeyUp", "getView().showInputFieldDisplayValue('" + this.m_id +"')")
          .att("onMouseOver", "getView().showInputFieldDisplayValue('" + this.m_id +"')")
          .att("onMouseOut", "getView().hideInputFieldDisplayValue()");
    }
    body+=tag.text();
                         
   var imgPlus = new Tag("img").att("src", this.getImageURL("input/counter_inc.gif"))
             .att("class", "ImgInput").att("border", "0").att("style","margin:0;").att("title", sysGetMessage("assistant.incValue"));

   var buttonTagPlus = new Tag("a").setBody(imgPlus.text())
                .att("href", "javascript:incValue('"+this.m_id+"_input',"+step+","+acceptNegative+")");         
    
   var imgMinus = new Tag("img").att("src", this.getImageURL("input/counter_dec.gif"))
                .att("class", "ImgInput").att("border", "0").att("style","margin:0;").att("title", sysGetMessage("assistant.decValue"));

   var buttonTagMinus = new Tag("a").setBody(imgMinus.text())
                .att("href", "javascript:incValue('"+this.m_id+"_input',-"+step+","+acceptNegative+")");   
       
    addListener(inputId,new CompomentListener(this.m_fieldName,this.m_id));
                   
    body+=buttonTagPlus.text();
    body+=buttonTagMinus.text();
    widget.setBody(body);
    
    return widget;
}


///////////////////// spin area ///////////////////////////////////

/**
 * UIComponent générant un composant spin
 * Les paramètres requit sont : 
 *    initValue --> valeur initial. Positionné dans inputWidget.js
 **/
Grouping.prototype = new UIComponent();

function Grouping()
{
   this.parent = UIComponent;
   this.parent();
}

/**
 * Nombre de group, permet de certifier l'identifiant comme unique
 */
var uniqueNumber=0;
Grouping.prototype.getWidget = function ()
{
    var initValue = this.m_params["initValue"];
    if(initValue==null)
      initValue="";
    var sourceField= this.m_params["sourceField"];
    var tableField= this.m_params["tableField"];
    var fieldName = this.m_params["fieldNameField"];

    var className = this.m_params["className"];
    var size =      this.m_params["size"];
    var inputName = this.m_params["inputName"];


    var d = new Date();
    var inputId = this.m_id+"_input"+d.getMilliseconds()+uniqueNumber;

    var widget = new Tag("div").att("valign", "middle").att("size", size).att("dir",this.m_langDir).att("id","div_"+inputId);
    var body = "";
    
    uniqueNumber++;
    if(inputName==null)
       inputName=inputId;
                              
    var tag = new Tag("input").att("name", inputName).att("id",inputId)
          .att("value", initValue).att("class", className).att("dir",this.m_langDir)
          .att("readonly", "readonly")
          .att("size", size)
          .att("ezName","ezidaGrouping");

    body+=tag.text();
                         
   var img = new Tag("img").att("src", this.getImageURL("tools/assist_saisie_off.gif"));
         img.att("class", "ImgInput").att("border", "0").att("title", sysGetMessage("assistant.long_text_input"));

   addListener(inputId,new GroupingListener(this.m_fieldName,this.m_id,inputId));

   // Cas 673 tdn 23/07/2008 En saisie standard sur STATS_TEMPLATE, erreur JS car
   // sourceField et tableField ne renvoie pas à des objets.
   // Je blinde sans corriger.
   var sourceFieldId = "";
   var tableFieldId = "";
   var textFieldId = "";
   if ( sourceField.getAttribute )
      sourceFieldId = sourceField.getAttribute("id");
   if ( tableField.getAttribute )
      tableFieldId = tableField.getAttribute("id");
   var textField = getLastFieldForName(fieldName);
   if ( textField && textField.getAttribute )
      textFieldId = textField.getAttribute("id")
   var boutonTag = 
            new Tag("a").setBody(img.text())
             .att("href", "javascript:displayGroupingPanel('"+inputId+"','"
                 +sourceFieldId+"','"
                 +tableFieldId+"','"
                 +textFieldId +"')")
                .att("ezName","UI_Grouping");         
                         
    body+=boutonTag.text();
    
    widget.setBody(body);
    return widget;
}


GroupingListener.prototype = new FileChooserListener();

function GroupingListener(compomentName,compomentid,displayId)
{
   this.parent = FileChooserListener;
   this.parent(compomentName,compomentid,displayId);
}

///////////////////// date component ///////////////////////////////////

/**
 * UIComponent générant un composant spin
 * Les paramètres requit sont : 
 *    initValue --> valeur initial. Positionné dans inputWidget.js
 **/
DateComponent.prototype = new UIComponent();

function DateComponent()
{
   this.parent = UIComponent;
   this.parent();
}

DateComponent.prototype.getWidget = function ()
{
   var initValue = this.m_params["initValue"];
   if(initValue==null)
      initValue="";
   var className = this.m_params["className"];
   var size =      this.m_params["size"];
   var inputName = this.m_params["inputName"];
   var timeFormat = this.m_params["timeFormat"];
   var dateFormat = this.m_params["dateFormat"];
   var acceptFormula = this.m_params["acceptFormula"];

   var initialTime = "";
   var initialDate = "";
   var displayFormula = false;
   if(initValue.length<15)
   {
      var date=initValue.substring(0,8);
      var time = initValue.substring(8);
      if(!isNaN(time) && !isNaN(date))
      {
         var timeDatas=parseDate(time,timeFormat)
         initialTime=timeDatas[TIME_FORMATED];
         initialDate =DateUtil_getVisibleFormat(date);
      }
      else
      {
         displayFormula=true && (acceptFormula=='true');
      }
   }
   else
   {
      displayFormula=true && (acceptFormula=='true');
   }

   var widget = new Tag("div").att("valign", "middle").att("size", size).att("dir",this.m_langDir);
   var body = "";

   var timeInputName = this.m_id + "_EVERTIME_DISPLAY";
   var dateDisplayInputName  = this.m_id + "_EVERDATE";
          
   var timeTag = new Tag("input").att("name", timeInputName).att("id",timeInputName).att("type", "text")
      .att("value", initialTime).att("class", className).att("dir",this.m_langDir)
      .att("size", timeFormat.length)
      .att("maxlength", timeFormat.length)
      .att("title",timeFormat);
       
   timeTag.att("onkeydown","frmParseTime(this,'"+timeFormat+"')")
          .att("onchange",
            "frmParseTime(this,'"+timeFormat+"',true);" +
            "setDateInResultField('"+this.m_id+"','"+timeInputName+"','"+timeFormat+"','"+dateDisplayInputName+"')");
   if(displayFormula)
   {
      timeTag.att("style","visibility:hidden;display:none;margin: 5px;");
   } else
   {
      timeTag.att("style","margin: 5px;");
   }
   
   body+=timeTag.text();                       
    
           
    var dateTag = new Tag("input").att("name", dateDisplayInputName).att("id",dateDisplayInputName).att("type", "text")
      .att("value", initialDate).att("class", className).att("dir",this.m_langDir)
      .att("size", 10)
      .att("maxlength", 10)
      .att("title",dateFormat);  
         
    
    dateTag.att("onblur","setDateInResultField('"+this.m_id+"','"+timeInputName+"','"+timeFormat+"','"+dateDisplayInputName+"')");
    if(displayFormula)
    {
       dateTag.att("style","visibility:hidden;display:none;margin: 5px;");
    } else
    {
       dateTag.att("style","margin: 5px;");
    }   
    body+=dateTag.text();       

   if(acceptFormula == 'true')
   {
      var formulaInputName  = this.m_id + "_EVERFORMULA";
      var formulaInput = new Tag("input").att("name", formulaInputName).att("id",formulaInputName)
        .att("type", "text")
        .att("value", initValue).att("class", className).att("dir",this.m_langDir)
        .att("size", size)
        .att("maxlength", MAX_INPUT_SIZE)
        .att("title",sysGetMessage("assistant.date.formulaInput"))
        .att("style","visibility:hidden;display:none;margin: 5px;");
   
      if(displayFormula)
      {
         formulaInput.att("style","margin: 5px;");
      } else
      {
         formulaInput.att("style","visibility:hidden;display:none;margin: 5px;");
      } 
   
   
      formulaInput.att("onchange","simpleCopy('"+formulaInputName+"','"+this.m_id+"')");
   
      body+=formulaInput.text();
   }
   
   //button
   var imgId = this.m_id + "_IMGCALENDAR";
   var img = new Tag("img")
         .att("src", this.getImageURL("tools/assist_calendar.gif"))
         .att("id",imgId)
         .att("border", "0")
         .att("title", sysGetMessage("input.date.choose"));
   if(displayFormula)
   {
      img.att("style","visibility:hidden;display:none;");
   }
         
   dateListener[this.m_id]=new CtrlDateListener(this.m_id,timeInputName,timeFormat,dateDisplayInputName);

   var boutonTag = 
            new Tag("a").setBody(img.text())
             .att("href", "javascript:frmShowDateAssist('','crit','" + dateDisplayInputName + "',dateListener['"+this.m_id+"']);")
             .att("class", "assist");        
  
  body+=boutonTag.text();
  if(acceptFormula == 'true')
  {
      var imgFormula = new Tag("img")
         .att("src", this.getImageURL("tools/btn_switch.gif"))
         .att("border", "0")
         .att("title", sysGetMessage("assistant.date.useFormula"));

      var boutonFormulaTag = 
            new Tag("a").setBody(imgFormula.text())
             .att("href", "javascript:showHideField('"+ dateDisplayInputName + "');" 
                    + "showHideField('"+ timeInputName + "');" 
                    + "showHideField('"+ formulaInputName + "');" 
                    + "showHideField('"+ imgId + "');")
             .att("class", "assist");     
      body+=boutonFormulaTag.text();
   }
   
   //result field
   var resultTag = new Tag("input").att("name", inputName).att("id",this.m_id).att("type", "hidden")
      .att("value", initValue)
      .att("readonly", "readonly");
      body+=resultTag.text();
   
    widget.setBody(body);
    return widget;
}

var dateListener=new Array();

function CtrlDateListener(fieldResultId,timeField,timeFormat,dateField)
{
   this.fieldResultId=fieldResultId;
   this.timeField=timeField;
   this.timeFormat=timeFormat;
   this.dateField=dateField;
}

CtrlDateListener.prototype.valueChanged = function (value,htmlElementSource)
{
   setDateInResultField(this.fieldResultId,this.timeField,this.timeFormat,this.dateField);
}

/////////////// SOURCE COMPONENTS //////////////////////////

/**
 * UIComponent générant un champ de type texte permettant de choisir une source
 * via un assistant
 * Les paramètres requit sont : 
 *    initValue --> valeur initial. Positionné dans inputWidget.js
 **/
SourceComponent.prototype = new UIComponent();

function SourceComponent()
{
   this.parent = UIComponent;
   this.parent();
}

/**
 * @return un objet de type tag capable de générer un champ texte avec un assistant de 
 * saisie pour les sources
 **/
SourceComponent.prototype.getWidget = function ()
{
    var initValue = this.m_params["initValue"];

    var widget = new Tag("div").att("class", "marc").att("valign", "middle").att("size", MAX_INPUT_SIZE).att("dir",this.m_langDir);
    var body = "";
    var inputId = this.m_id+"_input";
                         
    var tag = new Tag("input").att("name", this.m_fieldName).att("id",inputId)
          .att("value", initValue).att("class", "marc").att("dir",this.m_langDir)
          .att("size", MAX_INPUT_SIZE)
          .att("parentid",this.m_id);
    if(typeof(getView)!="undefined")
    {
       tag.att("onChange", "getView().updateData('"+this.m_fieldName + "','" + this.m_id+"', true);getView().showInputFieldDisplayValue('" + this.m_id +"') ;")
          .att("onKeyUp", "getView().showInputFieldDisplayValue('" + this.m_id +"')")
          .att("onMouseOver", "getView().showInputFieldDisplayValue('" + this.m_id +"')")
          .att("onMouseOut", "getView().hideInputFieldDisplayValue()");
    }
    body+=tag.text();
                         
   var img = new Tag("img").att("src", this.getImageURL("tools/assist_saisie_off.gif"));
         img.att("class", "ImgInput").att("border", "0").att("title", sysGetMessage("assistant.source_input"));

  addListener(inputId,new CompomentListener(this.m_fieldName,this.m_id));

   var acceptTypes = this.m_params["accept_types"];
   if ( ! acceptTypes )
      acceptTypes = "";
   var boutonTag =
            new Tag("a").setBody(img.text())
             .att("href", "javascript:displaySourceAssistant('"+inputId+"','" + acceptTypes + "')");         
                         
    body+=boutonTag.text();
    
    widget.setBody(body);
    return widget;
}

/////////////// TABLE COMPONENTS //////////////////////////

/**
 * UIComponent générant un champ de type texte permettant de choisir une table
 * via un assistant
 * Les paramètres requit sont : 
 *    initValue --> valeur initial. Positionné dans inputWidget.js
 *    source --> non de la source. Positionné dans inputWidget.js
 **/
TableComponent.prototype = new UIComponent();

function TableComponent()
{
   this.parent = UIComponent;
   this.parent();
}

/**
 * @return un objet de type tag capable de générer un champ texte avec un assistant de 
 * saisie pour les tables
 **/
TableComponent.prototype.getWidget = function ()
{
    var initValue = this.m_params["initValue"];
    var sourceName = this.m_params["source"];

    var widget = new Tag("div").att("class", "marc").att("valign", "middle").att("size", MAX_INPUT_SIZE).att("dir",this.m_langDir);
    var body = "";
    var inputId = this.m_id+"_input";
                         
    var tag = new Tag("input").att("name", this.m_fieldName).att("id",inputId)
          .att("value", initValue).att("class", "marc").att("dir",this.m_langDir)
          .att("size", MAX_INPUT_SIZE);
    if(typeof(getView)!="undefined")
    {
       tag.att("onChange", "getView().updateData('"+this.m_fieldName + "','" + this.m_id+"', true);getView().showInputFieldDisplayValue('" + this.m_id +"') ;")
          .att("onKeyUp", "getView().showInputFieldDisplayValue('" + this.m_id +"')")
          .att("onMouseOver", "getView().showInputFieldDisplayValue('" + this.m_id +"')")
          .att("onMouseOut", "getView().hideInputFieldDisplayValue()");
    }
    body+=tag.text();
                         
   var img = new Tag("img").att("src", this.getImageURL("tools/assist_saisie_off.gif"));
         img.att("class", "ImgInput").att("border", "0").att("title", sysGetMessage("assistant.source_input"));

  addListener(inputId,new CompomentListener(this.m_fieldName,this.m_id));

   var boutonTag = 
            new Tag("a").setBody(img.text())
             .att("href", "javascript:displayTableAssistant('"+this.m_id+"','"+sourceName+"')");         
                         
    body+=boutonTag.text();
    
    widget.setBody(body);
    return widget;
}

/////////////// DEFAULT NUMERIC COMPONENTS //////////////////////////

/**
 * Tableau contenant les inputs verifier pour les champs numerics
 */
var inputVerifierById = new Array();
//accessor
function setInputVerifier(inputId,verifier)
{
   inputVerifierById[inputId]=verifier;
}
function getInputVerifier(inputId)
{
   return inputVerifierById[inputId];
}

/**
 * UIComponent générant un champ de type numeric généric, préféré un type
 * moin généric entier par exemple.
 **/
NumberField.prototype = new UIComponent();

function NumberField()
{
   this.parent = UIComponent;
   this.parent();
}

/**
 * @return un objet de type tag capable de générer un champ texte n'acceptant que des
 * valeur numeric
 **/
NumberField.prototype.getWidget = function ()
{
    var initValue = this.m_params["initValue"];
    var className = this.m_params["className"];
    var size = this.m_params["size"];
    if(size == null)
       size=MAX_INPUT_SIZE;
    if(className==null)
       className='marc';
    var widget = new Tag("div").att("class", className).att("valign", "middle").att("size", size).att("dir",this.m_langDir);
    var body = "";
    var inputId = this.m_id+"_input";
                         
    var tag = new Tag("input").att("name", inputId).att("id",inputId)
          .att("value", initValue).att("class", "marc").att("dir",this.m_langDir)
          .att("size", size)
          .att("onKeyPress", "checkData('" + inputId+"')");
    if(typeof(getView)!="undefined")
    {
       tag.att("onChange", "checkData('" + inputId+"');getView().updateData('"+this.m_fieldName + "','" + this.m_id+"', true);getView().showInputFieldDisplayValue('" + this.m_id +"') ;")
          .att("onKeyUp", "getView().showInputFieldDisplayValue('" + this.m_id +"')")
          .att("onMouseOver", "getView().showInputFieldDisplayValue('" + this.m_id +"')")
          .att("onMouseOut", "getView().hideInputFieldDisplayValue()");
    }
    else
    {
        tag.att("onChange", "checkData('" + inputId+"')");
    }
    body+=tag.text();
    
    setInputVerifier(inputId,this.getInputVerifier(inputId));
    widget.setBody(body);
    return widget;
}

/**
 * To override to return good verifier
 */
NumberField.prototype.getInputVerifier = function (inputId)
{
   return new StandardVerifier(inputId);
}

/**
 * Objet vérifiant la saisie en cours
 */
function StandardVerifier(compomentId)
{
   this.compomentId=compomentId;
   this.compoment=null;
}

/**
 * Méthode appellé après chaque saisie
 */
StandardVerifier.prototype.verify = function ()
{
   if(this.compoment==null)
   {
      this.compoment = document.getElementById(this.compomentId);
      if(this.compoment==null)
         return;
   }
   var data = this.compoment.value;
   
   if(!this.check(data))
   {
      this.compoment.value = data.substr(0,data.length-1);
      return false;
   }
   return true;
}
/**
 * @return true si la chaine est correct, check data
 * est applé après chaque insertion de nouveau charactères
 */
StandardVerifier.prototype.check = function (value)
{   
   return !isNaN(value);
}
/**
 * Méthod appellé par le composant sur l'événement keyPress
 */
function checkData(elementId)
{
   var verifier = getInputVerifier(elementId);
   if(verifier!=null)
      verifier.verify();
}

/////////////// Integer COMPONENTS //////////////////////////

/**
 * UIComponent générant un champ de type entier
 **/
IntegerField.prototype = new NumberField();

function IntegerField()
{
   this.parent = NumberField;
   this.parent();
}

IntegerField.prototype.getInputVerifier = function (inputId)
{
   return new IntegerInputVerifier(inputId);
}

/**
 * Verifier pour les champs entiers
 **/
IntegerInputVerifier.prototype = new StandardVerifier();


function IntegerInputVerifier(compomentId)
{
   this.parent = StandardVerifier;
   this.parent(compomentId);
}

IntegerInputVerifier.prototype.check = function (data)
{
   var lastChar;
   if(data.length>1)
      lastChar = data.charAt(data.length-1);
   else if(data.length==1)
      lastChar =data;
   else return true;
   
   if(isNaN(lastChar))
   {
      this.compoment.value = data.substr(0,data.length-1);
      alert(sysGetMessage("assistant.integerField.no_integer_value")+lastChar);
      return false;
   }
   return true;
}

/////////////// Multi list value component //////////////////////////////

MultiList.prototype = new UIComponent();

function MultiList()
{
   this.parent = UIComponent;
   this.parent();
}

MultiList.prototype.getWidget = function ()
{
    var initValue = this.m_params["initValue"];
    if(initValue==null)
      initValue="";
    var listName = this.m_params["listName"];
    
    var className = this.m_params["className"];
    if(className==null || className.length==0)
       className="marc";
    var size =      this.m_params["size"];
    if(size==null || size.length==0)
       size=MAX_INPUT_SIZE;
    
    var inputName = this.m_params["inputName"];
    var inputId = this.m_id+"_input";
    if(inputName==null || size.length==0)
       inputName=inputId;

    var widget = new Tag("div").att("valign", "middle").att("size", size).att("dir",this.m_langDir);
    var body = "";
                              
    var tag = new Tag("input").att("name", inputName).att("id",inputId)
          .att("value", initValue).att("class", className).att("dir",this.m_langDir)
          .att("readonly", "readonly")
          .att("size", size)
          .att("onMouseOver", "getView().showInputFieldDisplayValue('" + this.m_id +"')")
          .att("onMouseOut", "getView().hideInputFieldDisplayValue()");

    body+=tag.text();
                         
   var img = new Tag("img").att("src", this.getImageURL("tools/assist_saisie_off.gif"));
         img.att("class", "ImgInput").att("border", "0").att("title", sysGetMessage("assistant.multi_value.list"));

   addListener(inputId,new MultiListListener(this.m_fieldName,this.m_id,inputId));

   var boutonTag = 
            new Tag("a").setBody(img.text())
             .att("href", "javascript:displayMultiListPanel('"+inputId+"','"
                 +this.m_sourceName+"','"
                 +listName+"','"
                 +",')"); //le caractère séparateur est la virgule
                         
    body+=boutonTag.text();
    
    widget.setBody(body);
    return widget;
}

MultiListListener.prototype = new FileChooserListener();

function MultiListListener(compomentName,compomentid,displayId)
{
   this.parent = FileChooserListener;
   this.parent(compomentName,compomentid,displayId);
}
/////////////// UTILS METHOD FOR UI COMPONENTS //////////////////////////

/**
 * Function incrémentant la valeur présente dans le champ d'id elementId
 * de la valeur de step. si la valeur dans elementId et null ou n'est
 * pas un nombre rien ne ce passe
 **/
function incValue(elementId,step,acceptNegative)
{
    var field = this.document.getElementById(elementId);
    var value = field.value;
    if(value==null || isNaN(value))
    {
        return;
    }
    var newVal = Number(value)+ step
    if(!acceptNegative && newVal<0)
        return
    
    updateValue(elementId,""+newVal,null);
}

/**
 * Permet la mise à jour de la valeur de champs
 * en fonction des valeurs des cases cochés.
 * le nom de case doit être le même soit: fieldName+elemId;
 * @param separator: charactère utilisé pour séparer les valeurs, si null les 
 *                   valeurs sont collées
 * @param fieldName: Nom du champ dans la description
 * @param elemID:    id unique d'un champ
 **/
function checkAction(separator,fieldName,elemId)
{
    var checkBoxName = fieldName+elemId;
    var checkBoxs = this.document.getElementsByName(checkBoxName);
    var data=null;
    if(separator==null)
        separator="";
    for(var index in checkBoxs)
    {
        var checkBox = checkBoxs[index];
        if(checkBox.checked)
        {
            if(data==null)
            {
               data=checkBox.value;
            }
            else
            {
              data+=separator+checkBox.value;
            }
        }
    }
    updateData(data,fieldName,elemId);
}

/**
 * Permet la mise à jour de la valeur d'un champ boolean.
 * Si la cose est coché, trueValue est utilisé sinon falseValue
 * le nom de la case doit être le même soit: fieldName+elemId;
 * 
 * fieldName et elemID sont utilisés pour updateData(...)
 * 
 * @param fieldName: Nom du champ dans la description
 * @param elemID:    id unique d'un champ
 * @param trueValue: Valeur si la case est cochée
 * @param falseValue Valeur si la case est décochée
 */
function boolAction(fieldName,elemId,trueValue,falseValue)
{
   var checkBoxName = fieldName+elemId;
   var checkBox = this.document.getElementById(checkBoxName);
   if(checkBox.checked)
   {
      updateData(trueValue,fieldName,elemId);
   }
   else
   {
      updateData("",fieldName,elemId);
   }
    
}


/**
 * Permet la mise à jour de la vue sous jacente
 * @param value: nouvelle valeur
 * @param fieldName: nom du champ affecté
 * @param elemId: Identifiant unique de l'element
 **/
function updateData(value,fieldName,elemId)
{
   var htmlInput = this.document.getElementById(elemId+"_input");
   if(htmlInput!=null)
       htmlInput.value = value;
   if(typeof(getView)!="undefined")
   {
      //pru: 27/02/2008, ajout de la méthode permettant de vérifier les autres contrôles
     getView().checkControls(fieldName,elemId);
     getView().updateData(fieldName,elemId, true);
   }
}

/**
 * Affiche une fenêtre permettant de sélectionner
 * un fichier dans une arborescence
 * @param elementID: id de l'élément affichant le chemin du fichier
 * après sélection
 * @param setFieldName: nom du set décrivant les fichiers pouvant être sélectionné
 * @param isDirectoryAccepted: valeur boolean si true alors le file chooser permet de sélectionner
 *        les répertoires
 * @parma multiSelectionMode: si true, il est possible de sélectionné plusieurs
 *        élément simultanément
 * @param reloadServerFile: si true, le repository est rechargé coté serveur, sinon
 *        c'est le repository mis en cache qui est retourné
 **/
function displayFileChooser(elementID,setFieldName,isDirectoryAccepted,multiSelectionMode,reloadServerFile)
{
   var url = sysGetAppBaseUrl()+"jsp/admin/resource/file_chooser.jsp";
   url+="?set="+myEscape(setFieldName)+"&elementId="+elementID;
   if(isDirectoryAccepted)
       url+="&acceptDir=true";
   if(reloadServerFile)
      url+="&reload-file=true";
   if(multiSelectionMode)
      url+="&multi-selection=true";
   sysOpenWindow("FileChooser", url, false, "0,0,400,270", "toolbar=0,location=0,directories=0,menuBar=0,scrollbars=yes,resizable=yes");
}

/**
 * Affiche une fenêtre permettant de saisir est modifier des textes de taille important
 * @param elementID: id de l'élément affichant le texte
 **/
function displayLongText(elementID,defaultValue)
{
   if(defaultValue==null)
      defaultValue="";
   var initialValue = document.getElementById(elementID).value;
   var url = sysGetAppBaseUrl()+"jsp/tools/long_text_input.jsp";
   url+="?initialValue="+myEscape(initialValue)
      +"&elementId="+elementID
      +"&defaultValue="+myEscape(defaultValue);
   sysOpenWindow("LongTextInput", url, false, "0,0,500,350", "toolbar=0,location=0,directories=0,menuBar=0,scrollbars=yes,resizable=yes");
}


/**
 * Affiche une fenêtre permettant de choisir une source
 * @param elementID: id de l'élément affichant le texte
 * @param acceptTypes types des sources à retenir, séparés par virgule
 **/
function displaySourceAssistant(elementID, acceptTypes)
{
   var initialValue = document.getElementById(elementID).value;
   var url = sysGetAppBaseUrl()+"jsp/tools/assist_source.jsp";
   url+="?targetInput="+elementID+"&multiple="+1;
   if ( acceptTypes && acceptTypes.length > 0 )
   {
      url += "&acceptTypes=" + acceptTypes;
   }
   sysOpenWindow("SourceInput", url, false, "0,0,500,350", "toolbar=0,location=0,directories=0,menuBar=0,scrollbars=yes,resizable=yes");
}

/**
 * Recherche le première élément ayant pour nom sourceFieldName dans la hierarchie
 * et utilise sa valeur pour trouver le nom de la source.
 * Les noeuds frères sont parcouru en premier, puis les noeuds parents
 * Affiche une fenêtre permettant de choisir une table
 * 
 * ps: on utilise soit sourceFieldName soit sourceFieldId[,defaultSourceFieldId]
 * 
 * @param elementID: id de l'élément affichant le texte
 * @param sourceName: nom de la source contenant les tables
 * @param sourceFieldId: l'id de la source contenant les tables (utilisé a la place de sourceName si non null)
 * @param defaultSourceFieldId: si aucun composant n'existe pour sourceFieldId ont essaie defaultSourceFieldId
 **/
function displayTableAssistant(elementID,sourceFieldName,sourceFieldId,defaultSourceFieldId)
{
   var tableNode = document.getElementById(elementID);
   var sourceNode = null
   if(sourceFieldId!=null)
   {
     sourceNode = document.getElementById(sourceFieldId);
     if(sourceNode==null && defaultSourceFieldId!=null)
       sourceNode = document.getElementById(defaultSourceFieldId);
   }
   else
   {
     var sourceNodes = document.getElementsByName(sourceFieldName);
     sourceNode = getBestAncestor(tableNode,sourceNodes);
     if(sourceNode==null)
     {
        alert(sysGetMessage("assistant.error.noFieldName")+sourceFieldName);
        return;
     }
   }
   
   var sourceName = "";
   // la sasie standart oblige à n'avoir qu'un seul champ pour un même nom
   if(sourceNode!=null)
   {
         sourceName=sourceNode.value;
   }
   
   var targetInput = elementID;
   if(typeof(getView)!="undefined")
   {
      //saisie standard
      targetInput+="_input";
   }
   
   var initialValue = tableNode.value;
   var url = sysGetAppBaseUrl()+"jsp/tools/assist_tables.jsp";
   url+="?targetInput="+targetInput+"&multiple="+1;
   if(sourceName!=null)
      url+="&sourceName="+sourceName;
   sysOpenWindow("tableAssistant", url, false, "0,0,500,350", "toolbar=0,location=0,directories=0,menuBar=0,scrollbars=yes,resizable=yes");
}


/**
 * Affiche une fenêtre permettant de choisir un champ
 * 
 * ps: on utilise soit sourceFieldName soit sourceFieldId[,defaultSourceFieldId]
 * 
 * @param elementID: id de l'élément affichant le texte
 * @param sourceFieldId: l'id de la source contenant les tables (utilisé a la place de sourceName si non null)
 * @param defaultSourceFieldId: si aucun composant n'existe pour sourceFieldId ont essaie defaultSourceFieldId
 * @param tableFieldId: l'id de la source contenant les tables (utilisé a la place de sourceName si non null)
 * @param defaultTableFieldId: si aucun composant n'existe pour sourceFieldId ont essaie defaultSourceFieldId
 **/
function displayFieldAssistant(elementID,sourceFieldId,tableFieldId,defaultSourceFieldId,defaultTableFieldId)
{
   var tableNode = document.getElementById(elementID);
   var sourceNode = document.getElementById(sourceFieldId);
   if(sourceNode==null && defaultSourceFieldId!=null)
   {
      sourceNode = document.getElementById(defaultSourceFieldId);
   }
   
   var tableNode = document.getElementById(tableFieldId);
   if(tableNode==null && defaultTableFieldId!=null)
   {
      tableNode = document.getElementById(defaultTableFieldId);
   }
   
   var sourceName = "";
   // la sasie standart oblige à n'avoir qu'un seul champ pour un même nom
   if(sourceNode!=null)
   {
      sourceName=sourceNode.value;
   }
   
   var tableName = "";
   // la sasie standart oblige à n'avoir qu'un seul champ pour un même nom
   if(tableNode!=null)
   {
         tableName=tableNode.value;
   }
   
   
   var initialValue = tableNode.value;
   var targetInput = elementID;
   if(typeof(getView)!="undefined")
   {
      //saisie standard
      targetInput+="_input";
   }
   var targetElement = document.getElementById(targetInput);
   var currentValue = targetElement.value;
   displayFieldAssist(targetInput,sourceName,tableName,1,null,currentValue);
}

/**
 * Affiche une fenêtre permettant de choisir un ou plusieurs champ sans notion d'ordre
 * @param targetInput element contenant le resultat
 * @param sourceName nom de la source
 * @param tableName nom de la table
 * @param NbMaxSelected nombre de valeur maximun, si négatif, pas de limite
 * @param separator separateur entre les valeurs
 * @param selection valeurs déjà sélectionnées (string)
 * @param displayFieldName si true le nom des champs est affichés sinon le label
 * 
 */ 
function displayFieldAssist(targetInput,sourceName,tableName,NbMaxSelected,separator,selection,displayFieldName,displaySystemField)
{ 
   var url = sysGetAppBaseUrl()+"jsp/tools/assist_fields.jsp";
   url+="?targetInput="+targetInput;
   if(sourceName!=null)
      url+="&sourceName="+sourceName;
   if(tableName!=null)
      url+="&tableName="+tableName;
   if(NbMaxSelected!=null)
      url+="&multiple="+NbMaxSelected;
   else
      url+="&multiple=1";
   if(separator!=null && separator.length !=0)
      url+="&separator="+separator;
   if(selection!=null)
      url+="&selection="+selection;
   if(displayFieldName!=null)
      url+="&displayFieldName="+displayFieldName;
   else
     url+="&displayFieldName=false";
   if(displaySystemField!=null)
      url+="&displaySystemField="+displaySystemField;
   else
     url+="&displaySystemField=false";
   sysOpenWindow("fieldAssist", url, false, "0,0,500,350", "toolbar=0,location=0,directories=0,menuBar=0,scrollbars=yes,resizable=yes");
}


/**
 * Affiche une fenêtre permettant de choisir plusieurs champ et de les ordonner
 * @param targetInput element contenant le resultat
 * @param sourceName nom de la source
 * @param tableName nom de la table
 * @param separator separateur entre les valeurs
 * @param selection valeurs déjà sélectionnées (string)
 * @param displayFieldName si true le nom des champs est affichés sinon le label
 * @param useExtraField, si 'true' permet la creation de champ imaginaire (utile pour aligner les champs)
 *                    ex: si l'on a besoin de 5 colonnes et que la table ne possède que 2 champs
 */ 
function displayMultiFieldAssist(targetInput,sourceName,tableName,separator,selection,displayFieldName,displaySystemField,useExtraField)
{ 
   var url = sysGetAppBaseUrl()+"jsp/tools/assist_multi_fields.jsp";
   url+="?targetInput="+targetInput;
   if(sourceName!=null)
      url+="&sourceName="+sourceName;
   if(tableName!=null)
      url+="&tableName="+tableName;
   if(separator!=null && separator.length !=0)
      url+="&separator="+separator;
   if(selection!=null)
      url+="&selection="+selection;
   if(displayFieldName!=null)
      url+="&displayFieldName="+displayFieldName;
   else
     url+="&displayFieldName=false";
   if(displaySystemField!=null)
      url+="&displaySystemField="+displaySystemField;
   else
     url+="&displaySystemField=false";
   if(useExtraField!=null)
      url+="&useExtraField="+useExtraField;
   sysOpenWindow("multiFieldAssist", url, false, "0,0,600,250", "toolbar=0,location=0,directories=0,menuBar=0,scrollbars=yes,resizable=yes");
}

/**
 * Permet, avec la saisie standard, de retrouve pour un noeud
 * fils (child) sont ancêtre le plus proche. Il doit posséder un
 * ancêtre commun avec child ou lui même être un ancêtre de child 
 * Cet ancêtre ou lui même doit être le plus proche possible
 * du noeud child dans la hierarchie
 */
function getBestAncestor(child,ancestorList)
{
   if(ancestorList.length==null)
      return null;
   var childParentIds = new Array();
   var parentId = child.getAttribute("parentid");
   //attribution des scores, plus le noeud et proche de child
   //plus sont score est élevé.
   var score = 100000;
   while(parentId!="1" && parentId!=null)
   {
      childParentIds[""+parentId]=score--;
      var parentElement = document.getElementById(parentId);
      parentId = parentElement.getAttribute("parentid");
   }
   
   //recherche du noeud ancêtre possèdant des ancêtres en commun avec
   //child
   var bestAncestor=null;
   var bestScore=-1;
   for(var i = 0;i<ancestorList.length;i++)
   {
       var currentAncestor=ancestorList[i];
       if(currentAncestor.nodeName.toLowerCase() == "input" )
       {
          var currentId=currentAncestor.getAttribute("parentid");
          var score = getScore(childParentIds,currentAncestor,parseInt(child.getAttribute("level")));
          if(score>bestScore)
          {
             bestScore=score;
             bestAncestor=currentAncestor;
          }
       }
   }
   return bestAncestor;
}

/**
 * Permet de noter les noeuds trouvés pour élire
 * le meilleur candidat!
 */
function getScore(childParentIds,currentAncestor)
{
   var parentId = currentAncestor.getAttribute("parentid");
   while(parentId!="1" && childParentIds[parentId]==null &&  parentId!=null)
   {
      var parentElement = document.getElementById(parentId);
      parentId = parentElement.getAttribute("parentid");
   }
   if(childParentIds[parentId]!=null)
   {
      return childParentIds[parentId];
   }
   return 1;
}

/**
 * Affiche l'assistant permettant le regroupement d'éléments contenues dans
 * une liste
 */
function displayGroupingPanel(elementID,sourceFieldId,tableFieldId,fieldFieldId)
{
   var initialValue = document.getElementById(elementID).value;
   var url = sysGetAppBaseUrl()+"jsp/tools/grouping_input.jsp";
   url+="?elementId="+elementID;
   
   var sourceField = document.getElementById(sourceFieldId);
   if(sourceField!=null && sourceField.value!=null && sourceField.value!='')
    url+="&sourceName="+sourceField.value;
    
   var tableField = document.getElementById(tableFieldId);
   if(tableField!=null && tableField.value!=null && tableField.value != '')
    url+="&tableName="+tableField.value;
    
   var fieldField = document.getElementById(fieldFieldId);
   if(fieldField!=null && fieldField.value!=null && fieldField.value!='')
      url+="&fieldName="+fieldField.value;
   url+="&value="+myEscape(initialValue);
   sysOpenWindow("groupingInput", url, false, "0,0,650,300", "toolbar=0,location=0,directories=0,menuBar=0,scrollbars=yes,resizable=yes");
}

/**
 * Affiche un assistant permettant la saisie de la valeur d'un champ multi-valué
 * contrôlé sur liste
 */
function displayMultiListPanel(elementID,sourceName,listName,separator)
{
   var initialValue = document.getElementById(elementID).value;
   var url = sysGetAppBaseUrl()+"jsp/tools/multi_list_value_input.jsp";
   url+="?elementId="+elementID;
   
   url+="&sourceName="+sourceName;
   url+="&listName="+listName;
   url+="&value="+myEscape(initialValue);
   url+="&separator="+myEscape(separator);
   sysOpenWindow("multiValue", url, false, "0,0,650,300", "toolbar=0,location=0,directories=0,menuBar=0,scrollbars=yes,resizable=yes");
}

/**
 * Show the field identified by fieldId if hidden
 * otherwise hide it
 */
function showHideField(fieldId)
{
   var element = document.getElementById(fieldId);
   if(element)
   {
      if ( element.style )
      {
         if(element.style.visibility!='hidden' || element.style.display!='none')
         {
            element.style.visibility = 'hidden';
            element.style.display = 'none';
         }
         else
         {
            element.style.visibility = 'visible';
            element.style.display = ''; 
         }
      }
      else
      {
         if(element.visibility!='hide')
            element.visibility = 'hide';
         else
            element.visibility = 'show';
      }
   }
}

/**
 * Récupère les valeurs des champs timeField et dateField
 * pour fixer la valeur du champ résultat resultField
 * Le pattern timePattern permet de parser la chaine présente 
 * dans le champ timeField.La date(valeur de dateField) doit 
 * être au format iso
 */
function setDateInResultField(resultFieldId,timeFieldId,timePattern,dateFieldId)
{
   var resultField = document.getElementById(resultFieldId);
   var result = "";
   if(dateFieldId!=null)
   {
     var dateField = document.getElementById(dateFieldId);
     if(dateField.value.length == 0)
     {
        // Cas 528 Quand on vide le champ de saisie, il faut vider le champ
        // date masué aussi
        resultField.value = "";
        return;
     }
     var date = DateUtil_guessDate(dateField.value);
     if(date==null)
     {
        date = new Date();
        dateField.value=DateUtil_getVisibleFormat(date);
     }
    result += date.getISO();
   }
   
   if(timeFieldId!=null)
   {
      var timeField = document.getElementById(timeFieldId);
      var datas = frmParseTime(timeField,timePattern,true);
      var hour =datas[TIME_HOUR];
      var min =datas[TIME_MINUTES];
      var sec = datas[TIME_SECONDES];
      result += hour+min+sec;
   } else
   {
      result += "000000"
   }
   resultField.value=result;
}

/**
 * recopie la valeur du champ from dans le champ to
 */
function simpleCopy(fromId,toId)
{
   var fromField = document.getElementById(fromId);
   var toField = document.getElementById(toId);
   toField.value = fromField.value;
}

















