//---------------------------
// 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) 
{
   // 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é : '_RS_' est le séparateur 
   //    - entre clés !!! DORIS !!!
   //    - entre les displays des notices
   else if ( schemaField.getLinkTable() )
   {   
      separData = "_RS_";
      separ0 = "_RS_";
   }   

   // 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; }
         
         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 (cf Doris)
   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
      codes = listeValue.split(separ0);  
   }   

   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");

   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;
         
   return result;
}   

// 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 = "";
   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;
   alert(message);   
}


// 
function inputCtrlDate(inputValue, showMessage, fieldLabel) 
{
   // Pas de valeur saisie 
   if (inputValue.length == 0)
      return true;

   var val = 0;
   var ok = 0;
   
   // 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  
   }       
   
   if (parts.length == 3)
   {
      // Le jour
      val = parseInt(parts[0],10); 
      if ( inputCtrlInteger(parts[0], false, null) && 0<val && val<32 )
         ok ++;
      // Le mois   
      val = parseInt(parts[1],10);
      if ( inputCtrlInteger(parts[1], false, null) && 0<val && val<13 )
         ok ++;
      //L'année   
      val = parseInt(parts[2],10);
      if ( inputCtrlInteger(parts[2], false, null) && 0<val && parts[2].length == 4)
         ok ++;
   }
   if ( ok != 3 ) 
   {
      if (showMessage)
         inputCtrlGetMessageError(fieldLabel, inputValue, mess_control_date2, null);
      return false;
   }
return true; 
}

// 
function inputCtrlDecimal(inputValue, showMessage, fieldLabel) 
{
   // Pas de valeur saisie 
   if (inputValue.length == 0)
      return true;

   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; 
}

// 
function inputCtrlInteger(inputValue, showMessage, fieldLabel)
{
   // Pas de valeur saisie 
   if (inputValue.length == 0)
      return true;
   var k=0;
   if(inputValue.charAt(0)=='-')
	k=1;
   for (var i=k; 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 (Cf Doris)      
   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  (cf Doris)
   var separ0 = schemaField.getAttribute("separ0");
   
   // Champ lié : '_RS_' est le séparateur entre clés !!! DORIS !!!   
   if ( schemaField.getLinkTable() )  
      separ0 = "_RS_";
   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, true, 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 (cf Doris)
   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;
}
