/*
 * Ever Ezida (c) 2004 
 * @author tdn, sau
 */
 
/*
* Variables globales utilisées dans les .js pour la saisie marc
*/
var schemaTypeRoot      = 0;
var schemaTypeLeaf      = 1;
var schemaTypeSelection = 2;
var schemaTypeSet       = 3;
var schemaTypeSql       = 4;

// -----------------------------------------------------------------------------
// Un générateur d'identifiant entier unique 
// -----------------------------------------------------------------------------
function IdFactory()
{
   this.counter = 0;
   return this;
}
//
IdFactory.prototype.getNextId = function ()
{
   this.counter ++;
   return this.counter;
}
//
IdFactory.prototype.getCurrentId = function ()
{
   return this.counter;
}
//
IdFactory.prototype.setCurrentId = function (id)
{
   this.counter = id;
}

// -----------------------------------------------------------------------------
// Gestion des onglets
// type : 1 : Horizontal, 2 : vertical
// -----------------------------------------------------------------------------
var allHtmlTabViews = new Array();

function HtmlTabView(div, type, styleSelected, styleNotSelected)
{
   this.type = type;
   this.div = div;
   this.items = new Array();
   this.selectedIndex = 0;
   this.styleSelected = styleSelected;
   this.styleNotSelected = styleNotSelected;
   
   allHtmlTabViews[div.id] = this;
   
   return this;
}
// Ajoute un onglet
HtmlTabView.prototype.add = function (label, action)
{
   var tab = new HtmlTab(label, action);
   this.items[this.items.length] = tab;  
}
// Handler appelÃ© pour mettre Ã  jour l'onglet sÃ©lectionnÃ©
// Si une action avait Ã©tÃ© dÃ©finie pour l'onglet, elle est 
// appelÃ©e, sinon l'action par dÃ©faut est de l'afficher et de 
// masquer les autres
function HtmlTabView_setCurrentTab(divId, idx)
{
   var tabview = allHtmlTabViews[divId];
   tabview.selectedIndex = idx;
   tabview.refresh();
   var tabAction = tabview.items[idx].action;
   // Evalue l'action associÃ©e Ã  l'onglet si elle est dÃ©finie
   if ( tabAction )
   {
      try
      {
	     eval("window." + tabAction);
	  }
	  catch(e)
	  {
	     alert("Error during evaluation of tab action :\n" + tabAction);
	  }
   }
   else // L'action par dÃ©faut
   {
      for(var i=0; i<tabview.items.length; i++)
      {
         var divContentId = tabview.items[i].divContentId;
         var divElem = document.getElementById(divContentId);
         if ( ! divElem )
         {
            alert("HtmlTab with divContentId = '" + divContentId + "' not found !");
            continue;
         }
         if ( i==idx ) // affiche
         {
            divElem.style.visibility = "visible";
            divElem.style.display = "block";
         }
         else // masque
         {
            divElem.style.visibility = "hidden";
            divElem.style.display = "none";
         }
      }
   }
}
// GÃ©nÃ¨re le code HTML dans la div
HtmlTabView.prototype.refresh = function ()
{
   var ret = "";
   
   if ( this.type == 1 )
   {
      ret += "<table cellspacing='0' border='0' cellpadding='0'>";
      ret += "<tr>";
      for(var i=0; i<this.items.length; i++)
      {
         var style = (this.selectedIndex == i) ? this.styleSelected : this.styleNotSelected;
         ret += "<td nowrap='true' class='" + style + "'>";
         ret += "<a href=\"javascript:HtmlTabView_setCurrentTab('" + this.div.id + "'," + i + ");";
         ret += "\" ";
         //ret += this.items[i].action + "\" ";
         ret += "class='" + style + "'>&nbsp;" + this.items[i].label + "&nbsp;</a>";
         ret += "</td>";
      }
      ret += "</tr></table>";
      // Fin des onglets
      /*
      ret += "<table border='0' cellspacing='0' width='100%'><tr>";
      ret += "<td class='" + this.styleSelected + "'>";
      ret += "<table border='0' cellspacing='0' cellpadding ='0' height='3'><tr>";
      ret += "<td class='" + this.styleSelected + "'>";
      ret += "</td></tr></table></td></tr></table>";
      */
   }
   else
   {
      ret += "<table width='100%' cellspacing='0' border='0' cellpadding='0'>";
      for(var i=0; i<this.items.length; i++)
      {
         var style = (this.selectedIndex == i) ? this.styleSelected : this.styleNotSelected;
         ret += "<tr><td nowrap='true' class='" + style + "'>";
         ret += "<a href=\"javascript:HtmlTabView_setCurrentTab('" + this.div.id + "'," + i + ");";
         ret += "\" ";
         //ret += this.items[i].action + "\" ";
         ret += "class='" + style + "'>&nbsp;" + this.items[i].label + "&nbsp;</a>";
         //ret += "</td></tr><tr><td height='3'></td></tr>";
         ret += "</td></tr>";
      }
      ret += "</table>";
   }

   
   this.div.innerHTML = ret;
}

 

