//====================================================================================
// Namespace Fsa :
//
//  fonction f_getXYZ(element ou son id)
//   Retourne les coordonnées de l'élément.
//
//  fonction f_numberToString(number, digitCount)
//   Retourne une chaine de caractères représentant le nombre sur digitCount digits avec des zéros à gauche si nécessaire.
//
//  fonction f_newXMLHttpRequest()
//   Retourne un nouvel objet XMLHttpRequest
//
//  fonction f_asyncHttpGet(url, requestHeader, action, xml, timeout)
//  	Envoie une requête GET à l'URL spécifiée ("url").
//   "requestHeader" est un tableau d'objets {header, value}
//   "action" est la fonction qui sera appelée après réception de la réponse du serveur.
//    Elle admet un argument texte.
//                      Si "xml" est TRUE, on passera à "action" une réponse sous forme XML, sinon il sagira de texte.
//   Un "timeout (en ms) peut être précisé.
//   Retourne -1 en cas de problème.
//
//  fonction f_asyncHttpHead(url, action, manageErrors, timeout)
//   Envoie une requête HEAD à l'URL spécifiée ("url").
//   "action" est la fonction qui sera appelée après réception de la réponse du serveur.
//    Elle admet comme argument un tableau de headers de type
//     headers[headerName] = headerValue
//                      "manageErrors" est une fonction appelée en cas de réponse incorrecte du serveur.
//    Elle eadmet comme argument le status et le texte de l'erreur.
//   Un "timeout (en ms) peut être précisé.
//   Retourne -1 en cas de problème.
//
//  fonction f_asyncHttpPost(url, formValues, action, manageErrors, timeout)
//   Envoie une requête POST à l'URL spécifiée ("url").
//   "formValues" est un tableau d'objets {name, value}
//   "action" est la fonction qui sera appelée après réception de la réponse du serveur.
//    Elle admet un argument texte.
//                      Si "xml" est TRUE, on passera à "action" une réponse sous forme XML, sinon il sagira de texte.
//   "manageErrors" est une fonction appelée en cas de réponse incorrecte du serveur.
//    Elle eadmet comme argument le status et le texte de l'erreur.
//   Un "timeout (en ms) peut être précisé.
//   Retourne -1 en cas de problème.
//
//====================================================================================

// Initialisation du NameSpace

var Fsa;

