
//////////////////////////
// Start the Real stuff //
//////////////////////////


// XmlHttp factory
function XmlHttp() {}

XmlHttp.create = function () {
	try {
		if (window.XMLHttpRequest) {
			var req = new XMLHttpRequest();
			
			// some versions of Moz do not support the readyState property
			// and the onreadystate event so we patch it!
			if (req.readyState == null) {
				req.readyState = 1;
				req.addEventListener("load", function () {
					req.readyState = 4;
					if (typeof req.onreadystatechange == "function")
						req.onreadystatechange();
				}, false);
			}
			
			return req;
		}
		if (window.ActiveXObject) {
			return new ActiveXObject(getXmlHttpPrefix() + ".XmlHttp");
		}
	}
	catch (ex) {}
	// fell through
	throw new Error("Your browser does not support XmlHttp objects");
};

// XmlDocument factory
function XmlDocument() {}

XmlDocument.create = function () {
	try {
		// DOM2
		if (document.implementation && document.implementation.createDocument) {
			var doc = document.implementation.createDocument("", "", null);
			
			// some versions of Moz do not support the readyState property
			// and the onreadystate event so we patch it!
			if (doc.readyState == null) {
				doc.readyState = 1;
				doc.addEventListener("load", function () {
					doc.readyState = 4;
					if (typeof doc.onreadystatechange == "function")
						doc.onreadystatechange();
				}, false);
			}
			
			return doc;
		}
		if (window.ActiveXObject)
			return new ActiveXObject(getDomDocumentPrefix() + ".DomDocument");
	}
	catch (ex) {}
	throw new Error("Your browser does not support XmlDocument objects");
};

// Create the loadXML method and xml getter for Mozilla
if (window.DOMParser &&
	window.XMLSerializer &&
	window.Node && Node.prototype && Node.prototype.__defineGetter__) {

	// XMLDocument did not extend the Document interface in some versions
	// of Mozilla. Extend both!
	//XMLDocument.prototype.loadXML = 
	Document.prototype.loadXML = function (s) {
		
		// parse the string to a new doc	
		var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
		
		// remove all initial children
		while (this.hasChildNodes())
			this.removeChild(this.lastChild);
			
		// insert and import nodes
		for (var i = 0; i < doc2.childNodes.length; i++) {
			this.appendChild(this.importNode(doc2.childNodes[i], true));
		}
	};
	
	
	/*
	 * xml getter
	 *
	 * This serializes the DOM tree to an XML String
	 *
	 * Usage: var sXml = oNode.xml
	 *
	 */
	// XMLDocument did not extend the Document interface in some versions
	// of Mozilla. Extend both!
	/*
	XMLDocument.prototype.__defineGetter__("xml", function () {
		return (new XMLSerializer()).serializeToString(this);
	});
	*/
	Document.prototype.__defineGetter__("xml", function () {
		return (new XMLSerializer()).serializeToString(this);
	});
}

// used to find the Automation server name
function getDomDocumentPrefix() {
	if (getDomDocumentPrefix.prefix)
		return getDomDocumentPrefix.prefix;
	
	var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
	var o;
	for (var i = 0; i < prefixes.length; i++) {
		try {
			// try to create the objects
			o = new ActiveXObject(prefixes[i] + ".DomDocument");
			return getDomDocumentPrefix.prefix = prefixes[i];
		}
		catch (ex) {};
	}
	
	throw new Error("Could not find an installed XML parser");
}

function getXmlHttpPrefix() {
	if (getXmlHttpPrefix.prefix)
		return getXmlHttpPrefix.prefix;
	
	var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
	var o;
	for (var i = 0; i < prefixes.length; i++) {
		try {
			// try to create the objects
			o = new ActiveXObject(prefixes[i] + ".XmlHttp");
			return getXmlHttpPrefix.prefix = prefixes[i];
		}
		catch (ex) {};
	}
	
	throw new Error("Could not find an installed XML parser");
}
var XML_ELEMENT_NODE         = 1;
var XML_TEXT_NODE            = 3;
var XML_CDATA_SECTION_NODE   = 4;
/*
typedef enum {
    XML_ATTRIBUTE_NODE=		2,
    XML_ENTITY_REF_NODE=	5,
    XML_ENTITY_NODE=		6,
    XML_PI_NODE=		7,
    XML_COMMENT_NODE=		8,
    XML_DOCUMENT_NODE=		9,
    XML_DOCUMENT_TYPE_NODE=	10,
    XML_DOCUMENT_FRAG_NODE=	11,
    XML_NOTATION_NODE=		12,
    XML_HTML_DOCUMENT_NODE=	13,
    XML_DTD_NODE=		14,
    XML_ELEMENT_DECL=		15,
    XML_ATTRIBUTE_DECL=		16,
    XML_ENTITY_DECL=		17,
    XML_NAMESPACE_DECL=		18,
    XML_XINCLUDE_START=		19,
    XML_XINCLUDE_END=		20
} xmlElementType;
*/
/**
 * Renvoie le premier node text ou cdata de l'élément passé en paramètre
 *
 * @return null si aucun enfant "text" ou "cdata" n'existe.
 */
