
/* Copyright 2010 The Firebox.
 * All rights reserved.
 * Written by Nicholas De Cicco.
 */

var debug = false;

function DocumentRequest(documentName, actionOnLoad)
{
	this.isLocal = document.domain == "" ? true : false;
	this.documentName = documentName;
	this.actionOnLoad = actionOnLoad;

	this.fetchDocument = function() {
		var request; /* the XMLHttpRequest */

		/* Iterates over a list of ActiveX program IDs (strings), attempting
		 * to create an ActiveX object with each ID in turn, starting with the
		 * first, returning the newly created object on success. Returns null
		 * on failure.
		 */
		var createActiveXObject = function(progIDs) {
			for (var i = 0; i < progIDs.length; i++) {
				try { return new ActiveXObject(progIDs[i]); }
				catch (e) {}
			}
			return null;
		};

		/* We can also test for `window.XMLHttpRequest', to determine
		 * what browser is running (and thus what method to use), but
		 * instead we just try to see if XMLHttpRequest is defined; if
		 * not, we define an anonymous function to return the highest
		 * version of MSXML on the system. See 'http://blogs.msdn.com/b/
		 * xmlteam/ archive/2006/10/23/using-the-right-version-of-msxml-
		 * in-internet-explorer.aspx' for more info. Also note that we
		 * use the `MSXML2' namespace instead of `Microsoft'; this is
		 * because the Microsoft namespace is actually older and is only
		 * implemented in MSXML3 for legacy support. Again, see the
		 * above link for more information.
		 *
		 * Also note that (supposedly) local file requests only work with
		 * MSXML3.XMLHTTP; therefore, if we detect that we're running IE
		 * and the file is local, we'll use that.
		 */
		if (typeof(XMLHttpRequest) == "undefined" ||
			(this.isLocal && typeof(ActiveXObject) != "undefined")) {
			XMLHttpRequest = function () {
				var progIDs = [
					"Msxml2.XMLHTTP.6.0", /* MSXML 6.0 */
					"Msxml2.XMLHTTP.3.0", /* MSXML 3.0 */
					"Msxml2.XMLHTTP"      /* should default to MSXML 3.0 */
				];
				return createActiveXObject(progIDs);
				return null;
			}
		}

		/* For IE7+, Firefox, Chrome, Opera, and Safari, the
		 * XMLHttpRequest object should exist and so the above code will
		 * not execute; otherwise, an function will be created to create
		 * the correct MSXML ActiveX object.
		 */
		request = new XMLHttpRequest();

		/* Some versions of some Mozilla-based browsers won't work
		 * properly unless the response from the server has the XML
		 * mime type header (text/xml); therefore, we override the
		 * mime type just to be safe. Internet Explorer has a similar
		 * problem with local files (in that they have no content type),
		 * but that's a problem that is solved differently (see below).
		 */
		if (!window.ActiveXObject) request.overrideMimeType("text/xml");

		/* Abort if we've failed to create the request.
		 */
		if (!request) {
			logError("Failed to create XML HTTP request!");
			return;
		}

		/* Specify the request.
		 */
		request.open("GET", documentName, true);

		/* so that this.isLocal can be accessed in request.onreadystatechange */
		var isLocal = this.isLocal;

		/* Create a method to handle changes in the request's state;
		 * here, the method we create only responds when the request has
		 * been completed and the document fully loaded. It does so by
		 * performing the `actionOnLoad' method specified during
		 * construction.
		 */
		request.onreadystatechange = function (theEvent) {

			/* Wait for the request to finish */
			if (request.readyState == 4) {

				/* Check to see that the request went OK; HTTP indicates
				 * this with a status code of 200, whereas successful
				 * requests for local files will yield 0.
				 */
				if ((!isLocal && request.status == 200) ||
					(isLocal && request.status == 0)) {

					/* Mozilla (and perhaps other browsers?) will not create
					 * a responseXML object upon failure; Internet Explorer
					 * will, however, which we check for later.
					 */
					if (request.responseXML == null) {
						logError("XMLHttpRequest failed");
						return;
					}

					/* Internet Explorer will create a responseXML object
					 * regardless of status, so we have to check for some
					 * node in the responseXML object instead.
					 */
					if (request.responseXML.documentElement == null) {

						/* If the file is not local, the HTTP request failed.
						 */
						if (!isLocal) {
							logError("XMLHttpRequest failed");
							return;
						}

						/* Local requests always fail with Internet Explorer
						 * and XMLHttpRequest, but not entirely; that is, we just
						 * have to parse the XML, so we try Microsoft.XMLDOM.
						 */
						var progIDs = [
							"Msxml2.DOMDocument.6.0", /* MSXML 6.0 */
							"Msxml2.DOMDocument.3.0", /* MSXML 3.0 */
							"Microsoft.XMLDOM"        /* really, really old */
						];
						var xmlDocument = createActiveXObject(progIDs);
						if (!xmlDocument) {
							logError("Failed to parse XML");
							return;
						}

						xmlDocument.async = false;
						xmlDocument.loadXML(request.responseText);
						if (xmlDocument.documentElement != null) {
							if (debug) logError(request.responseText);
							actionOnLoad(xmlDocument.documentElement);
							return;
						} else {
							logError("XMLHttpRequest failed");
							return;
						}
					}

					if (debug) logError(request.responseText);
					actionOnLoad(request.responseXML);
				}
			}
		};

		/* Actually request the document.
		 */
		request.send();
	};

	/* Fetch the document on "construction".
	 */
	this.fetchDocument();
}

