/*******************************************************************************************
* Fichier : FieldsCheck.js
* ******************************************************************************************
* Description : Bibliotheque de scripts de controle des champs d'un formulaire.
* La bibliotheque suivante contient les fonctions necessaires pour controler
* les champs d'un formulaire, comme par exemple determiner si un nom obligatoire
* est encore vide, si un e-mail est bien forme, etc.
*
* Utilisation : Son utilisation est tres simple puisqu'il suffit :
*
* . D'importer la bibliotheque : <script language="JavaScript" src="FieldsCheck.js"></script>
*   (ne pas importer systematiquement dans l'application.inc.php ou le header standard 
*   car les pages sans formulaires n'en ont pas besoin. Importer juste au dessus du 
*   formulaire utilisateur)
*
* . De creer une fonction FieldsCheck() de controle a partir de l'exemple fourni dans FieldsCheck_Example.js
* 
* . De appeler la fonction dans le formulaire : <form onSubmit="return FieldsCheck(this);" ...>
*  
* La fonction FieldsCheck() est entierement de la responsabilite du developpeur 
* qui doit la creer/personnaliser en fonction des champs a controler. Un exemple 
* tout fait de cette fonction est disponible dans FieldsCheck_Example.js. Il est
* conseille de partir de cet exemple et de le personnaliser pour realiser vos
* controles.
* 
* Sources : Cette bibliotheque est directement inspiree de la bibilotheque que genere
* en arriere plan Cold Fusion Application Server pour ses propres controles de champs.
*
* Auteurs : 
* Iharizaka Rahaingoson (ihari@ibonia.mg), 1999-2005, Allaire Corp / Cold Fusion Application Server
* Thierie Christophin (thierie@ibonia.mg) pour la [future] fonction de controle de date, 2005.
*
*******************************************************************************************/


// ATTENTION
// Ne pas modifier le contenu de ce script, sauf pour ajouter des fonctions de controle 
// supplementaires et qui sont generiques (fonctions utilisables dans tous les sites).

// Constantes utiles au controle de date
var DateFormat = "fr";          // Valeurs attendues "fr" pour "dd/mm/yy" ou "dd/mm/yyyy", sinon "mm/dd/yy" ou "mm/dd/yyyy"
var DateSeparator = "/";
var minYear = 1900;
var maxYear = 2100;

// 1. Pop-up d'alerte lorsqu'une erreur est rencontree :
// -----------------------------------------------------------
// Affiche la boite de dialogue d'erreur a l'utilisateur.
// 1. Pour le moment se contente d'alert(). Dans le futur, 
//    pourrait demander du confirm() et changer en consequence
//    sa valeur de retour qui est pour le moment fige a false.
// 2. form_object et input_object sont aussi reserves pour un
//    usage ulterieur. Ils pourraient afficher des informations
//    de debug supplementaires.

function FieldsCheck_OnError(form_object, input_object, object_value, error_message) {
    alert(error_message);
    return false;    
}

// 2. Controle d'existence d'une valeur dans un champ quequesoit son type :
// -----------------------------------------------------------
// Nous aurions pu ne pas ecrire/appeler cette fonction et tester
// in-line dans FieldsCheck() la validite de chaque champs, comme
// par exemple en faisant if (CurrentForm.txtEmail.value.length == 0) {}
// Cependant, l'appel a cette deuxieme fonction decharge le developpeur
// des details du type de champ au moment ou il ecrit les controles.
// Les seuls cas ou le developpeur n'appellera pas ceci ce sont les
// cas ou les regles vont plus loin que la seule existence. 
//
// Exemple 1 : Demander une valeur si une case est cochee:
// if (CurrentForm.chkNeedName.checked && CurrentForm.txtNom.value.length == 0) {}
//
// Exemple 2 : Controler que deux champs de mot-de-passe sont identiques:
// if (CurrentForm.txtNewPasswordControl.value != CurrentForm.txtNewPassword.value) {}

