$MSG=new Object();
 $MSG["alert_xhr_missing"]="Abbruch!\n\nDieser Browser unterstützt leider kein XMLHttpRequest!";
 $MSG["alert_xhr_deactivated"]="Abbruch!\n\nLeider ist XMLHttpRequest momentan deaktiviert.\nBitte das Ausführen erlauben!";
 $MSG["alert_xhr_failing"]="Abbruch!\n\nXMLHttpRequest konnte nicht starten!";
 $MSG["alert_xml_error"]="Fehler bei der Datenübermittlung!";

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

/* XMLHttpRequest absenden & verarbeiten */
/* doXHR(mixed callbackFunction, string url [, string requestData [, string requestType [, mixed requestHeader [, bool forceNoCach]]]])
 * Sendet einen XMLHttpRequest und ruft anschliessend die angegebene Callback-Funktion auf.
 * Der Callback-Funktion wird im 1. Parameter das Ergebnis (XML-Dokument-Knoten oder Response-Text),
 * im 2. Parameter das XMLHttpRequest-Objekt selbst uebergeben.
 *
 * Example: doXHR(funcObj,"http://example.org");
            doXHR("funcName","http://example.org",null,"GET","",false);
            doXHR("funcName","http://example.org",null,null,null,null,true);
            doXHR("funcName","http://example.org",null,"GET","Pragma: no-cache",true);
            doXHR("funcName","http://example.org",null,"GET",new Array("Pragma: no-cache"),true);
 * @return mixed: (object) XMLHttpRequest-Objekt oder null, wenn XMLHttpRequest nicht vorhanden, bzw.
                  (bool) false, wenn XMLHttpRequest moeglich, aber deaktiviert ist */
function doXHR(callback,url,data,type,header,forceNoCache) {
 var i, h, xhrObj=null, result=null;

 // Doppelte Funktionalitaet je nach url-Parameter
 if(url!="@internalCall") {
  /*** 2. Parameter url ist ein normaler String (=URL) -> User-Call ***/

  if(!type) { type="GET"; }
  if(typeof(data)=="undefined") { data=null; }
  // Caching ggf. verhindern durch hinzufuegen eines Timestamps an den URL
  if(forceNoCache) { url+=((url.indexOf("?")>=0)?"&":"?")+(new Date()).getTime(); }

  xhrObj=newXHR();
  if(xhrObj) {
   // Rekursiven Aufruf initialisieren, um Ergebnis des Requests zu ermitteln
   xhrObj.onreadystatechange=function() { doXHR(callback,"@internalCall",xhrObj); }
   try {
    xhrObj.open(type,url,true);
    // Request-Header senden
    if(header && header.length) {
     if(typeof(header)=="string") {
      // (einzelnen)
      h=header.split(": ");
      if(h.length==2) { xhrObj.setRequestHeader(h[0],h[1]); }
     } else {
      // (mehrere in Array)
      for(i=0;i<header.length;i++) {
       h=header[i].split(": ");
       if(h.length==2) { xhrObj.setRequestHeader(h[0],h[1]); }
      }
     }
    }

   xhrObj.send(data);

   } catch(e) {
    alert($MSG["alert_xhr_failing"]); xhrObj=false;
   }
  }
  // Standardaufruf (User-Call): xhrObj zurueckgeben
  return xhrObj;

 } else {
  /*** 2. Parameter url ist "@internalCall" - data sollte dann ein xhrObj sein ***/
  xhrObj=data;
  if(xhrObj.readyState==4) {
   if(xhrObj.status==200) {
    // XML- oder Text-Daten?
    if(xhrObj.responseXML && xhrObj.responseXML.firstChild) {
     result=xhrObj.responseXML;
    } else {
     result=xhrObj.responseText;
    }
   }
   // Selbstaufruf (intern):
   // Gewuenschte Funktion mit Ergebnis des Requests (Text oder XML-Dokumentknoten)
   // und dem Request-Objekt selbst (XMLHttpRequest-Object) aufrufen
   if(typeof(callback)=="function" ) {
    callback(result,xhrObj);
   } else if(typeof(callback)=="string" && typeof(window[callback])=="function" ) {
    window[callback](result,xhrObj);
   } else {
    alert('doXHR()-Callback-Funktion "'+callback+'()" existiert nicht!');
   }
  }

 }
}

// --------------------------------------------------------------------------

