/**
 * XML Request handling, with support for multiple connections
 * (c) 2006 IVinity
 * http://www.ivinity.nl/
 * Tested with:
 *  IE 6 (win)
 *  Opera 8.5 (win / mac)
 *  Firefox 1.5 (win / mac)
 *  Safari 1.3 (mac)
 */
 
// global request and XML document objects
var http_request;

function XMLRequestHandler(method, url, asynch, data) {
	if (window.XMLHttpRequest) { // Mozilla, Safari,...
		this.xmlRequest = new XMLHttpRequest();
	} else if (window.ActiveXObject) { // IE
		this.xmlRequest = new ActiveXObject("Microsoft.XMLHTTP");
	}
	var self = this;
	this.handle = processReqChange;
	this.requestID = requestID++;
	
	this.xmlRequest.onreadystatechange = function() { self.handle(); }
	this.xmlRequest.open(method, url, asynch);
	if (method == "POST") {
		this.xmlRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
	}
	this.xmlRequest.send(data);
}

var requests = new Array();
var requestID = 1;

function loadXMLDoc(url) {
	var index = requests.length;
	requests[index] = new XMLRequestHandler('GET', url, true, null);	
}

function loadXMLDocPost(url, postdata) {
	var index = requests.length;
	requests[index] = new XMLRequestHandler('POST', url, true, postdata);	
}

// handle onreadystatechange event of req object
function processReqChange() {
    // only if req shows "loaded"
    if (this.xmlRequest.readyState == 4) {
        // only if "OK"
        if (this.xmlRequest.status == 200) {
					handleXMLupdate(this.xmlRequest);
					// cleanup
					for (i = 0; i < requests.length; i++) {
						if (requests[i].requestID == this.requestID) {
							requests.splice(i, 1);							
						}
					}					
        } else {
           alert("There was a problem retrieving the XML data:\n" +
               this.xmlRequest.statusText);
           handleXMLerror(this.xmlRequest);
        }
    }
}

// retrieve text of an XML document element, including
// elements using namespaces
function getElementTextNS(prefix, local, parentElem, index) {
    var result = "";
    if (prefix && isIE) {
        // IE/Windows way of handling namespaces
        result = parentElem.getElementsByTagName(prefix + ":" + local)[index];
    } else {
        // the namespace versions of this method
        // (getElementsByTagNameNS()) operate
        // differently in Safari and Mozilla, but both
        // return value with just local name, provided
        // there aren't conflicts with non-namespace element
        // names
        result = parentElem.getElementsByTagName(local)[index];
    }
    if (result) {
        // get text, accounting for possible
        // whitespace (carriage return) text nodes
        if (result.childNodes.length > 1) {
            return result.childNodes[1].nodeValue;
        } else {
            return result.firstChild.nodeValue;
        }
    } else {
        return "n/a";
    }
}

function UrlData() {
	this.items = new Array();
	this.add = addUrlData;
	this.getString = urlDataString;	
}

function addUrlData(name, value) {
	this.items[this.items.length] = new Array(name, value);
}

function urlDataString() {
	var result = "";
	for (var i = 0; i < this.items.length; i++) {
		result += URLEncode(this.items[i][0]) + "=" + URLEncode(this.items[i][1]);
		if (i < this.items.length -1) result += "&";
	}
	return result;
}

function URLEncode(plaintext) {
	// The Javascript escape and unescape functions do not correspond
	// with what browsers actually do...
	var SAFECHARS = "0123456789" +					// Numeric
		"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +	// Alphabetic
		"abcdefghijklmnopqrstuvwxyz" +
		"-_.!~*'()";					// RFC2396 Mark characters
	var HEX = "0123456789ABCDEF";

	var encoded = "";
	for (var i = 0; i < plaintext.length; i++ ) {
		var ch = plaintext.charAt(i);
		if (ch == " ") encoded += "+";				// x-www-urlencoded, rather than %20
		else if (SAFECHARS.indexOf(ch) != -1) encoded += ch;
		else {
			var charCode = ch.charCodeAt(0);
			if (charCode > 255) {
				alert( "Unicode Character '" + ch
					+ "' cannot be encoded using standard URL encoding.\n" +
					"(URL encoding only supports 8-bit characters.)\n" +
					"A space (+) will be substituted." );
				encoded += "+";
			} else {
				encoded += "%";
				encoded += HEX.charAt((charCode >> 4) & 0xF);
				encoded += HEX.charAt(charCode & 0xF);
			}
		}
	} // for
	return encoded;
}

/*
 * Returns a new XMLHttpRequest object, or false if this browser
 * doesn't support it
 */
function newXMLHttpRequest() {

  var xmlreq = false;

  if (window.XMLHttpRequest) {

    // Create XMLHttpRequest object in non-Microsoft browsers
    xmlreq = new XMLHttpRequest();

  } else if (window.ActiveXObject) {

    // Create XMLHttpRequest via MS ActiveX
    try {
      // Try to create XMLHttpRequest in later versions
      // of Internet Explorer

      xmlreq = new ActiveXObject("Msxml2.XMLHTTP");

    } catch (e1) {

      // Failed to create required ActiveXObject

      try {
        // Try version supported by older versions
        // of Internet Explorer

        xmlreq = new ActiveXObject("Microsoft.XMLHTTP");

      } catch (e2) {

        // Unable to create an XMLHttpRequest with ActiveX
      }
    }
  }

  return xmlreq;
}


/*
 * Returns a function that waits for the specified XMLHttpRequest
 * to complete, then passes its XML response
 * to the given handler function.
 * req - The XMLHttpRequest whose state is changing
 * responseXmlHandler - Function to pass the XML response to
 */
function getReadyStateHandlerBckp(req, responseXmlHandler) {

  // Return an anonymous function that listens to the 
  // XMLHttpRequest instance
  return function () {

    // If the request's status is "complete"
    if (req.readyState == 4) {
      
      // Check that a successful server response was received
      if (req.status == 200) {

        // Pass the XML payload of the response to the 
        // handler function
        responseXmlHandler(req.responseXML);

      } else {

        // An HTTP problem has occurred
        alert("HTTP error: "+req.status);
      }
    }
  }
}