function XMLUtil_getElementText(elem)
{
   if ( elem.hasChildNodes() )
   {
      var nodeList = elem.childNodes;
      for (var i=0; i< nodeList.length; i++ )
      {
         var node = nodeList[i];
         if ( node.nodeType == XML_TEXT_NODE )
         {
            return node;
         }
         if ( node.nodeType == XML_CDATA_SECTION_NODE )
         {
            return node;
         }
         // On a changé d'élément, il n'y a pas de node Text ou CData
         if ( node.nodeType == XML_ELEMENT_NODE )
         {
            return null;
         }
      }
   }
   return null;
}
/**
 * Positionne le contenu texte de l'élément.
 * @return true si ok
 */
function XMLUtil_setElementContent(elem, value)
{
   var ret = false;
   var node = XMLUtil_getElementText(elem);
   var text = null;

   if ( node != null )
   {
      if ( (node.nodeType == XML_TEXT_NODE) ||
           (node.nodeType == XML_CDATA_SECTION_NODE) )
         text = node;
   }

   if ( text != null )
   {
      text.nodeValue = value;
      ret = true;
   }
   else
   {
      // Le node text n'existe pas, il faut le créer
      var doc = elem.ownerDocument;
      text = doc.createTextNode (value);
      elem.appendChild (text);
      ret = true;
   }
   return ret;
}
/**
 * Cherche tous les éléments Text ou CDATA de l'élément et les concatène.
 *
 * @return vide si l'élément n'a aucun élement Text
 */
function XMLUtil_getElementContent(elem)
{
   if ( elem.hasChildNodes() )
   {
      var buf = "";
      for (var i=0; i< elem.childNodes.length; i++ )
      {
         var node = elem.childNodes[i];
         if ( ( node.nodeType == XML_TEXT_NODE ) ||
              ( node.nodeType == XML_CDATA_SECTION_NODE ) )
         {
            buf += node.nodeValue;
         }
         // On a changé d'élément, il n'y a plus de node Text ou CData
         else if ( node.nodeType == XML_ELEMENT_NODE )
         {
            break;
         }
      }
      return StringUtil_trim(buf);
   }
   return "";
}
/**
 * Recherche le prochain élément de même niveau, null si non trouvé
 */
function XMLUtil_getNextElement(elem)
{
   var found = false;
   while ( ! found )
   {
      var nextNode = elem.nextSibling();
      if ( nextNode == null ) break;
      if ( nextNode.nodeType == XML_ELEMENT_NODE )
         return nextNode;
   }
   return null;
}
/**
 * Renvoie les éléments enfants directs, null si aucun enfants
 */