// Onglet onglet privÃ©
function HtmlTab(label, action, divContentId)
{
   this.label = label;
   this.action = action;
   this.divContentId = divContentId;
   return this;
}

// Modifie le label
HtmlTab.prototype.setLabel = function (label)
{
   this.label = label;  
}
// ----------------------------------------------------------------------------
/**
 * Fonction utilisÃ©e pour le nouveau style flora2.
 * Elle gÃ©nÃ¨re des onglets dans un tableau lui mÃªme placÃ© dans
 * la section identifiÃ©e par div. Un onglet est constituÃ© de 3 colonnes.
 * || bord G || lien || bord D + || un espace pour sÃ©parer 2 onglets ||
 * 
 * div : section contenant les onglets
 * selectedPrefixStyle : Prefix de tous les styles utilisÃ©s pour afficher
 *                       un onglet selectionnÃ©.(bord gauche,bord droit, lien..)
 * notSelectePrefixStyle : idem selectedPrefixStyle pour les onglets non selectionnÃ©s.
 * tabStyle : Style du tableau contenant les onglets
 * spaceStyle : Style utilisÃ© pour marquer un espace en chaque onglet
 **/
function HtmlTabView2(div, selectedPrefixStyle, notSelectePrefixStyle, tabStyle,spaceStyle,clientWidth)
{
   this.div = div;
   this.items = new Array();
   this.selectedIndex = 0;
   if(selectedPrefixStyle != undefined) this.linkSelectedStyle = selectedPrefixStyle+"Link";
   if(tabStyle != undefined) this.tabStyle=tabStyle;
   if(spaceStyle != undefined) this.spaceStyle=spaceStyle;
   if(selectedPrefixStyle != undefined) 
   {
      this.leftSelectedStyle=selectedPrefixStyle+"Left";
      this.rightSelectedstyle=selectedPrefixStyle+"Right";
      this.centerSelectedStyle=selectedPrefixStyle+"Center";
   }
   if(notSelectePrefixStyle != undefined) 
   {
      this.leftNotSelectedStyle=notSelectePrefixStyle+"Left";
      this.rightNotSelectedStyle=notSelectePrefixStyle+"Right";
      this.centerNotSelectedStyle=notSelectePrefixStyle+"Center";
   }
   allHtmlTabViews[div.id] = this;
   
   //taille de la fenÃªtre en cours
   this.clientWidth = clientWidth;
   
   return this;
}

// =========== GETTER ==================

HtmlTabView2.prototype.getLinkSelectedStyle = function () 
{
   if(this.linkSelectedStyle != undefined)
   {
      return " class='"+this.linkSelectedStyle+"' ";
   }
   return "";
}

HtmlTabView2.prototype.getLeftSelectedStyle = function () 
{
   if(this.leftSelectedStyle != undefined)
   {
      return " class='"+this.leftSelectedStyle+"' ";
   }
   return "";
}

HtmlTabView2.prototype.getRightSelectedStyle = function () 
{
   if(this.rightSelectedstyle != undefined)
   {
      return " class='"+this.rightSelectedstyle+"' ";
   }
   return "";
}

HtmlTabView2.prototype.getCenterSelectedStyle = function () 
{
   if(this.centerSelectedStyle != undefined)
   {
      return " class='"+this.centerSelectedStyle+"' ";
   }
   return "";
}

HtmlTabView2.prototype.getLeftNotSelectedStyle = function () 
{
   if(this.leftNotSelectedStyle != undefined)
   {
      return " class='"+this.leftNotSelectedStyle+"' ";
   }
   return "";
}

