Sarissa.getView = function(strXSL) {
  try {
    var xmlhttp = new XMLHttpRequest();
    // prevent caching
    var uri = strXSL + ((strXSL.indexOf("?") < 0) ? "?" : "&") + "ms=" + new Date().getTime();
    xmlhttp.open("GET", uri, false);
    xmlhttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
    xmlhttp.setRequestHeader("Pragma", "no-chache");
    xmlhttp.send("");
    if(Sarissa.getParseErrorText(xmlhttp.responseXML) != Sarissa.PARSED_OK)
      throw Sarissa.getParseErrorText(xmlhttp.responseXML);
    var proc = new XSLTProcessor();
    proc.importStylesheet(xmlhttp.responseXML);
  } catch(e) {
    return null;
  }
  return {
    lastError: 0,
    lastErrorText: "",
    render: function(xmlModel, strElementId) {
      // load XML, transform using processor and update html
      try {
        // transform using processor and update html
        var htmlElement = document.getElementById(strElementId);
        if (htmlElement == null)
          throw "Id: "+strElementId+" not found";
        if (typeof xmlModel == "object" && xmlModel.getDoc()) 
          Sarissa.updateContentFromNode(xmlModel.getDoc(), htmlElement, proc);
        else if (typeof xmlModel == "string") {
          var uri = xmlModel + ((xmlModel.indexOf("?") < 0) ? "?" : "&") + "ms=" + new Date().getTime();
          Sarissa.updateContentFromURI(uri, htmlElement, proc);
        } else 
          throw "illegal Model"; 
      } catch(e) {
        var rc = e.number & 0xFFFF;
        if ( !rc ) rc = 8000;
        lastError = rc;
        if (""+e == "[object Error]") 
          lastErrorText = e.description;
        else
          lastErrorText = ""+e;
      }
      return rc;
    }, 
    setParameter: function(strName, strValue) {
      proc.setParameter("", strName, strValue);
      return;
    },
    getParameter: function(strName, strValue) {
      return proc.getParameter("", strName);
    },
    clearParameters: function() {
      proc.clearParameters();
      return;
    }
  };
}

Sarissa.getModel = function(strURI) {
  try {
    var xmlhttp = new XMLHttpRequest();
    if ( strURI )
      request(strURI, false);
  } catch(e) {
    return null;
  }
  function request(strURI, bPOST, callback) {
    var async = (callback) ? true : false;
    // load document
    /*if ( !bPOST && this.xmlDoc ) {
      Sarissa.clearChildNodes(this.xmlDoc.documentElement);      delete this.xmlDoc;
      this.xmlDoc = null;
    }*/
    if ( !strURI ) {
      return;
    }
    // prevent caching
    var uri = strURI + ((strURI.indexOf("?") < 0) ? "?" : "&") + "ms=" + new Date().getTime();
    xmlhttp.open(bPOST ? "POST" : "GET", uri, async);
    /*// the callback funtion
    if (async) {
      xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4) {
          if ( (xmlhttp.status == 200) &&
               (Sarissa.getParseErrorText(xmlhttp.responseXML) == Sarissa.PARSED_OK) )
            thisModel.xmlDoc = xmlhttp.responseXML;
          callback(xmlhttp.status);          
          delete xmlhttp.responseXML;
          thisModel._inProgress = false;
        }
      }
    }*/
    // send the request
    if (bPOST) {
      xmlhttp.setRequestHeader("Content-Type", "text/xml");
      xmlhttp.send(this.toString());
    } else {
      xmlhttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
      xmlhttp.setRequestHeader("Pragma", "no-chache");
      xmlhttp.send("");
    }
    if (!async) {
      if (Sarissa.getParseErrorText(xmlhttp.responseXML) != Sarissa.PARSED_OK)
        throw Sarissa.getParseErrorText(xmlhttp.responseXML);
      if (xmlhttp.status == 200) {
        //this.xmlDoc = xmlhttp.responseXML;      
      }
    }
    return;
  }
  return {
    lastError: 0,
    lastErrorText: "",
    load: function(strDoc, callback) {
      try {
        request(strDoc, false, callback);
        throw "Blöder Fehler";
      } catch(e) {
        var rc = e.number & 0xFFFF;
        if ( !rc ) rc = 8000;
        lastError = rc;
        if (""+e == "[object Error]") 
          lastErrorText = e.description;
        else
          lastErrorText = ""+e;
//alert(lastError);          
      }
      return;
    },
    getDoc: function() {
      return xmlhttp.responseXML;
    },
    toString: function() {
      if ( xmlhttp.responseXML )
        return new XMLSerializer().serializeToString(xmlhttp.responseXML);
      else
        return "";
    }
  }
}    
    
