/* 'this' is used in order to reference the data of the object instance. In the Asynchronous constructor, the data member _xmlhttp is assigned an instance of XMLHttpRequest by using the factory function FactoryXMLHttpRequest. This means that for every instantiated Asynchronous class an instance of XMLHttpRequest is associated. */

function Asynchronous(){
    this._xmlhttp = new FactoryXMLHttpRequest();
}

/* What is the problem that the function below solves. Normally if we were to create multiple requests it would entail creating multiple instances of XMLHttpRequest where each instance was assigned its own function. A more efficient approach is to use object-orientated principles and the 'this' keyword. So here we are solving the instance and callback problem. */

/* Note: 1. the this variable is assigned to the instance variable, 2. the property onreadystatechange is assigned a dynamic anonymous function. In this way the variable instance is available for referencing in the anonymous function. This means that in using the original function - Asynchronous_call - as a callback the reference does not disappear. (The feedback from the server to the Javascript is a callback.) */

/* Note: I've added feedback for user based on firstly 'operatingStatus' - if in case 3 this returns 404 the call is aborted and 'notice of failure' supplied - and secondly, 'operatingStatus' - if in case 4 this does not return 200 the call is aborted and 'notice of failure' supplied.  */

function Asynchronous_call(callType,url,divId) {
    var instance = this;
    var date = new Date();
    var timestamp = date.getTime();
    url=url+'?time='+timestamp;
    if (callType == 'GET'){
    }
    this._xmlhttp.open(callType,url,true);
    if (callType == 'POST'){
	//Send the proper header infomation along with the request
	this._xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	this._xmlhttp.setRequestHeader("Connection", "close");
	this._xmlhttp.setRequestHeader('Cache-Control: no-cache');
    }
    this._xmlhttp.onreadystatechange = function() {
	switch(instance._xmlhttp.readyState) {
	case 1:	
		instance.loading();
		break;
	case 2:
		instance.loaded();
		break;
	case 3:
		instance.interactive(instance._xmlhttp.status);
	        var operatingStatus = instance._xmlhttp.status;
	        if (operatingStatus == 404){
		    instance._xmlhttp.abort();
		    noticeOfFailure(operatingStatus);
	        }
		else {
	        startProgressIndicator();
		}
		break;
	case 4:
	instance.complete(instance._xmlhttp.status, instance._xmlhttp.statusText, instance._xmlhttp.responseText, instance._xmlhttp.responseXML, divId);
	        var operatingStatus = instance._xmlhttp.status;
		var call = instance._xmlhttp;
	        alertFailure(operatingStatus, call);
	        stopProgressIndicator();
		break;
	}
    }
    this._xmlhttp.send();
}

/* The methods - loading, loaded, interactive and complete are called whenever the asynchronous request updates its status. In the default case, all the status methods do nothing and are placeholders so that no exceptions are generated. See below. */

function Asynchronous_loading() {
}
function Asynchronous_loaded() {
}
function Asynchronous_interactive(status, statusText) {
}
function Asynchronous_complete(status, statusText, responseText, responseXML, divId) {
}

/* We have declared a class by declaring a function with the name of the class, namely, Asynchronous. The declared function is called a constructor. This class has no methods or properties as yet. Below we use the prototype property to define five default methods. These will be shared by all instances of the type. Stating it another way, below the Asynchronous class is instantiated creating an object with five methods. Note: if the prototype property were not used and the methods were assigned in the constructor, each instance whould have its own copy of a function. */

Asynchronous.prototype.loading = Asynchronous_loading;
Asynchronous.prototype.loaded = Asynchronous_loaded;
Asynchronous.prototype.interactive = Asynchronous_interactive;
Asynchronous.prototype.complete = Asynchronous_complete;
Asynchronous.prototype.call = Asynchronous_call;

/* Now this needs implementing in our web page. To do this the Asynchronous property 'complete' is assigned the functions AsyncUpdateEvent and AsyncUpdateEvent2 and so on. 

In the page's javascript:

var asynchronous = new Asynchronous();
asynchronous.complete = AsyncUpdateEvent;
var asynchronous2 = new Asynchronous();
asynchronous2.complete = AsyncUpdateEvent2;

function AsyncUpdateEvent(status, statusText, responseText, responseXML) {
document.getElementById('result').innerHTML = responseXML; (for example)
and more... ;
}
function AsyncUpdateEvent2 (status, statusText, responseText, responseXML) {
document.getElementById('httpstatus').innerHTML = statusText; (for example)
and more... ;
}

In the HTML code:

<button onclick="asynchronous.call('/books/mystudy')">Button</button> (for example)
<button onclick="asynchronous2.call('/books/mystudy2')">Button</button> (for example)

*/