HtmlTabView2.prototype.getRightNotSelectedStyle = function () 
{
   if(this.rightNotSelectedStyle != undefined)
   {
      return " class='"+this.rightNotSelectedStyle+"' ";
   }
   return "";
}

HtmlTabView2.prototype.getCenterNotSelectedStyle = function () 
{
   if(this.centerNotSelectedStyle != undefined)
   {
      return " class='"+this.centerNotSelectedStyle+"' ";
   }
   return "";
}

HtmlTabView2.prototype.getTabStyle = function () 
{
   if(this.tabStyle != undefined)
   {
      return " class='"+this.tabStyle+"' ";
   }
   return "";
}
HtmlTabView2.prototype.getTabStyleMulti = function () 
{
   if(this.tabStyle != undefined)
   {
      return " class='"+this.tabStyle+"Multi' ";
   }
   return "";
}


// Ajoute un onglet
// action : fonction JS appelÃ©e si non null lorsqu'on clique sur l'onglet
//          si l'action est null, l'action par dÃ©faut est d'afficher
//          l'onglet et masquer les autres           
// divContentId : id de la div contenant le corps de l'onglet
//                pour traiter l'action automatique
HtmlTabView2.prototype.add = function (label, action, divContentId)
{
   if ( ! action && ! divContentId )
   {
      alert("HtmlTab : if 'action' is not defined, 'divContentId' is needed to handle default action.");
      return;
   }
   var tab = new HtmlTab(label, action, divContentId);
   this.items[this.items.length] = tab;  
}
HtmlTabView2.prototype.setClientWidth = function (clientWidth)
{
this.clientWidth=clientWidth;
}

// Renvoie un onglet
HtmlTabView2.prototype.getHtmlTab = function (tabIndex)
{
   return this.items[tabIndex];  
}

// GÃ©nÃ¨re le code HTML dans la div
HtmlTabView2.prototype.refresh = function ()
{
   var ret = "";
   var style="";
   var nbTable=0;
   var nbTabPerLine=7; //nombre d'onglet par ligne
   var oneTabSize=120; //en px
   
   if(this.clientWidth!=null) 
   {
   var width=this.clientWidth;
   if(width<oneTabSize) width=oneTabSize+1;
   nbTabPerLine=Math.round(parseInt(width) / oneTabSize);
   }
   var nbLine=(Math.round(this.items.length / nbTabPerLine));
   if(nbLine==0) nbLine=1;
   
   
  // alert("nbLine : "+nbLine);
   //alert("nbTabPerLine : "+nbTabPerLine);

   if(this.clientWidth!=null)  
   {
   if(nbLine==1) width=nbTabPerLine*this.items.length;
   var px="";
   if(document.getElementById) px="px";
   var style="style=\"width:"+width+px+";\"";
   var styleTop="style=\"margin-top:-3px;width:"+width+px+";\"";
   var className=this.getTabStyle();
   }
   
   
   for(var i=0; i<nbLine; i++)
   {
   var debutTr=0;
   if(i>0) debutTr=nbTabPerLine*i;
   var endTr=this.items.length;
   if(i+1<nbLine ) endTr=nbTabPerLine+nbTabPerLine*i;
   
   //alert("debutTr : "+debutTr);
   //alert("finTr : "+endTr);
   
   if(this.clientWidth!=null && i>0)  this.div.style.height=45+17*(i-1)+"px";
   
   if(i>0) 
   {
   style=styleTop;
   className=this.getTabStyleMulti();
   }
   ret += "<table cellspacing='0' border='0' cellpadding='0' " + className +" "+ style +" >";
   ret += "<tr>";
   ret += this.getTr(debutTr,endTr);
   ret += "</tr></table>";
   }
   this.div.innerHTML = ret;
   if(this.items.length==0) this.div.style.display="none";
}

HtmlTabView2.prototype.getTr = function (i,end)
{
var ret="";

   for(var j=i; j<end; j++)
   {
      var isSelected = (this.selectedIndex == j);
      ret += this.refreshLeftBorder(isSelected);
      ret += this.refreshLink(isSelected,j);
      ret += this.refreshRightBorder(isSelected);
       if(j<end)
      {
         ret+=this.refreshSpace();
      }
   }
   return ret;
}