////////////////////////////////////////////////////////////////
// Class: AjaxView
// 
// Contructor: AjaxView(<uri of stylesheet>)
//
// Properties: lastError       // last error number
//             lastErrorText   // last error description
//   
// Methods:    render(<name of document>, <element ID>)
//             setParameter(<name>, <value>)
//             clearParameters()
//             lastErrorReset()
//

////////////////////////////////////////////////////////////////
// constructor: load stylesheet "strXSL" and create XSLT processor
//
function AjaxView(strXSL) {
  // initialize public properties
  this.lastError = 0;
  this.lastErrorText = "";
  // initialze private properties
  this.stylesheetLoaded = false;

  // load stylesheet and create processor
  try {
    var xmlhttp = new XMLHttpRequest();
    // prevent caching
    var uri = strXSL + ((strXSL.indexOf("?") < 0) ? "?" : "&") + "ms=" + new Date().getTime();
    xmlhttp.open("GET", uri, false);
    xmlhttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
    xmlhttp.setRequestHeader("Pragma", "no-chache");
    xmlhttp.send("");
    if(Sarissa.getParseErrorText(xmlhttp.responseXML) != Sarissa.PARSED_OK)
      throw Sarissa.getParseErrorText(xmlhttp.responseXML);
    this.proc = new XSLTProcessor();
    this.proc.importStylesheet(xmlhttp.responseXML);
    this.stylesheetLoaded = true;
    delete xmlhttp.responseXML;
  } catch(e) {
    var rc = e.number & 0xFFFF;
    if ( !rc ) rc = 8000;
    this.lastError = rc;
    if (""+e == "[object Error]") 
      this.lastErrorText = e.description;
    else
      this.lastErrorText = ""+e;
  }
  return;
}

////////////////////////////////////////////////////////////////
// render: transform document (model) and update HTML
//         xmlModel:     instance of AjaxModel or URI to XML document
//         strElementId: Element ID to update after transformation
//
// Remark: model is loaded asynchronously
//
AjaxView.prototype.render = function(xmlModel, strElementId) {
  var rc = 0;
  // load XML, transform using processor and update html
  try {
    if (this.stylesheetLoaded == false)
      throw "Stylesheet not loaded";
    // transform using processor and update html
    var htmlElement = document.getElementById(strElementId);
    if (htmlElement == null)
      throw "Id: "+strElementId+" not found";
    if (typeof xmlModel == "object" && xmlModel.xmlDoc) 
      Sarissa.updateContentFromNode(xmlModel.xmlDoc, htmlElement, this.proc);
    else if (typeof xmlModel == "string") {
      var uri = xmlModel + ((xmlModel.indexOf("?") < 0) ? "?" : "&") + "ms=" + new Date().getTime();
      Sarissa.updateContentFromURI(uri, htmlElement, this.proc);
    } else 
      throw "illegal Model"; 
  } catch(e) {
    rc = e.number & 0xFFFF;
    if ( !rc ) rc = 8000;
    this.lastError = rc;
    if (""+e == "[object Error]") 
      this.lastErrorText = e.description;
    else
      this.lastErrorText = ""+e;
  }
  return rc;
}

////////////////////////////////////////////////////////////////
// setParameter: Set XSLT parameter of the imported stylesheet
//
AjaxView.prototype.setParameter = function(strName, strValue) {
  this.proc.setParameter("", strName, strValue);
  return;
}

////////////////////////////////////////////////////////////////
// getParameter: get XSLT parameter
//
AjaxView.prototype.getParameter = function(strName, strValue) {
  return this.proc.getParameter("", strName);
}

////////////////////////////////////////////////////////////////
// clearParameters: Clear parameters
// (set them to default values as defined in the stylesheet itself)
AjaxView.prototype.clearParameters = function() {
  this.proc.clearParameters();
  return;
}

