// Setzt die Klasse eines Elementes
function zSetClass(oElement, sClass) {
	if(AT.ie) {
		oElement.className = sClass;
	} else {
		oElement.setAttribute("class", sClass);
	}
	return oElement;
}

// Setzt die Klasse eines Elementes
function zGetClass(oElement) {
	if(AT.ie) {
		return oElement.className;
	} else {
		return oElement.getAttribute("class");
	}
}

/**
 * Loescht eine Klasse aus einem Element
 */
function zRemoveClass(oElement, sClass) {
	if (oElement == null || sClass == null) {
		return false;
	}
	var className = zGetClass(oElement);
	if (className == null) {
		return false;
	}
	var classToSet = null;
	if (className != null) {
		var names = className.split(" ");
		for (var i = 0; i < names.length; i++) {
			if (names[i] != sClass) {
				if (classToSet == null) {
					classToSet = names[i];
				} else {
					classToSet += " " + names[i];
				}
			}
		}
	}
	zSetClass(oElement, classToSet);
};

/**
 * Hinzufuegen einer Klasse in ein Element
 */
function zAddClass(oElement, sClass) {
	if (oElement == null || sClass == null) {
		return false;
	}
	var className = zGetClass(oElement);
	if (className == null) {
		return false;
	}
	var classToSet = null;
	if (className != null) {
		var names = className.split(" ");
		for (var i = 0; i < names.length; i++) {
			if (names[i] != sClass) {
				if (classToSet == null) {
					classToSet = names[i];
				} else {
					classToSet += " " + names[i];
				}
			}
		}
	}
	if (classToSet == null) {
		classToSet = sClass;
	} else {
		classToSet += " " + sClass;
	}
	zSetClass(oElement, classToSet);
};

/**
 * Prueft, ob das Element die Klasse enthaelt
 */
function zHasClass(oElement, sClass) {

	if (oElement == null || sClass == null) {
		return false;
	}
	var className = zGetClass(oElement);
	if (className == null) {
		return false;
	}
	var names = className.split(" ");
	for (var i = 0; i < names.length; i++) {
		if (names[i] == sClass) {
			return true;
		}
	}
	return false;
};

// Setzt den Style eines HTML-DOM-Elements
// sStyle als Semikolon-separierte Liste (String) uebergeben
// Beispiel fuer sStyle: "position: absolute; top:5px;"
function zSetStyle(oElement, sStyle) {
  if(isIE) {
    var aStyles = sStyle.split(";");
    for(var i = 0; i < aStyles.length; i++) {
      var sSingle = aStyles[i];
      aSingle = sSingle.split(":");
      oElement.style.setAttribute(trim(aSingle[0]), trim(aSingle[1]), false);
    }
  } else {
    oElement.setAttribute("style", sStyle, false);
  }
  return oElement;
}

// (z)Xml-Funktionsdefinitionen generisch als CrossBrowser-Instanz
var zXml = {
  useActiveX:(typeof ActiveXObject != "undefined"),
  useDom:document.implementation && document.implementation.createDocument,
  useXmlHttp:(typeof XMLHttpRequest != "undefined")
};

zXml.ARR_XMLHTTP_VERS = [
  "MSXML2.XmlHttp.6.0",
  "MSXML2.XmlHttp.5.0",
  "MSXML2.XmlHttp.4.0",
  "MSXML2.XmlHttp.3.0",
  "MSXML2.XmlHttp",
  "Microsoft.XmlHttp"
];

zXml.ARR_DOM_VERS = [
  "MSXML2.DOMDocument.6.0",
  "MSXML2.DOMDocument.5.0",
  "MSXML2.DOMDocument.4.0",
  "MSXML2.DOMDocument.3.0",
  "MSXML2.DOMDocument",
  "Microsoft.XmlDom"
];

// Konstruktor
function zXmlHttp(){}