HtmlTabView2.prototype.refreshLink = function (isSelected,index)
{
   var ret = "";
   if(isSelected) 
   {
      ret += "<td nowrap='nowrap' " + this.getCenterSelectedStyle() + " >";
      ret += "<a href=\"javascript:HtmlTabView_setCurrentTab('" + this.div.id + "'," + index + ");";
      ret += "\" "+this.getLinkSelectedStyle() +  ">&nbsp;" + this.items[index].label + "&nbsp;</a>";
      ret += "</td>";
   }
   else
   {
      ret += "<td nowrap='nowrap' " + this.getCenterNotSelectedStyle() + " >";
      ret += "<a href=\"javascript:HtmlTabView_setCurrentTab('" + this.div.id + "'," + index + ");\">";
      //ret += this.items[i].action + "\" ";
      ret += "&nbsp;" + this.items[index].label + "&nbsp;</a>";
      ret += "</td>";
   }
   return ret;
}

// Le nouveau style flora nÃ©cessite un style pour l'ouverture des bordures
HtmlTabView2.prototype.refreshLeftBorder = function (isSelected)
{
   var ret = "";
   if(isSelected) 
   {
      ret += "<td " + this.getLeftSelectedStyle() + " > &nbsp; </td>";
   }
   else 
   {
      ret += "<td " + this.getLeftNotSelectedStyle() + " > &nbsp; </td>";
   }
   return ret;   
}

// Le nouveau style flora nÃ©cessite un style pour la fermeture des bordures
HtmlTabView2.prototype.refreshRightBorder = function (isSelected)
{
   var ret = "";
   if(isSelected) 
   {
         ret += "<td " + this.getRightSelectedStyle() + " > &nbsp; </td>";
   }
   else 
   {
      ret += "<td " + this.getRightNotSelectedStyle() + " > &nbsp; </td>";
   }
   return ret;
}

// Le nouveau style flora nÃ©cessite un espace entre deux onglets
HtmlTabView2.prototype.refreshSpace = function ()
{
   var ret = "";
   if(this.spaceStyle != undefined)
   {
      ret += "<td class='" +this.spaceStyle+"' > &nbsp; </td>";
   }
  
  return ret;
}

// -----------------------------------------------------------------------------
//
function StringUtil_trim(str)
{
   return StringUtil_trimright(StringUtil_trimleft(str));
}
function StringUtil_trimleft(str)
{
   if ( str == null ) return;
   return str.replace( /^\s+/g, '');
} 
function StringUtil_trimright(str)
{
   if ( str == null ) return;
   return str.replace( /\s+$/g, '');
}

function StringUtil_toUpperCase(str)
{
   if ( str == null ) return;
   return str.toUpperCase();
}

String.prototype.trimleft = function ()
{
   return StringUtil_trimleft(this);
}
String.prototype.trimright = function ()
{
   return StringUtil_trimright(this);
}
String.prototype.trim = function ()
{
   return StringUtil_trim(this);
}
// Remplace dans la chaÃ®ne plusieurs occurrences Ã  la suite de sep par un seul
// et renvoie la chaÃ®ne transformÃ©e
String.prototype.compressSepar = function(sep)
{
   var len = this.length;
   var ret = "";
   for (var i=0; i<len; i++)
   {
      var c = this.charAt(i);
      if ( c != sep ) ret += c;
   }
   return ret;
} 
// Renvoie la chaine de caractÃ¨re passÃ©e en paramÃ¨tre, 
// en ayant dÃ©codÃ© les caractÃ¨res octal \**** 
function decodeOctal(s)
{
   if ( s == null ) return null;
   var ret = "";
   var code = "";
   
   var len = s.length;
   for (var i=0; i<len; i++)
   {
      var c = s.charAt(i);
      switch ( c )
      {
         case '0':
         case '1':
         case '2':
         case '3':
         case '4':
         case '5':
         case '6':
         case '7':
            if ( code.length > 0 )
               code += c;
            else
               ret += c;
            break;
         case '\\':
         default:
         {
            // Il y avait quelque chose en cours, le dÃ©coder d'abord
            switch ( code.length )
            {
               case 0 : // rien encore dans code
                  if ( c == '\\')
                  {
                     code = c; // dÃ©bute un nouveau
                  }
                  else
                  {
                     ret += c;
                  }
                  break;
               case 1 : // seulement \, on l'ajoute
                  ret += "\\";
                  if ( c != '\\' )
                  {
                     ret += c;
                     code = "";   
                  }
                  break;
               default : // \x au moins, Ã  dÃ©coder
                  // DÃ©codage et ajout du caractÃ¨re
                  var toDecode = code.substring(1); // ne garde pas \
                  var icode = parseInt(toDecode, 8); 
                  ret += String.fromCharCode(icode);

                  if ( c == '\\')
                  {
                     // dÃ©bute un nouveau
                     code = c;
                  }
                  else
                  {
                     ret += c;
                     code = "";
                  }
            }
         }
      }
   } // for
   
   // Ne pas oublier le dernier code !
   if ( code != null && code.length > 1) 
   {
      if ( code.length == 1 )
         ret += '\\';
      else
      {
         var toDecode = code.substring(1); // ne garde pas \
         var icode = parseInt(toDecode, 8); 
         ret += String.fromCharCode(icode);
      }
   } 
   return ret;   
}