/* Erstelle XMLHttpRequest-Objekt */
/* newXHR([string generalErrorMessage [, string activateErrorMessage [, bool returnMessage]]])
 * Erstellt ein neues XMLHttpRequest-Objekt. Gibt auf Wunsch bei Misserfolg die
 * jeweilige ErrorMessage als Alert aus oder als Ergebnis zurueck.
 *
 * Example: newXHR();
            newXHR("Kein XMLHttpRequest vorhanden","Kein XMLHttpRequest erlaubt");
            newXHR("Kein XMLHttpRequest vorhanden","Kein XMLHttpRequest erlaubt",true);
 * @return mixed: (object) XMLHttpRequest-Objekt oder null, wenn XMLHttpRequest nicht vorhanden, bzw.
                  (bool) false, wenn XMLHttpRequest moeglich, aber deaktiviert ist, sowie
                  (string) die jeweilige ErrorMessage, wenn returnMessage true ist */
 function newXHR(generalErrorMsg,activateErrorMsg,returnMsgFlag) {
  var result=null, msg;

  if(window.XMLHttpRequest) {
   // Standard
   result=new XMLHttpRequest();
  } else if(window.ActiveXObject) {
   // IE<7
   try { result=new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { result=false; }
  } else if(window.createRequest) {
   // IceBrowser
   result=window.createRequest();
  }

  if(!result && generalErrorMsg && activateErrorMsg) {
   msg=(typeof(result)=="boolean")?activateErrorMsg:generalErrorMsg;
   if(returnMsgFlag) {
    result=msg;
   } else {
    alert(msg)
   }
  }

  return result;
 }

// --------------------------------------------------------------------------

/* Hole Markup eines Elements */
/* erwartet node oder collection als startObj */
function innerXML(startObj,alwaysClosingTag) {
 var i, collectTags, result="";

 if(!alwaysClosingTag) { alwaysClosingTag=false; }

 if(startObj&& startObj.length && startObj[0].parentNode) {
  collectTags=startObj[0].nodeName;
  startObj=startObj[0].parentNode
 }

 if(startObj&& startObj.childNodes) {
  for(i=0; i<startObj.childNodes.length; i++) {
   if(!collectTags || startObj.childNodes[i].nodeName==collectTags) {
    result+=outerXML(startObj.childNodes[i],alwaysClosingTag);
   }
  }
 }
 return result;
}

// --------------------------------------------------------------------------

/* Hole Markup eines Tags mit Kindelementen */
function outerXML(node,alwaysClosingTag) {
 var i, result="";

 if(!alwaysClosingTag) { alwaysClosingTag=false; }

 switch(node.nodeType) {
  case 1: // ELEMENT_NODE
   result+="<"+node.nodeName;
   for(i=0; i<node.attributes.length; i++) {
    if(node.attributes.item(i).nodeValue!=null) {
     result+=' '+node.attributes.item(i).nodeName+'="'+node.attributes.item(i).nodeValue+'"';
    }
   }

   // Leere Elemente ggf. ohne Endtag schliessen (z.B. <br />)
   if(!node.childNodes.length) {
    result+=(alwaysClosingTag)?('></'+node.nodeName+'>'):' />';
   } else {
    result+='>'+innerXML(node,alwaysClosingTag)+'</'+node.nodeName+'>';
   }
   break;

  case 3: //TEXT_NODE
   result+=node.nodeValue;
   break;

  case 4: // CDATA_SECTION_NODE
   result+='<![CDATA['+node.nodeValue+']]>';
   break;

  case 5: // ENTITY_REFERENCE_NODE
   result+='&'+node.nodeName+';'
   break;

  case 8: // COMMENT_NODE
   result+='<!--'+node.nodeValue+'-->';
   break;

  case 9: // DOCUMENT_NODE
   if(node.childNodes.length) {
    result+=innerXML(node,alwaysClosingTag);
   }
   break;
 }
 return result;
}

// --------------------------------------------------------------------------

/* Hole Text eines Elements (und seiner Kinder) */
function innerText(node) {
 var i, result="";

 if(node && node.childNodes) {
  for(i=0; i<node.childNodes.length; i++) {
   child=node.childNodes.item(i);

   switch(child.nodeType) {
    case (1): // ELEMENT_NODE
    if(child.childNodes.length) {
     result+=innerText(child);
    }
    break;

    case (3 || 4): //TEXT_NODE + CDATA_SECTION_NODE
     result+=child.nodeValue;
     break;
   }

  }
 }

 return result;
}
// --------------------------------------------------------------------------

/* Hole numerischen Wert eines Elements (und seiner Kinder) */
function innerNumber(node,defaultNumber) {
 var result;

 if(typeof(defaultNumber)=="undefined" || isNaN(defaultNumber)) { defaultNumber=0; }

 result=parseFloat(innerText(node));
 if(isNaN(result)) { result=defaultNumber; }

 return result;
}

// --------------------------------------------------------------------------