function XMLUtil_getChildElements (elem)
{
   if ( elem.hasChildNodes() )
   {
      var ret = new Array();
      for (var i=0; i<elem.childNodes.length; i++)
      {
         var child = elem.childNodes[i];
         if ( (child.nodeType == XML_ELEMENT_NODE))
         {
            ret[ret.length] = child;
         }
      }
      return ret;
   }
   return null;
}
//
// Sérialise simplement un élément
//
function XMLUtil_serialize(elem)
{
   var ret = "<?xml version='1.0' encoding='UTF-8'?>";
   ret += _XMLUtil_serialize(elem);
   return ret;
}
function _XMLUtil_serialize(elem)
{
   var ret= "<" + elem.tagName;
   var value = elem.getAttribute("value");
   // Encodage des entités
   value = XMLUtil_replaceEntities(value);
   var childValue = "";
   if ( value != null && value != "")
   {
      childValue += value;
      //elem.removeAttribute("value");
   }
   ret += XMLUtil_serializeAtributes(elem);
   
   if (elem.hasChildNodes())
   {
      for(var i=0; i<elem.childNodes.length; i++)
      {
         var child = elem.childNodes[i];
         if ( child.nodeType == XML_ELEMENT_NODE )
         {
            childValue += _XMLUtil_serialize(child);
         }
         else if ( (child.nodeType == XML_TEXT_NODE) ||
            (child.nodeType == XML_CDATA_SECTION_NODE) )
         {
            //childValue += "[" + child.nodeType +"]" + child.nodeValue;
            childValue += child.nodeValue;
         }
      }
      if ( childValue.length > 0 )
         ret += ">" + childValue + "</" + elem.tagName + ">";
      else
         ret += " />";
   }
   else
   {
      if ( childValue.length > 0 )
         ret += ">" + childValue + "</" + elem.tagName + ">";
      else
         ret += " />";
   }
   return ret;
}
function XMLUtil_serializeAtributes(elem)
{
   var attrs = elem.attributes;
   var ret = "";
   if ( attrs )
   {
      for (var i=0; i<attrs.length; i++)
      {
         var val = null;
         try { val=elem.getAttribute(attrs[i].name);} catch(ex){}
         if ( val )
            ret += " " + attrs[i].name + "=\"" + XMLUtil_replaceEntities(val) + "\"";
      }
   }
   return ret;
}

//
// Serialise un élement avec uniquement ses attributs
//
function XMLUtil_serializeAttributesOnly(elem)
{
   var ret = "<?xml version='1.0' encoding='UTF-8'?>";
   ret += _XMLUtil_serializeAttributesOnly(elem);
   return ret;
}

function _XMLUtil_serializeAttributesOnly(elem)
{
   var ret= "<" + elem.tagName;
   var childValue = "";   
   ret += XMLUtil_serializeAtributes(elem);
   
   if (elem.hasChildNodes())
   {
      for(var i=0; i<elem.childNodes.length; i++)
      {
         var child = elem.childNodes[i];
         if ( child.nodeType == XML_ELEMENT_NODE )
         {
            childValue += _XMLUtil_serializeAttributesOnly(child);
         }
      }   
      if ( childValue.length > 0 )
         ret += ">" + childValue + "</" + elem.tagName + ">";
      else
         ret += " />";
   }
   else
   {
      if ( childValue.length > 0 )
         ret += ">" + childValue + "</" + elem.tagName + ">";
      else
         ret += " />";
   }
   return ret;
}


// 
// Sérialise un élément Record. Seul l'attribut id est conservé. Le contenu de
// l'attribut "value" est mis dans le corps de l'élément.
// tdn 05/04/2007
function XMLUtil_serializeRecord(elem)
{
   var ret = "<?xml version='1.0' encoding='UTF-8'?>";
   ret += _XMLUtil_serializeRecord(elem);
   return ret;
}
function _XMLUtil_serializeRecord(elem)
{
   var ret= "<" + elem.tagName;
   var value = elem.getAttribute("value");
   // Encodage des entités
   value = XMLUtil_replaceEntities(value);
   var childValue = "";
   if ( value != null && value != "")
   {
      childValue += value;
   }
   // Conserve uniquement id
   var idVal = elem.getAttribute("id");
   if ( idVal )
   {
      ret += " id=\"" + XMLUtil_replaceEntities(idVal) + "\"";
   }
   
   if (elem.hasChildNodes())
   {
      for(var i=0; i<elem.childNodes.length; i++)
      {
         var child = elem.childNodes[i];
         if ( child.nodeType == XML_ELEMENT_NODE )
         {
            childValue += _XMLUtil_serializeRecord(child);
         }
         else if ( (child.nodeType == XML_TEXT_NODE) ||
            (child.nodeType == XML_CDATA_SECTION_NODE) )
         {
            childValue += child.nodeValue;
         }
      }
      if ( childValue.length > 0 )
         ret += ">" + childValue + "</" + elem.tagName + ">";
      else
         ret += " />";
   }
   else
   {
      if ( childValue.length > 0 )
         ret += ">" + childValue + "</" + elem.tagName + ">";
      else
         ret += " />";
   }
   return ret;
}


// Renvoie un objet DOM si le flux XML est ok, null sinon
function XMLUtil_MakeDocument(xmlContent)
{
   var xmlDoc = XmlDocument.create();
   xmlDoc.loadXML(xmlContent);
   var docElem = xmlDoc.documentElement;
   if ( ! docElem )
      return null;
   return xmlDoc;
}