// tdn 24/06/2005 Attention : les noms de fonctions 
// normalizeFieldName et unNormalizeFieldName prÃªtaient Ã  confusion.
// Normaliser doit signifier 'Nom au norme XML'. 
// J'ajoute Tools_decorateFieldName pour lever l'ambiguitÃ©
function Tools_decorateFieldName(name)
{
   return unNormalizeFieldName(name);
}

// Si le nom commence par un chiffre, prefixe le nom avec le caractÃ¨re underscore '_'
function normalizeFieldName(name)
{
  if ( ! isNaN(name.charAt(0)) )
     name = "_" + name;
  return name;
}

// Si le nom commence par '_', saute le premier caractÃ¨re
function unNormalizeFieldName(name)
{
  if ( name.charAt(0) == '_' )
     name = name.substring(1);
  return name;
}

//
function appendDebug(txt)
{
   printDebug(txt, true);
}

//
function printDebug(txt, append)
{
   // Ouvre la fenÃªtre
   var win = window.open("", "win_debug",
  "toolbar=0,location=0,directories=0,menuBar=0,scrollbars=yes,resizable=yes" +
  ",width=" + 750 + ",height=" + 800 +
  ",top=" + 50 + ",left=" + 50);
   win.focus();
   
   if ( append == true ) if (win.document) if ( win.document.forms[0])
      txt = win.document.forms[0].elements["text"].value + '\n' + txt;

   // Passage suivant
   if (win.document) if ( win.document.forms[0])
   {
      win.document.forms[0].elements["text"].value = txt;
      return;  
   }
   // Premier passage
   win.document.write("<html><body><form name='frm'>");
   win.document.write("<input type='button' onclick='window.close()' value='Fermer' /><br />");
   win.document.write("<textarea name='text' cols='80' rows='40'>");
   win.document.writeln(txt);
   win.document.writeln("</textarea>");
   win.document.write("</form></body></html>");
   win.document.close();
   
}

// -----------------------------------------------------------------------------
// Objet RecordId
// A partir d'un recordId, permet de diposer des ces composantes
// Format d'un recordId :
// recordId = source:table:internalId|documentId
// -----------------------------------------------------------------------------
function RecordId(recordId)
{
   this.recordId = recordId;
   this.source = "default";
   this.table = "";
   this.internalId = "";
   this.documentId = "";
   
   if (recordId  &&  recordId != "")
      this.init();
      
   return this;
}

// Initialise les Ã©lÃ©ments de l'objet
RecordId.prototype.init = function ()
{
   var res = this.splitId();
   this.source = res[0];
   this.table = res[1];
   this.internalId = res[2];
   this.documentId = res[3];
}      

// Renvoie true si le recordid est valide, false sinon
RecordId.prototype.isValid = function ()
{
   if (   this.table == undefined      || this.table.length == 0
       || this.internalId == undefined || this.internalId.length == 0 )
     return false;
     
   return true;  
}