(function()
{
 if (!Fsa)
  Fsa = {};

//====================================================================================

// Constantes
/*
WEBSITE_DOMAIN = 'http://localhost/';
WEBSITE_DIR    = 'zizikafafa/';
*/
/*
WEBSITE_DOMAIN = 'http://www.zizikafafa.be/';
WEBSITE_DIR    = '';
*/
/*
WEBSITE_ROOT   = WEBSITE_DOMAIN + WEBSITE_DIR;
*/

//====================================================================================

HttpCreators = [
 function() { return new XMLHttpRequest(); },
 function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
 function() { return new ActiveXObject("Microsoft.XMLHTTP"); }
 ]; // Trois possibilités de création d'un objet XMLHttpRequest selon le navigateur.

HttpCreator = null; // Celle qui sera utilisée

function f_newXMLHttpRequest()
{
 if(HttpCreator != null)
  return HttpCreator();

 //----- On ne sait pas encore laquelle des 3 méthodes utiliser
 //      => les tester l'une après l'autre

 for(var i = 0; i < HttpCreators.length; i++)
 {
  try
  {
   var cr = HttpCreators[i];
   var req = cr();
   if(req != null)
   {
    HttpCreator = cr;
    return req;
   }
  }
  catch(ex)
  {
   continue;
  }
 }

 //----- Aucune n'a fonctionné

 HttpCreator = function()
 {
  throw new Error("L'objet XMLHttpRequest n'est pas pris en charge par votre navigateur.");
 }

 HttpCreator(); // Génère volontairement une erreur
}

//====================================================================================

function f_asyncHttpGet(url, requestHeader, action, xml, timeout)
{
 var minuterie;

 var req = f_newXMLHttpRequest();
 if (req == null)
  return -1;

 if (xml)
 {
  req.onreadystatechange = function()
  {
   if (req.readyState == 4) // la réponse du serveur est complète
   {
    if (minuterie)
     clearTimeout(minuterie);

    if (req.status == 200) // la requête a réussi
     action(req.responseXML);
   }
  }
 }
 else
 {
  req.onreadystatechange = function()
  {
   if (req.readyState == 4) // la réponse du serveur est complète
   {
    if (minuterie)
     clearTimeout(minuterie);

    if (req.status == 200) // la requête a réussi
     action(req.responseText);
   }
  }
 }

 req.open("GET", url);

 for(var i = 0; i < requestHeader.length; i++)
 {
  req.setRequestHeader(requestHeader[i].header, requestHeader[i].value);
 }

 req.send(null);

 if (timeout)
 {
  minuterie = setTimeout(
   function()
   {
    req.abort();
    throw new Error("Timeout expiré sur la requête passée au serveur.");
   },
   timeout);
 }

 return 1;
}

//====================================================================================

function f_asyncHttpHead(url, action, manageErrors, timeout)
{
 var minuterie;

 var req = f_newXMLHttpRequest();
 if (!req)
  return -1;

 req.onreadystatechange = function()
 {
  if (req.readyState == 4) // la réponse du serveur est complète
  {
   if (minuterie)
    clearTimeout(minuterie);

   if (req.status == 200) // la requête a réussi
    action(f_httpHeaderAnalysis(req));
   else
   {
    if(manageErrors)
     manageErrors(req.status, req.statusText);
    else
     action(null);
   }
  }
 }

 req.open("HEAD", url);

 req.send(null);

 if (timeout)
 {
  minuterie = setTimeout(
   function()
   {
    req.abort();
    throw new Error("Timeout expiré sur la requête passée au serveur.");
   },
   timeout);
 }

 return 1;
}

//====================================================================================

function f_httpHeaderAnalysis(req)
{
 var headerText = req.getAllResponseHeaders();
 var headers = {};
 var ed = /^\s*/; // espaces de début
 var ef = /\s*$/; // espaces de fin

 var lines = headerText.split("\n");

 for (var i = 0; i < lines.length; i++)
 {
  var line = lines[i];
  if (line.length == 0) continue;

  var pos = line.indexOf(':');
  var headerName  = line.substing(0, pos).replace(ed, "").replace(ef, "");
  var headerValue = line.substing(pos + 1).replace(ed, "").replace(ef, "");

  headers[headerName] = headerValue;
 }

 return headers;
}

//====================================================================================

/*
 Transforme un tableau en une string au même format que celles provenant d'un formulaire <form>
*/

function f_manageFormValues(formValues)
{
 var paires = [];
 var sp = /%20/g; //espace insérés par encodeURIComponent

 for(var prop in formValues)
 {
                if (typeof(formValues[prop]) == 'string')
                 var val = formValues[prop];
                else
   var val = (formValues[prop]).toString();

  var paire = encodeURIComponent(prop).replace(sp, "+") + '=' + encodeURIComponent(val).replace(sp, "+");
  paires.push(paire);
 }

 var text_out = paires.join('&'); // on concatène toutes les paires en les séparent par des '&'

 return text_out;
}

//====================================================================================

function f_getHttpResponse(req)
{
 switch(req.getResponseHeader("Content-Type"))
 {
  case "text/xml":
   return req.responseXML;

  case "text/json": //JavaScript Object Notation
  case "text/javascript":
  case "application/javascript":
   return eval(req.responseText);

  default:
   return req.responseText;
 }
}

//====================================================================================

function f_asyncHttpPost(url, formValues, act, manageErrors, timeout)
{
 try
 {
  var minuterie;

  var req = f_newXMLHttpRequest();
  if (!req)
   return -1;

  if(act)
  {
   req.onreadystatechange = function()
    {
     if (req.readyState == 4) // la réponse du serveur est complète
     {
      if (minuterie)
       clearTimeout(minuterie);

      if (req.status == 200) // la requête a réussi
      {
       if(act)
        act(f_getHttpResponse(req));
      }
      else
      {
       if(manageErrors)
        manageErrors(req.status, req.statusText);
       else
        if(act)
         act(null);
      }
     }
    }
  }

  req.open('POST', url);  // !!! l'url doit avoir le même domaine que la page qui utilise ce script sinon "Permission refusée d'appeler la méthode XMLHttpRequest.open"

  req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

  req.send(f_manageFormValues(formValues));

  if (timeout)
  {
   minuterie = setTimeout(
    function()
    {
     req.abort();
     throw new Error("Timeout expiré sur la requête passée au serveur.");
    },
    timeout);
  }

  return 1;
 }
 catch(e)
 {
  alert(e);
  return -1;
 }
}

//====================================================================================

/*
 Retourne le contenu du {} suivant
*/

function f_unser_getArrayLimits(response)
{
 var level = 0;
 var posOpen = response.indexOf('{');
 if (posOpen >= 0)
  level++;
 else
 {
//alert(1);
  return -1;
 }
 //----- rechercher l'accolade fermante de même niveau

 var posNext = posOpen;
 while(true)
 {
  var posNextOpen = response.indexOf('{', posNext + 1);
  var posNextClose = response.indexOf('}', posNext + 1);

  if (posNextClose > 0 && (posNextOpen < 0 || posNextOpen > posNextClose))
  {
   // la première accolade rencontrée est fermante
   posNext = posNextClose;
   level--;
  }
  else if (posNextOpen > 0)
  {
   // la première accolade rencontrée est ouvrante
   posNext = posNextOpen;
   level++;
  }
  else
  {
//alert(2);
   return -1;
  }

  if (level == 0)
   break;
 }

 posClose = posNext;
//alert(response.substring(posOpen + 1, posClose));
 return response.substring(posOpen + 1, posClose);
}

//==================================================================================

/*
 La fonction serialize() de PHP transforme un tableau en string.
 Ceci est la fonction inverse, qui, à partir de la string, recrée un array, une string ou un int
*/

function f_unserialize(response)
{
 switch (response.charAt(0))
 {
  case 's':
   var posEndLen = response.indexOf(':', 2);
   var len = parseInt(response.substring(response.indexOf(':') + 1, posEndLen));
   var str = response.substr(response.indexOf(':', 2) + 2, len);
   return {val:str, len:posEndLen + len + 4};

  case 'i':
   var posEndVal = response.indexOf(';');
   var num = parseInt(response.substring(response.indexOf(':') + 1, posEndVal));
   return {val:num, len:posEndVal + 1};

  case 'a':
   var sArray = f_unser_getArrayLimits(response);
   if (sArray == -1)
    return null;

   //----- Lire le nombre de valeurs contenues dans le tableau

   var arrayContent = new Object;

   var posStart = 0;
   var posStartArray = response.indexOf('{');
   var keysCount = parseInt(response.substring(response.indexOf(':') + 1, posStartArray));
   for (var i = 0; i < keysCount; i++)
   {
    var oKeyName = f_unserialize(sArray.substr(posStart));
    posStart += oKeyName.len;

    var oValue = f_unserialize(sArray.substr(posStart));
    posStart += oValue.len

    arrayContent[oKeyName.val] = oValue.val;
   }
   return {val:arrayContent, len:posStartArray + sArray.length + 3};

  case 'N':
   return {val:null, len:2};

  case '<':
   // Message d'erreur du serveur (on le retrouvera dans php.log)
   alert('f_unserialize() : Message d\'erreur du serveur\n' + response.replace(/\<br \/\>/g, '\n').replace(/\<b\>/g, '').replace(/\<\/b\>/g, ''));
   return null;

  default:
   alert('f_unserialize() : Contenu inapproprié : ' + response);
   return null;
 }
}

//============================================================================

function f_serialize(obj)
{
 var text_out = '';

 switch(typeof obj)
 {
  case 'number' :
   text_out = 'i:' + obj + ';';
   break;

  case 'string' :
   text_out = 's:' + obj.length + ':"' + obj + '";';
   break;

  case 'object' :
   if(obj)
   {
    var cnt = 0;
    var t_o = '';
    for(var prop in obj)
    {
     t_o += f_serialize(prop);
     t_o += f_serialize(obj[prop]);
     cnt++;
    }

    text_out = 'a:' + cnt + ':{' + t_o + '};';
   }
   else
    text_out= 'N;';

   break;
 }
//alert(obj + ' => ' + text_out);
 return text_out;
}

//============================================================================

/*
 Inverse de la fonction PHP serialize(), pour analyse de la réponse du serveur
*/
/*
function f_unserialize(response)
{
 var t_response = new Object();

 switch (response.charAt(0))
 {
  case 'a':
   break;

  case 's':
   return response.substring(response.indexOf(':', 2) + 1, response.indexOf(';'));
   break;

  case 'i':
   return response.substring(response.indexOf(':') + 1, response.indexOf(';'));
   break;
 }


 var t_response = new Array();

 while(true)

  var pos = response.indexOf('"result";');
  if (pos < 0)
  {
   alert('Réponse du serveur mal formatée');
   return;
  }

  posStart = response.indexOf(':', pos + 9);
  posEnd = response.indexOf(';', posStart);
  result = parseInt(response.substring(posStart + 1, posEnd));

}
*/
//====================================================================================

/*
 Fonction à appeler pour enregistrer un message dans la table de log
*/

function f_log(script, msg)
{
 try
 {
  var arg = [];

  arg['script'] = script;
  arg['msg'] = msg;
  arg['_query'] = 'error';

  Fsa.f_asyncHttpPost(WEBSITE_ROOT + 'inc/php/_req_log.php', arg);

  return 1;
 }
 catch(e)
 {
   if(e.toString().indexOf('Fsa.f_asyncHttpPost is not a function')) // Voir d'où vient cette erreur : "Type error : Fsa.f_asyncHttpPost is not a function
    return 1;

   alert('f_log() : ' + e);
   return -1;
 }
}
//====================================================================================

/*
 Fonction à appeler pour enregistrer une exception dans la table de log
*/

function f_logException(script, ex)
{
 try
 {
  var arg = [];

  arg['jsExMessage'] = ex.message;
  arg['jsExName'] = ex.name;
  arg['msg'] = ex.toString();
  arg['script'] = script;
  arg['_query'] = 'error';

  Fsa.f_asyncHttpPost(WEBSITE_ROOT + 'incinc/php/_req_log.php', arg);

  return 1;
 }
 catch(e)
 {
   if(e.toString().indexOf('Fsa.f_asyncHttpPost is not a function')) // Voir d'où vient cette erreur : "Type error : Fsa.f_asyncHttpPost is not a function
    return 1;

   alert('f_log() : ' + e);
   return -1;
 }
}

//====================================================================================

function f_exception(script, ex)
{
 f_logException(script, ex);
 window.alert(script + ' : ' + ex);
}

//====================================================================================

function f_getXYZ(ael)
{
 try
 {
  if(typeof ael == "string")
   ael = document.getElementById(ael);

  var coord = {x:0, y:0, z:0};

  //----- Cumuler les positions relatives d'élément parent en élément parent

  for(var e = ael; e; e = e.offsetParent)
  {
   coord.x += e.offsetLeft;
   coord.y += e.offsetTop;
  }

  //----- soustraire le défilement

  if(navigator.appName != 'Opera')
   for(e = ael.parentNode; e && e != document.body; e = e.parentNode)
   {
    if (e.scrollLeft)
     coord.x -= e.scrollLeft;
    if (e.scrollTop)
     coord.y -= e.scrollTop;
   }

  //----- position Z

  if (ael.currentStyle)
   coord.z = ael.currentStyle.zIndex;
  else
   if(window.getComputedStyle)
    if(document.getElementById(ael.id))
     coord.z = window.getComputedStyle(ael, null).zIndex;

  return coord;
 }
 catch(ex)
 {
  f_exception('f_getXYZ()', ex);
  return {x:0, y:0, z:0};
 }
}

//====================================================================================

function f_numberToString(num, digitCount)
{
 var text_out = "000000000000000000000000000000000000000000" + num;
 return text_out.substr(text_out.length - digitCount, digitCount);
}

//====================================================================================

function f_ltrim(txt)
{
 while(txt.charAt(0) == ' ')
  txt = txt.substr(1);
 return txt;
}

//====================================================================================

function f_rtrim(txt)
{
 while(txt.charAt(txt.length - 1) == ' ')
  txt = txt.substr(0, txt.length - 1);
 return txt;
}

//====================================================================================

function f_trim(txt)
{
 return f_ltrim(f_rtrim(txt));
}

//==================================================================================

/*
 Evalue le datatype d'un argument
*/

function f_evalDataType(arg)
{
 try
 {
  //----- boolean ?

  switch (arg.toLowerCase())
  {
   case 'true' :
   case 'false' :
    return 'boolean';
  }

  //----- datetime ?

  if(arg.length == 19
   && arg.charAt(4) == '-'
   && arg.charAt(7) == '-'
   && arg.charAt(10) == ' '
   && arg.charAt(13) == ':'
   && arg.charAt(16) == ':'
   && !isNaN(parseInt(arg.substr(0,4)))
   && !isNaN(parseInt(arg.substr(5,2)))
   && !isNaN(parseInt(arg.substr(8,2)))
   && !isNaN(parseInt(arg.substr(11,2)))
   && !isNaN(parseInt(arg.substr(14,2)))
   && !isNaN(parseInt(arg.substr(17,2)))
   )
   return 'datetime';

  //----- date ?

  if(arg.length == 10
   && arg.charAt(4) == '-'
   && arg.charAt(7) == '-'
   && !isNaN(parseInt(arg.substr(0,4)))
   && !isNaN(parseInt(arg.substr(5,2)))
   && !isNaN(parseInt(arg.substr(8,2)))
   )
   return 'date';

  //----- time ?

  if(arg.length == 8
   && arg.charAt(2) == ':'
   && arg.charAt(5) == ':'
   && !isNaN(parseInt(arg.substr(0,2)))
   && !isNaN(parseInt(arg.substr(3,2)))
   && !isNaN(parseInt(arg.substr(6,2)))
   )
   return 'time';

  if(arg.length == 9
   && arg.charAt(0) == '-'
   && arg.charAt(3) == ':'
   && arg.charAt(6) == ':'
   && !isNaN(parseInt(arg.substr(1,2)))
   && !isNaN(parseInt(arg.substr(4,2)))
   && !isNaN(parseInt(arg.substr(7,2)))
   )
   return 'time';  // durée négative

  //----- number ?

  if(!isNaN(parseFloat(arg)))
   return 'number';

  return 'alpha';
 }
 catch(ex)
 {
  Fsa.f_exception('f_evalDataType("' + arg + '")', ex);
  return null;
 }
}

//===================================================================================

function f_daysInMonth(month, year)
{
 try
 {
  if (month > 12)
  {
   year += ((month - 1) / 12).toFixed();
   month = (month - 1) % 12 + 1;
  }

  while (month < 1)
  {
   year --;
   month += 12;
  }

  switch(month)
  {
   case 1 :
   case 3 :
   case 5 :
   case 7 :
   case 8 :
   case 10 :
   case 12 :
    return 31;

   case 4 :
   case 6 :
   case 9 :
   case 11 :
    return 30;

   case 2 :
    if(year % 4)
     return 28; // non bissextile

    if (year % 1000 == 0)
     return 29; // millénaire

    if (year % 100 == 0)
     return 28; // centenaire

    return 29; // bissextile "normale"

   default :
    return null;
  }
 }
 catch(ex)
 {
  Fsa.f_exception('f_daysInMonth(' + month + ',' + year + ')', ex);
  return null;
 }
}

//===================================================================================

function f_normalizeDateTime(dt)
{
 try
 {
  //----- Convertir la partie time en un nombre de secondes

  if(dt.s == null) dt.s = 0;
  if(dt.m == null) dt.m = 0;
  if(dt.h == null) dt.h = 0;

  var secondes = dt.s + dt.m * 60 + dt.h * 60 * 60;

  //----- cas d'un simple time :

  if (dt.Y == null && dt.M == null && dt.D == null)
  {
   if(secondes > 0)
   {
    dt.s = secondes;

    dt.m = (dt.s / 60).toFixed();
    dt.s = dt.s % 60;

    dt.h = (dt.m / 60).toFixed();
    dt.m = dt.m % 60;
   }
   else
   {
    //----- durée négative

    dt.s = - secondes;

    dt.m += (dt.s / 60).toFixed();
    dt.s = dt.s % 60;

    dt.h += (dt.m / 60).toFixed();
    dt.m = dt.m % 60;

    dt.s = -dt.s;
    dt.m = -dt.m;
    dt.h = -dt.h;
   }

   return {Y:null, M:null, D:null, h:dt.h, m:dt.m, s:dt.s};
  }

  //----- cas d'un datetime (ou d'un simple date)

  //---------- normaliser la partie time

  t = f_normalizeDateTime({Y:null, M:null, D:null, h:dt.h, m:dt.m, s:dt.s});

  //---------- secondes

  while(dt.s < 0)
  {
   dt.m--;
   dt.s += 60;
  }
  dt.m += (dt.s / 60).toFixed();
  dt.s = dt.s % 60;

  //---------- minutes

  while(dt.m < 0)
  {
   dt.h--;
   dt.m += 60;
  }
  dt.h += (dt.m / 60).toFixed();
  dt.m = dt.m % 60;

  //---------- heure

  while(dt.h < 0)
  {
   dt.D--;
   dt.h += 24;
  }
  dt.D += (dt.h / 24).toFixed();
  dt.h = dt.h % 24;

  //---------- jour

  while(dt.D < 1)
  {
   dt.M--;
   dt.D += f_daysInMonth(dt.M, dt.Y);
  }

  while(dt.D > f_daysInMonth(dt.M, dt.Y))
  {
   dt.D -= f_daysInMonth(dt.M, dt.Y);
   dt.M++;
  }

  //---------- mois

  while(dt.M < 1)
  {
   dt.Y--;
   dt.M += 12;
  }

  while(dt.M > 12)
  {
   dt.M -= 12;
   dt.Y++;
  }

  //----- c'est normalisé

  return {Y:dt.Y, M:dt.M, D:dt.D, h:dt.h, m:dt.m, s:dt.s};
 }
 catch(ex)
 {
  Fsa.f_exception('f_normalizeDateTime()', ex);
  return null;
 }
}

//===================================================================================

function f_timeHmsToString(hours, minutes, seconds)
{
 try
 {
  var date = f_normalizeDateTime({Y:null, M:null, D:null, h:hours, m:minutes, s:seconds});

  if(date.h < 0 || date.m < 0 || date.s < 0)
  {
   //----- durée négative
   var h = -date.h;
   var m = -date.m;
   var s = -date.s;
  }
  else
  {
   var h = date.h;
   var m = date.m;
   var s = date.s;
  }

  var hours = h.toString(10);
  if (hours.length == 1)
   hours = '0' + hours;

  minutes = m.toString(10);
  minutes = ('00' + minutes).substr(minutes.length);

  seconds = s.toString(10);
  seconds = ('00' + seconds).substr(seconds.length);

  if(date.h < 0 || date.m < 0 || date.s < 0)
   return "-" + hours + ":" + minutes + ":" + seconds; // Pour les durées négatives, on place un 'moins' devant
  else
   return hours + ":" + minutes + ":" + seconds;
 }
 catch(ex)
 {
  Fsa.f_exception('f_timeHmsToString()', ex);
  return null;
 }
}

//===================================================================================

function f_dateYmdToString(year, month, day)
{
 try
 {
  var date = f_normalizeDateTime({Y:year, M:month, D:day, h:0, m:0, s:0});
  var Y = date.Y.toString();
  var M = date.M.toString();
  var D = date.D.toString();

  return  Y + "-" + ('00' + M).substr(M.length) + "-" + ('00' + D).substr(D.length);
 }
 catch(ex)
 {
  Fsa.f_exception('f_dateYmdToString()', ex);
  return null;
 }
}

//===================================================================================

function f_YmdHmsToString(year, month, day, hours, minutes, seconds)
{
 try
 {
  if (year == null || month == null || day == null)
  {
   if (hours == null || minutes == null || seconds == null)
    return null;
   return f_timeHmsToString(hours, minutes, seconds);
  }
  else if (hours == null || minutes == null || seconds == null)
   return f_dateYmdToString(year, month, day);
  else
  {
   var date = f_normalizeDateTime({Y:year, M:month, D:day, h:hours, m:minutes, s:seonds});
   var Y = date.Y.toString();
   var M = date.M.toString();
   var D = date.D.toString();
   var h = date.h.toString();
   var m = date.m.toString();
   var s = date.s.toString();

   return  Y + "-" + ('00' + M).substr(M.length) + "-" + ('00' + D).substr(D.length) + ' ' + ('00' + h).substr(h.length) + ":" ('00' + m).substr(m.length) + ":" ('00' + s).substr(s.length);
  }
 }
 catch(ex)
 {
  Fsa.f_exception('f_YmdHmsToString()', ex);
  return null;
 }
}

//===================================================================================

function f_stringToYmdHms(txt)
{
 try
 {
  var dataType = f_evalDataType(txt);
  var Y = null;
  var M = null;
  var D = null;
  var h = null;
  var m = null;
  var s = null;

  switch(dataType)
  {
   case 'datetime' :
    Y = parseInt(txt.substr( 0,4));
    M = parseInt(txt.substr( 5,2));
    D = parseInt(txt.substr( 8,2));
    h = parseInt(txt.substr(11,2));
    m = parseInt(txt.substr(14,2));
    s = parseInt(txt.substr(17,2));
    break;

   case 'date' :
    Y = parseInt(txt.substr( 0,4));
    M = parseInt(txt.substr( 5,2));
    D = parseInt(txt.substr( 8,2));
    break;

   case 'time' :
    if(txt.charAt(0) == '-')
    {
     //----- durée négative
     h = -parseInt(txt.substr(1,2));
     m = -parseInt(txt.substr(4,2));
     s = -parseInt(txt.substr(7,2));
    }
    else
    {
     h = parseInt(txt.substr(0,2));
     m = parseInt(txt.substr(3,2));
     s = parseInt(txt.substr(6,2));
    }
    break;

   default :
    return null;
  }

  return {Y:Y, M:M, D:D, h:h, m:m, s:s};
 }
 catch(ex)
 {
  Fsa.f_exception('f_stringToYmdHms()', ex);
  return null;
 }
}

//===================================================================================

/*
 L'argument 'date' peut être une date, un datetime, un time
*/

function f_addTime(date, time)
{
 try
 {
  //----- si les arguments sont des strings, alors les convertir en {Y,M,D,h,m,s}
  //      (et mémoriser le fait que la sortie devra se faire sous forme de string)

  var dataTypeOut = 'oDT'; // par défaut

  if(typeof date == 'string')
  {
   dataTypeOut = 'string';
   date = f_stringToYmdHms(date);
  }
  if(typeof time == 'string')
   time = f_stringToYmdHms(time);

  //----- convertir les null

  if (date.h == null) date.h = 0;
  if (date.m == null) date.m = 0;
  if (date.s == null) date.s = 0;

  if (time.h == null) time.h = 0;
  if (time.m == null) time.m = 0;
  if (time.s == null) time.s = 0;

  //----- l'addition

  date.h += time.h;
  date.m += time.m;
  date.s += time.s;

  date = f_normalizeDateTime(date);

  //----- sortie

  if (dataTypeOut = 'string')
   return f_YmdHmsToString(date.Y, date.M, date.D, date.h, date.h, date.s);
  else
   return date;
 }
 catch(ex)
 {
  Fsa.f_exception('f_addTime()', ex);
  return null;
 }
}

//===================================================================================

function f_multiplyTime(time, num)
{
 try
 {
  //----- si les arguments sont des strings, alors les convertir en {Y,M,D,h,m,s}
  //      (et mémoriser le fait que la sortie devra se faire sous forme de string)

  var dataTypeOut = 'oDT'; // par défaut

  if(typeof time == 'string')
  {
   dataTypeOut = 'string';
   time = f_stringToYmdHms(time);
  }

  //----- convertir les null

  if (time.h == null) time.h = 0;
  if (time.m == null) time.m = 0;
  if (time.s == null) time.s = 0;

  //----- la multiplication

  var seconds = (time.s + time.m * 60 + time.h * 60 * 60) * num;

  time.h = 0;
  time.m = 0;
  time.s = seconds;

  time = f_normalizeDateTime(time);

  //----- sortie

  if (dataTypeOut = 'string')
   return f_YmdHmsToString(date.Y, date.M, date.D, date.h, date.h, date.s);
  else
   return time;
 }
 catch(ex)
 {
  Fsa.f_exception('f_multiplyTime()', ex);
  return null;
 }
}

//===================================================================================

function f_diviseTime(time, num)
{
 try
 {
  f_multiplyTime(time, 1.0 / num);
 }
 catch(ex)
 {
  Fsa.f_exception('f_diviseTime()', ex);
  return null;
 }
}

//===================================================================================

function f_attachEvent(el, evt, eh)
{
 try
 {
  if (el.addEventListener)
   el.addEventListener(evt, eh, false);
  /*
 else if (el.attachEvent)
  el.attachEvent("on" + evt, eh);

SUPPRIMÉ CAR GENERE DES PROBLEMES DANS L'UTILISATION DE 'this' AVEC IE "Cet objet ne gère pas cette propriété ou cette méthode".
Pour IE, 'this' fait référence à 'window' et non à l'élément auquel est attaché le gestionnaire.
*/
  else
   el["on" + evt] = eh;
 }
 catch(ex)
 {
  f_exception('f_attachEvent()', ex);
 }
}

//====================================================================================

function f_attachImgEvents()
{
 try
 {
  var imgs = document.getElementsByTagName('img');

  for (var i = 0; i < imgs.length; i++)
  {
   if(imgs[i].className == 'buttonImage')
   {
    //----- boutons-images (class='buttonImage', avec attributs imgmousedown et imgmouseup, sans attribut src)

    var imgMouseDown = imgs[i].getAttribute('imgmousedown');
    if(imgMouseDown)
    {
     (new Image()).src = imgMouseDown; // Mise en cache
     f_attachEvent(imgs[i], 'mousedown', function(){this.src = this.getAttribute('imgmousedown');});
    }

    var imgMouseUp = imgs[i].getAttribute('imgmouseup');
    if(imgMouseUp)
    {
     imgs[i].src = imgMouseUp;
     f_attachEvent(imgs[i], 'mouseup', function(){this.src = this.getAttribute('imgmouseup');});
     f_attachEvent(imgs[i], 'mouseout', function(){this.src = this.getAttribute('imgmouseup');});
    }
   }
   else
   {
    var imgMouseOver = imgs[i].getAttribute('imgmouseover');
    if (imgMouseOver)
    {
     //----- images de survol (avec attributs mouseover et mouseout)

     (new Image()).src = imgMouseOver; // Mise en cache
     f_attachEvent(imgs[i], 'mouseover', function(){this.src = this.getAttribute('imgmouseover');});
    }

    if(imgs[i].getAttribute('imgmouseout'))
     f_attachEvent(imgs[i], 'mouseout', function(){this.src = this.getAttribute('imgmouseout');});
   }
  }
 }
 catch(ex)
 {
  f_exception('f_attachImgEvents()', ex);
 }
}

//====================================================================================

function f_replaceCookieValue(key, val)
{
 try
 {
  //----- Lecture du cookie

  var cookieTxt = '' + document.cookie;

//alert(cookieTxt);

/*
  //----- Supprimer l'ancienne valeur si elle existe

  var posLg = cookieTxt.indexOf(key + '=');
  if (posLg >= 0)
  {
   posEndLg = cookieTxt.indexOf(";", posLg);
   if (posEndLg < 0)
    posEndLg = cookieTxt.length;

   cookieTxt = cookieTxt.substr(0, posLg) + cookieTxt.substr(posEndLg + 1);
  }

  //----- Remplacement

  if(cookieTxt.charAt(cookieTxt.length - 1) == ";")
   cookieTxt = cookieTxt.substr(0,cookieTxt.length - 1); // Enlever le dernier ';'

  cookieTxt += ";" + key + '=' + val; // + "max-age=" + (60*60*24*365);

  if(cookieTxt.charAt(0) == ";")
   cookieTxt = cookieTxt.substr(1); // Enlever le premier ';'
*/

  var posKey = cookieTxt.indexOf(key + '=');
  if(posKey != -1)
  {
   var posVal = posKey + key.length + 1;
   var posEnd = cookieTxt.indexOf(';', posVal);
   if (posEnd == -1)
    posEnd = cookieTxt.length;
   var oldValue = cookieTxt.substring(posVal, posEnd);
   oldValue = decodeURIComponent(oldValue);

   cookieTxt = cookieTxt.substr(0, posVal) + val + cookieTxt.substr(posEnd);
  }
  else
  {
   if(cookieTxt.charAt(cookieTxt.length - 1) == ";")
    cookieTxt = cookieTxt.substr(0,cookieTxt.length - 1); // Enlever le dernier ';'
   cookieTxt += ";" + key + '=' + val;
   if(cookieTxt.charAt(0) == ";")
    cookieTxt = cookieTxt.substr(1); // Enlever le premier ';'
  }
//alert(cookieTxt);
  document.cookie = cookieTxt;
 }
 catch(ex)
 {
  Fsa.f_exception('f_replaceCookieValue()', ex);
 }
}

//====================================================================================

/*
 Lit les arguments de l'URL et retourne un tableau du type "arg[name] = value"
*/

function f_readUrlArgs()
{
 try
 {
  var args = new Array();
  var req = location.search.substring(1);
  var items = req.split('&');
  for (var i = 0; i < items.length; i++)
  {
   var pos = items[i].indexOf('=');
   if (pos == -1)
    continue;

   var argName  = items[i].substring(0, pos);
   var argValue = items[i].substring(pos + 1);

   args[argName] = decodeURIComponent(argValue);
  }
  return args;
 }
 catch(ex)
 {
  Fsa.f_exception('f_readUrlArgs()', ex);
 }
}

//====================================================================================

/*
 Vide l'élémnet de son contenu
*/

function f_clearContent(ael)
{
 try
 {
  for (var i = ael.childNodes.length - 1; i >= 0 ; i--)
   ael.removeChild(ael.childNodes[i]);
 }
 catch(ex)
 {
  Fsa.f_exception('f_clearContent()', ex);
 }
}

//====================================================================================

// Constantes publiques

 Fsa.WEBSITE_DOMAIN = WEBSITE_DOMAIN;
 Fsa.WEBSITE_DIR    = WEBSITE_DIR;
 Fsa.WEBSITE_ROOT   = WEBSITE_ROOT;

// Fonctions publiques

 Fsa.f_newXMLHttpRequest  = f_newXMLHttpRequest;
 Fsa.f_asyncHttpGet       = f_asyncHttpGet;
 Fsa.f_asyncHttpHead      = f_asyncHttpHead;
 Fsa.f_asyncHttpPost      = f_asyncHttpPost;

 Fsa.f_serialize          = f_serialize;
 Fsa.f_unserialize        = f_unserialize;

 Fsa.f_getXYZ             = f_getXYZ;

 Fsa.f_evalDataType       = f_evalDataType;
 Fsa.f_daysInMonth        = f_daysInMonth;
 Fsa.f_normalizeDateTime  = f_normalizeDateTime;
 Fsa.f_dateYmdToString    = f_dateYmdToString;
 Fsa.f_timeHmsToString    = f_timeHmsToString;
 Fsa.f_YmdHmsToString     = f_YmdHmsToString;
 Fsa.f_stringToYmdHms     = f_stringToYmdHms;
 Fsa.f_addTime            = f_addTime;
 Fsa.f_multiplyTime       = f_multiplyTime;
 Fsa.f_diviseTime         = f_diviseTime;

 Fsa.f_numberToString     = f_numberToString;

 Fsa.f_ltrim              = f_ltrim;
 Fsa.f_rtrim              = f_rtrim;
 Fsa.f_trim               = f_trim;

 Fsa.f_attachEvent        = f_attachEvent;
 Fsa.f_attachImgEvents    = f_attachImgEvents;

 Fsa.f_log                = f_log;
 Fsa.f_logException       = f_logException;
 Fsa.f_exception          = f_exception;

 Fsa.f_replaceCookieValue = f_replaceCookieValue;
 Fsa.f_readUrlArgs        = f_readUrlArgs;

 Fsa.f_clearContent       = f_clearContent;
})();

//Fsa.f_log('gen.js', 'Un petit coucou');