function FieldsCheck_HasValue(obj, obj_type) {
    if (obj_type == "TEXT" || obj_type == "PASSWORD") {
        if (obj.value.length == 0) return false;
        else return true; }
    else if (obj_type == "SELECT") {
        for (i=0; i < obj.length; i++) { if (obj.options[i].selected && obj.options[i].value != 0) return true; }
           return false; }
    else if (obj_type == "SINGLE_VALUE_RADIO" || obj_type == "SINGLE_VALUE_CHECKBOX") {
        if (obj.checked) return true;
        else return false; }
    else if (obj_type == "RADIO" || obj_type == "CHECKBOX") {
        for (i=0; i < obj.length; i++) { if (obj[i].checked) return true; }
        return false;    
    }
}

// 3. Controle comme quoi un champ est bien un entier :
// -----------------------------------------------------------
// Recoit une chaine (et non pas un objet de formulaire)
// Le controle se fait sur chaque chiffre individuel
// de la chaine Value de facon a ne pas faire des
// approximations.

function FieldsCheck_IsInteger(Value){
    var i;
    for (i = 0; i < Value.length; i++){   
        var c = Value.charAt(i);
        if (((c < "0") || (c > "9"))) return false;
    }
    return true;
}

// 4. Controle comme quoi un champ est bien un e-mail bien forme :
// -----------------------------------------------------------
// Recoit une chaine (et non pas un objet de formulaire).
// Controle de bonne forme d'une adresse e-mail. Le script suivant
// controle qu'une adresse e-mail a au moins deux caracteres avant le @,
// deux caracteres apres et deux apres le point. Il n'interdit pas une
// valeur vide car cela peut etre normale ou bien controle ailleurs.
// Nous avons aussi desactive le dialogue d'erreur car ce serait au
// code utilisateur de plus haut niveau de l'afficher.

function FieldsCheck_IsEmail(Value) {

    // Nous acceptons que le mail ne soit pas renseigne.
    // Nous ne controlons que si qq chose a ete donne.
    // En effet, le vide peut etre tester avant et ailleurs.
    
    if (Value.length == 0) return true;
    
    // are regular expressions supported?
    var supported = 0;
    if (window.RegExp) {
        var tempStr = "a";
        var tempReg = new RegExp(tempStr);
        if (tempReg.test(tempStr)) supported = 1;
    }
    if (!supported) {
        var IsValidEmail = (Value.indexOf(".") > 2) && (Value.indexOf("@") > 0);
        // Nous desactivons ceci si nous ne voulons pas que la fonction emet elle meme le dialogue d'erreur
        // Ce sera alors a la fonction appelante d'afficher l'erreur a l'utilisateur
        // if (!IsValidEmail) alert("Vous avez donné une adresse de courrier électronique incorrecte.");
        return IsValidEmail;
          // return (Value.indexOf(".") > 2) && (Value.indexOf("@") > 0);
    }
    var r1 = new RegExp("(@.*@)|(\\.\\.)|(@\\.)|(^\\.)");
    var r2 = new RegExp("^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$");
    var IsValidEmail = (!r1.test(Value) && r2.test(Value));
    // Nous desactivons ceci si nous ne voulons pas que la fonction emet elle meme le dialogue d'erreur
    // Ce sera alors a la fonction appelante d'afficher l'erreur a l'utilisateur
    // if (!IsValidEmail) alert("Vous avez donné une adresse de courrier électronique incorrecte.");
    return IsValidEmail
    // return (!r1.test(Value) && r2.test(Value));
}

// 5. Controle que le champ est bien une date bien formee:
// -----------------------------------------------------------
// Recoit une chaine (et non pas un objet de formulaire).
// Cette fonction permet de vérifier la validité d'une date au format jj/mm/aa ou jj/mm/aaaa.
// Elle ne controle pas [encore] les autres formats de date.