zXmlHttp.createRequest = function() {
  if(zXml.useXmlHttp){
    return new XMLHttpRequest();
  } else if(zXml.useActiveX) {
    if(!zXml.XMLHTTP_VER) {
      for(var i = 0; i < zXml.ARR_XMLHTTP_VERS.length; i++) {
        try {
          new ActiveXObject(zXml.ARR_XMLHTTP_VERS[i]);
          zXml.XMLHTTP_VER = zXml.ARR_XMLHTTP_VERS[i];
          break;
        } catch(oError) {} // Absicht: Hier soll kein Error geworfen werden!
                           // es wird die "beste" Version fuer MSIE ermittelt
      }
    }
    if(zXml.XMLHTTP_VER) {
      return new ActiveXObject(zXml.XMLHTTP_VER);
    } else {
      AT.log("atoolo: Could not create XML HTTP Request.", error);
    }
  } else {
    AT.log("atoolo: Your browser doesn't support an XMLHTTP Request.", error);
  }
}

// Abfrage, ob AJAX vom Client unterstuetzt wird
zXmlHttp.isSupported = function() {
  return zXml.useXmlHttp || zXml.useActiveX;
}

// (z)XmlDom generisch als CrossBrowser-Instanz
// erlaubt alle Dom-spezifischen Abfragen => XPath
 // Konstruktor
function zXmlDom(){}

zXmlDom.createDocument = function() {
  if(zXml.useDom){
    var oXmlDom = document.implementation.createDocument("","",null);
    oXmlDom.parseError = { valueOf:function() { return this.errorCode; }, toString:function() { return this.errorCode.toString() } };
//    oXmlDom.__initError__();
    oXmlDom.addEventListener("load", function() { this.__checkForErrors__(); this.__changeReadyState__(4); }, false);
    return oXmlDom;
  } else if(zXml.useActiveX) {
    if(!zXml.DOM_VER) {
      for(var i = 0; i < zXml.ARR_DOM_VERS.length; i++) {
        try{
          new ActiveXObject(zXml.ARR_DOM_VERS[i]);
          zXml.DOM_VER =  zXml.ARR_DOM_VERS[i];
          break;
        } catch(oError) {} // Absicht: Hier soll kein Error geworfen werden!
                           // es wird die "beste" Version fuer MSIE ermittelt
      }
    }
    if(zXml.DOM_VER) {
      return new ActiveXObject(zXml.DOM_VER);
    } else {
      AT.log("atoolo: Could not create XML DOM document.", "error");
    }
  } else {
    AT.log("atoolo: Your browser doesn't support an XML DOM document.", "error");
  }
}

// Abfrage, ob der Client das XML-DOM unterstuetzt.
zXmlDom.isSupported = function() {
  return zXml.useDom || zXml.useActiveX;
}

// Code to make Mozilla DOM documents act more like MS DOM documents.
var oMozDocument = null;
if(typeof XMLDocument != "undefined") {
  oMozDocument = XMLDocument;
} else if(typeof Document != "undefined") {
  oMozDocument = Document;
}

