/**
 * A basic AJAX-class. The original code was by Aleem Bawany on
 * http://aleembawany.com/2005/09/01/ajax-instant-tutorial/
 * based on an Ajax tutorial by Rasmus Lerdorf:
 * http://marc.theaimsgroup.com/?l=php-general&m=112198633625636&w=2
 *
 * This works as follows:
 *   o Instanciate a new AJAX-object
 *   o Set a callback or output-node
 *   o Add parameters, if you like
 *   o call sendReq()
 *
 * Last update: 10.Apr.2007
 *
 * @author Achim Wiedemann
 */
function AJAX(callback){
  //--Constructor-----
  // Store just the name of the node, instead of the node itself, is stored so
  // the HTML-document can be built up completely first. This makes it possible
  // to instanciate an AJAX-class at the very beginning of a document, e.g. in
  // the <head>-section, which seems to be good style to me...
  this._outputNodeName = null;
	this._xmlhttp = null
	this._parameters = new Object();
	this._callback = ((typeof callback) == "undefined") ? null : callback;
	this._avoidCaching = true;

  //--Methods-----
  /**
   * @param String The url to call (e.g. "do_something.php"). Set URL-Parameters
   *               with addParameter('param_name', 'param_value').
   */
	this.sendReq = function(url){
	  if (!this.hasOutputNode() && !this.hasCallback()){
	    alert("AJAX-Notice: You should either assign an output-node or a callback before sending an XML-HTTP-Request!");
	  }
	  
	  // Avoid caching by adding a timestamp as a paramter-name
	  if (this._avoidCaching){
	    now = new Date();
	    this.addParameter(now.getTime(), "");
	  }

	  // Build the query-string for the request
	  var parameterString = "";
	  first = true;
	  for (pName in this._parameters){
	    if (first){
	      parameterString += "?";
	      first = false;
	    }else{
	      parameterString += "&";
	    }
	    parameterString += pName + "=" + encodeURIComponent(this._parameters[pName]);
	  }

    // Get the XMLHttpRequest-object.
	  try {
      this._xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
	  }catch (e){
	    alert("Sorry, your browser doesn't support XMLHttpRequests. Maybe you should upgrade to a contemporary browser.\nDownload Firefox-Browser at\n\nwww.mozilla.com");
	    return false;
	  }

    // Define an event-handler that will be called when the xmlhttp-state is
    // changed. The thisObject var holds a reference to the current AJAX-object,
    // so it can be accesed from inside the state-handler.
    thisObject = this;
	  this._xmlhttp.onreadystatechange = function(){ thisObject.triggered(document.getElementById(thisObject.outputNodeName)); };
	  
	  // Set method and target-URL of the request (as well as parameters in form
	  // of a query-string)
	  this._xmlhttp.open("GET", url + parameterString);

    // Send the request (IE needs at least a null here)  
	  this._xmlhttp.send(null);
	  
	  // Reset the parameters
	  this.reset();
	  return true;
	}
	
	/** 
	 * Use this functions to pass parameters to the programm, called by sendReq().
	 * The params will be converted to a query-string before the request is made.
	 *
   * @param String name The parameter name
   * @param String value The parameter value
   */
	this.addParameter = function(name, value){
	  this._parameters[name] = value;
	}
	
	/**
	 * Resets the parameters
	 */
	this.reset = function(){
	  this._parameters = new Object();
	}
	
	/**
	 * Sets the name of the output node in the document.
	 *
	 * @param String outputNodeName The name of the output node in the document
	 */
	this.setOutputNode = function (outputNodeName){
	  this._outputNodeName = outputNodeName;
	}
	
	/**
	 * @return bool
	 */
	this.hasOutputNode = function(){
	  return null != this._outputNodeName;
	}
	
	/**
	 * Determines a callback that will be called when a response arrives. The
	 * callback will get the ajax-response passed as a parameter.
	 *
	 * @param String callbackName The name of the callback to call
	 */
	this.setCallback = function (callbackName){
  	this._callback = callbackName;
	}
	
	/**
	 * @return bool
	 */
	this.hasCallback = function (){
  	return null != this._callback;
	}
	
	/**
	 * @param bool avoidCaching
	 */
	this.setAvoidCaching = function(avoidCaching){
	  this._avoidCaching = avoidCaching;
	}
	
	/**
	 * Callback for state-change of the XMLHttpRequest-Object. Here the response
	 * will be handled.
	 *
	 * @param HTMLNode outputNode The HTML-node to which the output of the ajax-
	 *                            response will be written.
	 */
	this.triggered = function(outputNode){
	  // if the readyState code is 4 (Completed)
	  // and http status is 200 (OK) we go ahead and get the responseText
	  // other readyState codes:
	  // 0=Uninitialised 1=Loading 2=Loaded 3=Interactive 4=Completed
	  if ((this._xmlhttp.readyState == 4) && (this._xmlhttp.status == 200)) {
      // xmlhttp.responseText object contains the response.
	    if (this.hasCallback()){
	      responseText = this._xmlhttp.responseText;
	      // Call the given callback with the ajax-response as parameter
	      window.setTimeout(this._callback + "(responseText)", 0);
	    }
	    if (this.hasOutputNode()){
	      // Fill the output-node with the content of the response
	      outputNode.innerHTML = this._xmlhttp.responseText;
	    }
	  }
	}
}