////////////////////////////////////////////////////////////////
// lastErrorReset: reset properties lastError and LastErrorText
//
AjaxView.prototype.lastErrorReset = function() {
  this.lastError = 0;
  this.lastErrorText = "";
  return 0;
}
// end class AjaxView
////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////
// Class: AjaxModel
// 
// Contructor: AjaxModel(<uri of document>)
//             URI (optional)
//
// Properties: xmlDoc        // loaded document
//             lastError     // last error number
//             lastErrorText // last error description
//   
// Methods:    load(<uri>, callback)     // load XML document
//             save(<uri>, <callback>)   // save XML document
//             saveComplete(httpStatus, resultXML)
//                                       // called in callback of save()
//             selectNodes(<xpath>)      // emulates IE method
//             selectSingleNode(<xpath>) // emulates IE method
//             toString()                // serialize XML document
//             lastErrorReset()
//
/*function AjaxModel(strDoc) {
  // initialize public properties
  this.xmlDoc = null;
  this.lastError = 0;
  this.lastErrorText = "";
  // initialze private properties
  this._inProgress = false;
  
  // load document
  if ( strDoc )
    this._request(strDoc, false);
    
  return;
}

////////////////////////////////////////////////////////////////
// _request: execute GET/POST request (internal only)
//           strURI   : URI
//           bPOST    : true => POST request, otherwies GET request
//           callback : [optional] callback function after sucessfully
//                      asynchronous xmlhttp Request 
//                      default: synchronous call
//                      callback(<HTTP status>, <resulting XML doc>)
//
AjaxModel.prototype._request = function(strURI, bPOST, callback) {
  // do not call twice
  if (this._inProgress) return;
  this._inProgress = true;
  
  // used to have a reference to the instance of the model
  // in the callback function of an asynchronous request
  var thisModel = this;
  
  var async = (callback) ? true : false;
  
  // load document
  try {
    if ( !bPOST && this.xmlDoc ) {
      Sarissa.clearChildNodes(this.xmlDoc.documentElement);      delete this.xmlDoc;
      this.xmlDoc = null;
    }
    if ( !strURI ) {
      this._inProgress = false;
      return;
    }
    var xmlhttp = new XMLHttpRequest();
    // prevent caching
    var uri = strURI + ((strURI.indexOf("?") < 0) ? "?" : "&") + "ms=" + new Date().getTime();
    xmlhttp.open(bPOST ? "POST" : "GET", uri, async);
    // the callback funtion
    if (async) {
      xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4) {
          if ( (xmlhttp.status == 200) &&
               (Sarissa.getParseErrorText(xmlhttp.responseXML) == Sarissa.PARSED_OK) )
            thisModel.xmlDoc = xmlhttp.responseXML;
          callback(xmlhttp.status);          
          delete xmlhttp.responseXML;
          thisModel._inProgress = false;
        }
      }
    }
    // send the request
    if (bPOST) {
      xmlhttp.setRequestHeader("Content-Type", "text/xml");
      xmlhttp.send(this.toString());
    } else {
      xmlhttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
      xmlhttp.setRequestHeader("Pragma", "no-chache");
      xmlhttp.send("");
    }
    if (!async) {
      if (Sarissa.getParseErrorText(xmlhttp.responseXML) != Sarissa.PARSED_OK)
        throw Sarissa.getParseErrorText(xmlhttp.responseXML);
      //alert(xmlhttp.GetAllResponseHeaders()); // IE only
      if (xmlhttp.status == 200) {
        //this.xmlDoc = Sarissa.getDomDocument();
        //Sarissa.moveChildNodes(xmlhttp.responseXML.documentElement, this.xmlDoc.documentElement, true);
        this.xmlDoc = xmlhttp.responseXML;      
        //this.xmlDoc.documentElement.appendChild(xmlhttp.responseXML.documentElement.cloneNode());
        //alert(new XMLSerializer().serializeToString(this.xmlDoc));
      }
      //Sarissa.clearChildNodes(xmlhttp.responseXML.documentElement);      //alert(new XMLSerializer().serializeToString(xmlhttp.responseXML));
      //delete xmlhttp.responseXML;
      //delete xmlhttp;
      this._inProgress = false;    
    }
  } catch(e) {
    this._inProgress = false;    
    var rc = e.number & 0xFFFF;
    if ( !rc ) rc = 8000;
    this.lastError = rc;
    if (""+e == "[object Error]") 
      this.lastErrorText = e.description;
    else
      this.lastErrorText = ""+e;
  }
  
  if (!async) this._inProgress = false; 
  return;
}*/