if(oMozDocument && !window.opera) {
//  oMozDocument.prototype.readyState = 0;
  oMozDocument.prototype.onreadystatechange = null;
  oMozDocument.prototype.__changeReadyState__ = function(iReadyState) {
//    this.readyState=iReadyState;
    if(typeof this.onreadystatechange == "function") {
      this.onreadystatechange();
    }
  }
// Fehlerbehandlung initiieren <=> nur zur Klasseninternen Verwendung
  oMozDocument.prototype.__initError__ = function() {
    this.parseError.errorCode = 0;
    this.parseError.filepos   = -1;
    this.parseError.line      = -1;
    this.parseError.linepos   = -1;
    this.parseError.reason    = null;
    this.parseError.srcText   = null;
    this.parseError.url       = null;
  }

// Fehler(-typ) abfragen. Wenn errorCode != 0 => Fehler  <=> Aufruf nur zur Klasseninternen Verwendung
// Fehlereigenschaften sind aber natuerlich auch oeffentlich erreichbar

  oMozDocument.prototype.__checkForErrors__ = function() {
    if(this.documentElement.tagName == "parsererror") {
      var reError=/>([\s\S]*?)Location:([\s\S]*?)Line Number(\d+),Column(\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/;
      reError.test(this.xml);
      this.parseError.errorCode = -999999;                      // Genau krieg ich es an dieser Stelle nicht hin
      this.parseError.reason    = RegExp.$1;                    // Grund fuer den Fehler
      this.parseError.url       = RegExp.$2;                    // XML-URL, die den Fehler wirft
      this.parseError.line      = parseInt(RegExp.$3);          // Zeile, in der der Fehler auftritt
      this.parseError.linepos   = parseInt(RegExp.$4);          // Spalte, in der der Fehler auftritt
      this.parseError.srcText   = RegExp.$5;                    // Liefert den Source zurueck
    }
  }

// String in das DOM laden. Muss strict XML-Semantik genuegen
  oMozDocument.prototype.loadXML = function(sXml) {
    this.__initError__();
    this.__changeReadyState__(1);
    var oParser = new DOMParser();
    var oXmlDom = oParser.parseFromString(sXml, "text/xml");
    while(this.firstChild) {
      this.removeChild(this.firstChild);
    }
    for(var i = 0; i < oXmlDom.childNodes.length; i++) {
      var oNewNode = this.importNode(oXmlDom.childNodes[i],true);
      this.appendChild(oNewNode);
    }
    this.__checkForErrors__();
    this.__changeReadyState__(4);
  }

// String in das DOM laden. Muss strict XML-Semantik genuegen
  oMozDocument.prototype.loadXML2 = function(sXml) {
    this.__initError__();
    this.__changeReadyState__(1);
    var oParser = new DOMParser();
    var oXmlDom = oParser.parseFromString(sXml, "text/xml");
    while(this.firstChild) {
      this.removeChild(this.firstChild);
    }
    for(var i = 0; i < oXmlDom.childNodes.length; i++) {
      var oNewNode = this.importNode(oXmlDom.childNodes[i],true);
      this.appendChild(oNewNode);
    }
    this.__checkForErrors__();
    this.__changeReadyState__(4);
  }


// Datei via http:// - URL in das DOM laden. Muss fuer erfolgreiches Laden "strict" XML-Datei sein
  oMozDocument.prototype.__load__ = oMozDocument.prototype.load;
  oMozDocument.prototype.load = function(sURL) {
    this.__initError__();
    this.__changeReadyState__(1);
    this.__load__(sURL);
  }

// Prototyp fuer XML-Node-Getter <=> nur zur Klasseninternen Verwendung
  Node.prototype.__defineGetter__("xml", function() {
    var oSerializer = new XMLSerializer();
    return oSerializer.serializeToString(this,"text/xml");
  });

// Prototyp fuer Text-Node-Getter <=> nur zur Klasseninternen Verwendung
  Node.prototype.__defineGetter__("text", function() {
    var sText = "";
    for(var i = 0; i < this.childNodes.length; i++) {
      if(this.childNodes[i].hasChildNodes()) {
        sText += this.childNodes[i].text;
      } else {
        sText += this.childNodes[i].nodeValue;
      }
    }
    return sText;
  });
}



// (z)Xslt generisch als CrossBrowser-Instanz
// erlaubt XML => Stylesheet-Transformationen
// ich befuerchte, wir werden es kaum brauchen, aber da ich schonmal dabei war ;)
// wer es nutzen moechte, ist herzlich eingeladen. Die Moeglichkeiten sind sicher vorhanden.

// Hierfuer die XML UND die XSL-Datei mit "async = false" in jeweils ein XML-DOM.Document (XmlDom, XslDom) laden und
// dann mit der Notation "XmlDom.transformNode(XslDom);" transformieren. Klappt auch in jeder Node-Ebene.
// Die transformToText-Methode dient nur mal wieder der Browser-Angleichung. Der Rest funzt eh identisch.

function zXslt() {} // Konstruktor
zXslt.transformToText = function(oXml,oXslt) {
  if(typeof XSLTProcessor != "undefined") {
    var oProcessor = new XSLTProcessor();
    oProcessor.importStylesheet(oXslt);
    var oResultDom = oProcessor.transformToDocument(oXml);
    var sResult = oResultDom.xml;
    if(sResult.indexOf("<transformiix:result") > -1) {
      sResult = sResult.substring(sResult.indexOf(">") + 1, sResult.lastIndexOf("<"));
    }
    return sResult;
  } else if(zXml.useActiveX) {
    return oXml.transformNode(oXslt);
  } else {
    throw new Error(Lina.translate( "js.xBrowserExtensions.text1" ));
  }
}

// zXPath
// erlaubt XPath-Abfragen auf Basis der MSIE-XPath-Funktionalitaeten (selectNodes und selectSingleNode)
function zXPath() {} // Konstruktor
// Liefert die erste Node, die der sXPath-Abfrage (Beispiel: "na:myContent/pub:folders") genuegt innerhalb der oRefNode (Beispiel Node: (myContent).
zXPath.selectSingleNode = function(oRefNode, sXPath, oXmlNs) {
  if(typeof XPathEvaluator != "undefined") {
    oXmlNs = oXmlNs || {};
    var nsResolver = function(sPrefix) {
      return oXmlNs[sPrefix];
    };
    var oEvaluator = new XPathEvaluator();
    var oResult = oEvaluator.evaluate(sXPath, oRefNode, nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
    if(oResult != null) {
      return oResult.singleNodeValue;
    } else {
      return null;
    }
  } else if(zXml.useActiveX) {
    if(oXmlNs) {
      var sXmlNs="";
      for(var sProp in oXmlNs) {
        sXmlNs += "xmlns:" + sProp + "=\'" + oXmlNs[sProp] + "\' ";
      }
      oRefNode.ownerDocument.setProperty("SelectionNamespaces", sXmlNs);
    }
    return oRefNode.selectSingleNode(sXPath);
  } else {
    throw new Error(Lina.translate( "js.xBrowserExtensions.text2" ));
  }
}

// Liefert alle Nodes, die der sXPath-Abfrage (Beispiel: "myContent/folders") genuegen innerhalb der oRefNode (Beispiel Node: (myhead).
zXPath.selectNodes = function(oRefNode, sXPath, oXmlNs) {
  if(typeof XPathEvaluator != "undefined") {
    oXmlNs = oXmlNs || {};
    var nsResolver = function(sPrefix) {
      return oXmlNs[sPrefix];
    }
    var oEvaluator = new XPathEvaluator();
    var oResult = oEvaluator.evaluate(sXPath, oRefNode, nsResolver, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
    var aNodes = new Array;
    if(oResult != null) {
      var oElement = oResult.iterateNext();
      while(oElement) {
        aNodes.push(oElement);
        oElement = oResult.iterateNext();
      }
    }
    return aNodes;
  } else if(zXml.useActiveX) {
    if(oXmlNs) {
      var sXmlNs = "";
      for(var sProp in oXmlNs) {
        sXmlNs += "xmlns:" + sProp + "=\'" + oXmlNs[sProp] + "\' ";
      }
      oRefNode.ownerDocument.setProperty("SelectionNamespaces", sXmlNs);
    }
    return oRefNode.selectNodes(sXPath);
  } else {
    throw new Error(Lina.translate( "js.xBrowserExtensions.text2" ));
  }
}


// Serialisiert eine Node zu einem String
function zXMLSerializer() {
	Lina.requireOnce("common/lina/utils.js");
} // Konstruktor

zXMLSerializer.serializeToString = function(oNode) {
	var sXml = [];
	switch(oNode.nodeType) {
		case 1:
			sXml.push("<");
			sXml.push(oNode.tagName);
			for(var i = 0; i < oNode.attributes.length; i++) {
				sXml.push(" ");
				sXml.push(oNode.attributes[i].name);
				sXml.push("=\"");
				sXml.push(oNode.attributes[i].value.replace(/\"/g,"&quot;"));
				sXml.push("\"");
			}
			if (oNode.tagName.toLowerCase() == "br") {
				sXml.push(" />");
			} else {
				sXml.push(">");
				for(var i = 0; i < oNode.childNodes.length; i++) {
					sXml.push(this.serializeToString(oNode.childNodes[i]));
				}
				sXml.push("</");
				sXml.push(oNode.tagName);
				sXml.push(">");
			}
			break;
		case 3:
			sXml.push(Lina.Utils.String.encodeXml(oNode.nodeValue));
			break;
		case 4:
			sXml.push("<![CDATA[");
			sXml.push(oNode.nodeValue);
			sXml.push("]]>");
			break;
		case 7:
			sXml.push("<?");
			sXml.push(oNode.nodevalue);
			sXml.push("?>");
			break;
		case 8:
			sXml.push("<!--");
			sXml.push(oNode.nodevalue);
			sXml.push("-->");
			break;
		case 9:
			for(var i = 0; i < oNode.childNodes.length; i++) {
				sXml.push(this.serializeToString(oNode.childNodes[i]));
			}
			break;
	}
	return sXml.join("");
}