// Charge ert renvoie un document XML depuis le serveur
function XMLUtil_LoadXML (docURL, encoding, data)
{
   var response = XMLUtil_GetContent(docURL, encoding, data);
   //XMLUtil_Debug(response);
   var xmlDoc = XMLUtil_MakeDocument(response);
   if ( ! xmlDoc )
   {
      alert("XMLUtil_LoadXML : Document XML invalide :\n" + response);
      return null;
   }
   //appendDebug("XML = " + response);
   return xmlDoc;
}
// Renvoie juste le texte tel_quel 
//modif abe 13/03/06 : prise en compte de la méthoe POST
function XMLUtil_GetContent(docURL, encoding, data)
{
   if ( (encoding == null) ||(encoding == '') )
      encoding = "UTF-8";
   var xmlHttp = XmlHttp.create();
   var async = false;
   var url = docURL;
   var method="GET";
   if(data) method="POST";
   // tdn 08/07/2005 ajoute automatiquement un stamp pour éviter le cache de jouerr
   var stamp = new Date().getTime();
   if ( url.lastIndexOf("?") < 0)
      url += "?";
   else
      url += "&";
   url += "stamp=" + stamp;
   xmlHttp.open(method, url, async);
   xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
   xmlHttp.setRequestHeader("charset", encoding);
   xmlHttp.setRequestHeader("RequestType", "XmlHttpStream");
   if (data) 
   xmlHttp.send(data);
   else
   xmlHttp.send("");
   return xmlHttp.responseText;
}

// Ecrit dans une nouvelle fenêtre le contenu dans un
function XMLUtil_Debug(str)
{
   var win = open("", "_blank", "menubar=no, width=400, height=400");
   win.document.write(str);
   win.document.close();
}

/**
 * Remplace les entités par leur code :    
 * & => &amp;
 * > => &gt;
 * < => &lt;
 * " => &#22;
 * " => &#2;
 * \r => &#0D;
 * \n => &#0A;
 */
function XMLUtil_replaceEntities(s)
{
   var ret = "";
   if ( s == null )
      return ret;
   
   var i = 0;
   var len = s.length; 
   while ( i < len )
   {
      var c = s.charAt(i);
      switch (c)
      {
         case '&':
            ret += "&amp;";
         break;
         case '>':
            ret += "&gt;";
            break;
         case '<':
            ret += "&lt;";
            break;
         case '\'':
            ret += "&#x27;";
            break;
         case '"':
            ret += "&#x22;";
            break;
         case '\r':
            ret += "&#x0D;";
            break;
         case '\n':
            ret += "&#x0A;";
            break;
         default :
            ret += c;
            break;
      }
      i++;
   }
   return ret;
}

/**
 * A partir d'un nom de champ et de sa valeur, renvoie une chaine de caractères
 * au format xml, en ayant remplacé les entités par leurs codes pour la valeur 
 * du champ :
 *    <NOM_CHAMP>valeur_avec_les_entitées_codées</NOM_CHAMP>
 * ou
 *    <NOM_CHAMP /> 
 */
function XMLUtil_getXmlFieldCodedEntities(fieldName, fieldValue)
{
   var ret = "";
   if ( fieldName == null || fieldName.length == 0 )
      return ret;
   
   if ( fieldValue != null )
   {
      fieldValue = fieldValue.toString(); 
      if ( fieldValue.length > 0 )
      {
         ret  = '<' + fieldName + '>';
         ret += XMLUtil_replaceEntities(fieldValue);
         ret += '</' + fieldName + '>';
      }
      else
      {
         ret  = '<' + fieldName + '/>';
      }
   }   
   return ret;
}   

// Lit une notice XML à partir de son recordId et renvoie le flux texte
function XMLUtil_ReadRecord(recordId)
{
   var action = sysGetAppBaseUrl() + "servlet/RecordRead?record=" + recordId;
   var xmlContent = XMLUtil_GetContent(action);
   return xmlContent;
}

// Lit une notice XML à partir de son recordId et renvoie le document DOM
function XMLUtil_LoadRecord(recordId)
{
   var action = sysGetAppBaseUrl() + "servlet/RecordRead?record=" + recordId;
   var xmlDoc = XMLUtil_LoadXML(action);
   return xmlDoc;
}