function AjaxModel(strDoc) {
  // initialize public properties
  this.xmlDoc = null;
  this.lastError = 0;
  this.lastErrorText = "";
  // initialze private properties
  this._inProgress = false;
  
  var xmlhttp = new XMLHttpRequest();
  
  this._request = function(strURI, bPOST, callback) {
    if ( !strURI ) return;  // nothing to do

    var uri;  
    var async = (callback) ? true : false;
    
    // do not call twice
    if ( !strURI )
      return;
    if (this._inProgress) return;
    this._inProgress = true;
    
    // load document
    try {
      // prevent caching
      uri = strURI + ((strURI.indexOf("?") < 0) ? "?" : "&") + "ms=" + new Date().getTime();
      xmlhttp.open(bPOST ? "POST" : "GET", uri, async);
      // the callback funtion
      /*if (async) {
        xmlhttp.onreadystatechange = function() {
          if (xmlhttp.readyState == 4) {
            if ( (xmlhttp.status == 200) &&
                 (Sarissa.getParseErrorText(xmlhttp.responseXML) == Sarissa.PARSED_OK) )
              thisModel.xmlDoc = xmlhttp.responseXML;
            callback(xmlhttp.status);          
            thisModel._inProgress = false;
          }
        }
      }*/
      // send the request
      if (bPOST) {
        xmlhttp.setRequestHeader("Content-Type", "text/xml");
        xmlhttp.send(this.toString());
      } else {
        xmlhttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
        xmlhttp.setRequestHeader("Pragma", "no-chache");
        xmlhttp.send("");
      }
      if (!async) {
        if (Sarissa.getParseErrorText(xmlhttp.responseXML) != Sarissa.PARSED_OK)
          throw Sarissa.getParseErrorText(xmlhttp.responseXML);
        //alert(xmlhttp.GetAllResponseHeaders()); // IE only
        if (xmlhttp.status == 200) {
          this.xmlDoc = xmlhttp.responseXML;      
        }
        this._inProgress = false;    
      }
    } catch(e) {
      this._inProgress = false;    
      var rc = e.number & 0xFFFF;
      if ( !rc ) rc = 8000;
      this.lastError = rc;
      if (""+e == "[object Error]") 
        this.lastErrorText = e.description;
      else
        this.lastErrorText = ""+e;
    }
  
    if (!async) this._inProgress = false; 
    return;
    }
  
  // load document
  if ( strDoc )
    this._request(strDoc, false);
    
  return;
}


////////////////////////////////////////////////////////////////
// load: load XML document
//       strDoc   : URI
//       callback : [optional] callback function after sucessfully
//                  asynchronous xmlhttp Request 
//                  default: synchronous call
//                  callback(<HTTP status>, <resulting XML doc>)
//
AjaxModel.prototype.load = function(strDoc, callback) {
  this._request(strDoc, false, callback);
  return;
}

////////////////////////////////////////////////////////////////
// save: save XML document
//       strURI   : URI
//       callback : [optional] callback function after sucessfully
//                  asynchronous xmlhttp Request 
//                  default: synchronous call
//                  callback(<HTTP status>, <resulting XML doc>)
//
AjaxModel.prototype.save = function(strURI, callback) {
  this._request(strURI, true, callback);
  return;
}

////////////////////////////////////////////////////////////////
// complete: must be called in callback function of load or save
//           httpStatus  : same param as callback function
//           responseXML : same param as callback function
//
AjaxModel.prototype.complete = function(httpStatus, responseXML) {
  this._inProgress = false;
  if ( (httpStatus == 200) && responseXML )
    //Sarissa.copyChildNodes(responseXML, this.xmlDoc);
    this.xmlDoc = responseXML;
}

////////////////////////////////////////////////////////////////
// selectNodes
//
AjaxModel.prototype.selectNodes = function(xpath) {
  return this.xmlDoc.selectNodes(xpath);
}

////////////////////////////////////////////////////////////////
// selectSingleNode
//
AjaxModel.prototype.selectSingleNode = function(xpath) {
  return this.xmlDoc.selectSingleNode(xpath);
}

////////////////////////////////////////////////////////////////
// toString: serialize XML document
//
AjaxModel.prototype.toString = function() {
  if ( this.xmlDoc )
    return new XMLSerializer().serializeToString(this.xmlDoc);
  else
    return "";
}

////////////////////////////////////////////////////////////////
// lastErrorReset: reset properties lastError and LastErrorText
//
AjaxModel.prototype.lastErrorReset = function() {
  this.lastError = 0;
  this.lastErrorText = "";
  return 0;
}
// end class AjaxModel
////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////
// DOM helper funtions (inspired by prototype)
//
// $(element)        : getElementById(element) -> element
// $U(element, html) : elment.innerHTML = html -> element
//
function $(element) {
  if (typeof element == 'string')
    element = document.getElementById(element);
  return element;
}

function $U(element, html) {
  html = typeof html == 'undefined' ? '' : html.toString();
  $(element).innerHTML = html;
  return element;
  //var htmlElement = document.getElementById(strElementId);
  //if (htmlElement) {
  //  Sarissa.clearChildNodes(htmlElement);
  //  var newElement = document.createElement(htmlType);
  //  newElement.appendChild(document.createTextNode(strText));
  //  htmlElement.appendChild(newElement);
  //}
}

function $debug(obj) {
  if (obj.lastError) {
    alert(obj.lastErrorText);
    if (obj.toString) alert(obj.toString());
  }
}

