
function Delegate(func, object)
{
    this.func = func;
    this.object = object;
    var me = this;
        
    this.invoke = function()
    {
        if(object == null)
            me.func();
        else
            me.func.call(object);
    }
}

//AsyncRequest class
//should implement call back function arrays for all states of XMLHttpRequest object
//should identify problems with XMLHttpRequest object and should translate them to js error throws
//should be able to specify an array of AsyncRequests that this request depends on re: mutex
//should an AsyncRequest be invoked that relies on an uncompleted AsyncRequest(s) it will regester itself to be called
//  when and if that request succesfully completes

function AsyncRequest(type, url)
{
    this.type = type;
    this.url = url;
    
    /*@cc_on @if (@_win32 && @_jscript_version >= 5) if (!window.XMLHttpRequest)
    window.XMLHttpRequest = function() { return new ActiveXObject('Microsoft.XMLHTTP') }
    @end @*/
    
    this.request = new XMLHttpRequest();
    this.request.open(this.type,this.url,true,"qi_request","quickinsert.com");
	
	this.userData = null;
    
    this.isComplete = false;
    
    this.uninitialized = new Array();
    this.loading = new Array();
    this.loaded = new Array();
    this.interactive = new Array();
    this.complete = new Array();
    this.error = new Array();
    this.dependsOn = new Array();

	this.parseXML = function()
	{
		// code for IE
		if (window.ActiveXObject)
		{
			var doc=new ActiveXObject("Microsoft.XMLDOM");
			doc.async="false";
			doc.loadXML(this.request.responseText);
		}
		// code for Mozilla, Firefox, Opera, etc.
		else
		{
			var parser=new DOMParser();
			var doc=parser.parseFromString(this.request.responseText,"text/xml");
		}

		this.xml=doc.documentElement;
	}
    
    this.readyStateChanged = function()
    {
        switch(this.request.readyState)
        {
        case 0:
            //uninitialized
            for(var i=0;i<this.uninitialized.length;i++)
                this.uninitialized[i].invoke();
            break;
        case 1:
            //loading
            for(var i=0;i<this.loading.length;i++)
                this.loading[i].invoke();
            break;
        case 2:
            //loaded
            for(var i=0;i<this.loaded.length;i++)
                this.loaded[i].invoke();
            break;
        case 3:
            //interactive
            for(var i=0;i<this.interactive.length;i++)
                this.interactive[i].invoke();
            break;
        case 4:
            //complete
            if(this.request.status == 200)
            {
                this.isComplete = true;
				this.parseXML();
                for(var i=0;i<this.complete.length;i++)
                    this.complete[i].invoke();
            }
            else
            {
                //throw error
                for(var i=0;i<this.error.length;i++)
                    this.error[i].invoke();
            }
            break;    
        }
    }
    
    var delegate = new Delegate(this.readyStateChanged, this);
    this.request.onreadystatechange = delegate.invoke;
    
    this.send = function()
    {
        for(var i=0;i<this.dependsOn.length;i++)
        {
            if(!this.dependsOn[i].isComplete)
            {
                //need to make sure function isn't already on list
                this.dependsOn[i].complete.push(new Delegate(this.send,this));
                return;
            }
        }
        this.request.send(null);
    }
}

function loadingEnd () {
			document.getElementById("loadingZone").style.display = 'none';
			document.getElementById("loadingZone").innerHTML = '';
}

function loadingStart () {
			document.getElementById("loadingZone").style.display = 'block';
			document.getElementById("loadingZone").innerHTML = "<span class='loadingZoneRed'>Loading ...</span>";
}