// Un item ayant les attributs 'code' et 'value'
function ListItem(code, value)
{
   this.code = code;
   this.value = value;
   return this;
}
// Renvoie un tableau de ListItem à partir d'un flux XML au format list
function XMLUtil_MakeList(xmlContent)
{
   var xmlDoc = XMLUtil_MakeDocument(xmlContent);
   if ( ! xmlDoc )
   {
      alert("XMLUtil_MakeList : Document XML invalide :\n" + xmlContent);
      return null;
   }
   var ret = new Array();
   var items = xmlDoc.documentElement.getElementsByTagName("item");
   if ( items && items.length > 0 )
   {
      for (var i=0; i<items.length; i++)
      {
         var code = items[i].getAttribute("code");
         var value = items[i].getAttribute("value");
         var item = new ListItem(code, value);
         ret[ret.length] = item;
      }
   }
   return ret;
}

// Renvoie le message d'erreur si le document est de type <ERROR>..</ERROR>
// Le message d'erreur peut être vide.
// Renvoie null si le tag ERROR n'est pas détecté à la racine
function XMLUtil_IsError(xmlDoc)
{
   var rootTagName = "ERROR";
   return  _XMLUtil_IsErrorOrInfo(rootTagName, xmlDoc);
}

// Renvoie le message d'information si le document est de type <INFO>..</INFO>
// Le message d'erreur peut être vide.
// Renvoie null si le tag INFO n'est pas détecté à la racine
function XMLUtil_IsInfo(xmlDoc)
{
   var rootTagName = "INFO";
   return  _XMLUtil_IsErrorOrInfo(rootTagName, xmlDoc);
}

// Teste si un message est de type :
//   - <ERROR>...</ERROR>
// ou
//   - <INFO>...</INFO>
// Renvoie le contenu du message si le document est du type souhaité. 
// Le message peut être vide.
// Renvoie null si le tag ERROR ou INFO n'est pas détecté à la racine
function _XMLUtil_IsErrorOrInfo(rootTagName, xmlDoc)
{
   var ret = null;
   if ( xmlDoc != null )
   {
      if ( xmlDoc.documentElement.tagName == rootTagName )
      {
         var msgTag = xmlDoc.getElementsByTagName("MSG");   
         if ( (msgTag != null) && (msgTag.length > 0) )
         {
            ret = XMLUtil_getElementContent(msgTag[0]);
         }
         else
         {
            var rootElem = xmlDoc.documentElement;
            ret = XMLUtil_getElementContent(rootElem);
         }
         if ( ret == null ) ret = "";
         
      }
   }   
   return ret;
}

/**
 * @return le type de l'erreur  ou null si xmlDoc
 * n'est pas un document décrivant une erreur
 */
function XMLUtil_ErrorType(xmlDoc)
{
   var rootTagName = "ERROR";
   return _XMLUtil_ErrorOrInfoType(rootTagName, xmlDoc)
}

/**
 * @return le type de l'information ou null si xmlDoc
 * n'est pas un document décrivant une erreur
 */
function XMLUtil_InfoType(xmlDoc)
{
   var rootTagName = "INFO";
   return _XMLUtil_ErrorOrInfoType(rootTagName, xmlDoc)
}

// Teste si un message est de type :
//   - <ERROR>...</ERROR>
// ou
//   - <INFO>...</INFO>
// Renvoie le contenu de la balise <TYPE> présente dans le message si le 
// document est du type souhaité. Il peut être vide.
// Renvoie null si le tag ERROR ou INFO n'est pas détecté à la racine
function _XMLUtil_ErrorOrInfoType(rootTagName, xmlDoc)
{
   var type = null;
   if ( xmlDoc != null )
   {
      if ( xmlDoc.documentElement.tagName == rootTagName )
      {
         var type = xmlDoc.getElementsByTagName("TYPE");
         if ( (type != null) && (type.length > 0) )
         {
            type = XMLUtil_getElementContent(type[0]);
         }
         if(type==null) type="";
      }
   }
   return type;
}   

// Retourne le premier élément fils de nom name
function XMLUtil_getChildByTagName(elt, name)
{
   var curChild = elt.firstChild;
  
   while(curChild)
   {
      if(curChild.nodeType == 1)
      {
         if(curChild.tagName == name) {return curChild;}
      }
      curChild = curChild.nextSibling;
   }
   
   return null;
}