function FieldsCheck_IsDate(Value) {
    
    // Retourne si Value est une date valide au format Format.
    // Format peut prendre les valeurs "fr" (default) et "us"
    // (ou toute autre valeur). Cette routine a besoin des routines 
    // IsInteger(), StripChars(), DaysInFebruary() et DaysInMonth().
    //
    // Voir aussi plus haut les valeurs suivantes s'il faut les changer:
    // var DateFormat = "fr"
    // var DateSeparator = "/";  
    // var minYear = 1900;
    // var maxYear = 2100;
    //
    // Tire de SmartWebby.com (http://www.smartwebby.com/dhtml/)

    var tabDaysInMonth = DaysInMonth(12)
    var pos1 = Value.indexOf(DateSeparator)
    var pos2 = Value.indexOf(DateSeparator, pos1 + 1)
    if (DateFormat == "fr") {
        var strDay   = Value.substring(0, pos1)
        var strMonth = Value.substring(pos1 + 1, pos2)
    } else {
        var strDay   = Value.substring(pos1 + 1, pos2)
        var strMonth = Value.substring(0, pos1)
    }
    var strYear = Value.substring(pos2 + 1)
    
    strYr = strYear     // Sauvegarde car deux manipulations separees
    
    if (strDay.charAt(0) == "0" && strDay.length > 1) strDay = strDay.substring(1)
    if (strMonth.charAt(0) == "0" && strMonth.length > 1) strMonth = strMonth.substring(1)
    for (var i = 1; i <= 3; i++) {
        if (strYr.charAt(0) == "0" && strYr.length > 1) strYr = strYr.substring(1)
    }
    month = parseInt(strMonth)
    day = parseInt(strDay)
    year = parseInt(strYr)
    if (pos1 == -1 || pos2 == -1){
        // alert("The date format should be : dd/mm/yyyy")
        return false
    }
    if (strMonth.length < 1 || month < 1 || month > 12) {
        // alert("Please enter a valid month")
        return false
    }
    if (strDay.length < 1 || day < 1 || day > 31 || (month == 2 && day > DaysInFebruary(year)) || day > tabDaysInMonth[month]) {
        // alert("Please enter a valid day")
        return false
    }
    if (strYear.length != 4 || year == 0 || year < minYear || year > maxYear) {
        // alert("Please enter a valid 4 digit year between " + minYear + " and " + maxYear)
        return false
    }
   // if (Value.indexOf(DateSeparator, pos2 + 1) != -1 || IsInteger(StripChars(Value, DateSeparator)) == false) {
   // thierie@ibonia.mg Suppression du deuxieme condition IsInteger(StripChars(Value, DateSeparator)) == false)
   // car cette fonction possede de bug.
    if (Value.indexOf(DateSeparator, pos2 + 1) != -1){
       //  alert("Please enter a valid date")
        return false
    }
    return true
}

// AJOUTER d'autres fonctions de controle ici au fur et a mesure
// en veillant a ce qu'elles soient les plus generiques possibles
// car nous sommes toujours dans la Partie I qui ne doit pas changer.
// ...


// -----------------------------------------------------------
// Fonctions de support utilisees par les fonctions ci-dessus
// -----------------------------------------------------------

// Search through String's characters one by one.
// If character is not in Chars, append to returnString.

function StripChars(String, Chars){
    var i;
    var returnString = "";
    for (i = 0; i < String.length; i++){   
        var c = String.charAt(i);
        if (Chars.indexOf(c) ==  -1) returnString += c;
    }
    return returnString;
}

// February has 29 days in any year evenly divisible by four, 
// EXCEPT for centurial years which are not also divisible by 400.

function DaysInFebruary(year){
    return (((year % 4 ==  0) && ( (!(year % 100 ==  0)) || (year % 400 ==  0))) ? 29 : 28 );
}

// Retourne le nombre de jours pour chaque mois de l'annee
// L'argument perment de ne demander que les n premiers mois
// de l'annee au besoin.

function DaysInMonth(n) {
    for (var i = 1; i <= n; i++) {
        this[i] = 31
        if (i == 4 || i == 6 || i == 9 || i == 11) { this[i] = 30 }
        if (i == 2) {this[i] = 29}
   } 
   return this
}