// Renvoie le recordId formatÃ©
RecordId.prototype.getRecordId = function ()
{
   if (this.table != ""  &&  this.internalId != "")
      this.recordId = this.source + ':' + this.table  + ':' + this.internalId;
   return this.recordId;
}
// Renvoie la source
RecordId.prototype.getSource = function ()
{
   return this.source;
}
// Positionne la source
RecordId.prototype.setSource = function (source)
{
   this.source = source;
}
// Renvoie la table
RecordId.prototype.getTable = function ()
{
   return this.table;
}
// Positionne la table
RecordId.prototype.setTable = function (table)
{
   this.table = table;
}
// Renvoie l'internalId / le recordKey
RecordId.prototype.getInternalId = function ()
{
   return this.internalId;
}
// Positionne l'internalId / le recordKey
RecordId.prototype.setInternalId = function (internalId)
{
   this.internalId = internalId;
}
// Renvoie le documentId
RecordId.prototype.getDocumentId = function ()
{
   return this.documentId;
}
    
// Retourne les composantes clÃ© de l'identifiant
// ret[0] ==> source
// ret[1] ==> table
// ret[2] ==> internalId <=> recordKey
// ret[3] ==> documentId : vaut null si pas de document attachÃ©
RecordId.prototype.splitId = function ()
{
   var ret = new Array(4);
     
   // DÃ©coupe la valeur suivant '|' et ':' en partant de la fin
   // documentId Ã©ventuellement
   var recId = this.recordId;
   var pos = recId.lastIndexOf('|');
   if ( pos > - 1 )
   {
      ret[3]= recId.substring(pos+1);
      recId = recId.substring(0, pos);
   }
   // internalId <=> recordKey 
   pos = recId.lastIndexOf(':');
   if ( pos > -1)
   {
      ret[2] = recId.substring(pos+1);
      recId = recId.substring(0, pos);
   }
   // sourceName:TableName
   pos = recId.lastIndexOf(':');
   if ( pos > -1)
   {
      ret[1] = recId.substring(pos+1);
      ret[0] = recId.substring(0,pos); 
   }  
   
   return ret;
}


//-------------------------------------------------------
// Clone un tableau
function arrayClone (array)
{
   if ( ! array ) return null;
   var ret = new Array();
   for (var i in array)
   {
      ret[i] = array[i];
   }
   return ret;
}

// Tente de positionner le focus sur l'Ã©lÃ©ment passÃ© en paramÃ¨tre
function setFocus(element)
{
   try
   {
     element.focus();
   } 
   catch (ex)
   {
     // On ne fait rien
   };
}

// si la chaine str est > Ã  size, elle est coupÃ©e Ã  size-end.length caractÃ¨res
// et est renvoyÃ©e avec end en suffixe.
function subString(str,size,end){
//alert("str : "+str+"\n size : "+size+"\n end :"+end);
	   if(str.length>size) {
		   str=str.substring(0,size-end.length);
		   str+=end;
	   }
   return str;
}


// Cas 141 Donne le nombre d'éléments contenu dans un tableau associatif
// .length n'indiquant pas la bonne longueur is une des clés étaient une 
// chaîne numérique !
function getHashLength(aHash)
{
   var ret = 0;
   for (var key in aHash)
   {
      if(key != "map") ret++;
   }
   return ret;   
}


// Cas 141 : Objet Hash pour gérer correctement la longueur, à utiliser 
// à la place du tableau associatif
function Hash()
{
   this.length = 0;
   this.items = new Array();
   for (var i = 0; i < arguments.length; i += 2) {
      if (typeof(arguments[i + 1]) != 'undefined') {
         this.items[arguments[i]] = arguments[i + 1];
         this.length++;
      }
   }
   
   this.removeItem = function(in_key)
   {
      var tmp_value;
      if (typeof(this.items[in_key]) != 'undefined') {
         this.length--;
         var tmp_value = this.items[in_key];
         delete this.items[in_key];
      }
      
      return tmp_value;
   }

   this.getItem = function(in_key) {
      return this.items[in_key];
   }

   this.putItem = function(in_key, in_value)
   {
      if (typeof(in_value) != 'undefined') {
         if (typeof(this.items[in_key]) == 'undefined') {
            this.length++;
         }

         this.items[in_key] = in_value;
      }
      
      return in_value;
   }

   this.containsKey = function(in_key)
   {
      return typeof(this.items[in_key]) != 'undefined';
   }
}
      
