// ===================================================================
// Author: Matt Kruse <matt@ajaxtoolbox.com>
// WWW: http://www.AjaxToolbox.com/
//
// NOTICE: You may use this code for any purpose, commercial or
// private, without any further permission from the author. You may
// remove this notice from your final code if you wish, however it is
// appreciated by the author if at least my web site address is kept.
//
// You may *NOT* re-distribute this code in any way except through its
// use. That means, you can include it in your product, or your web
// site, or any other form where the code is actually being used. You
// may not put the plain javascript up on your site for download or
// include it in your javascript libraries for download. 
// If you wish to share this code with others, please just point them
// to the URL instead.
// Please DO NOT link directly to my .js files from your site. Copy
// the files to your server and use them there. Thank you.
// ===================================================================

/**
* The AjaxRequest class is a wrapper for the XMLHttpRequest objects which 
* are available in most modern browsers. It simplifies the interfaces for
* making Ajax requests, adds commonly-used convenience methods, and makes 
* the process of handling state changes more intuitive.
* An object may be instantiated and used, or the Class methods may be used 
* which internally create an AjaxRequest object.
*/
function AjaxRequest() {
    var req = new Object();

    // -------------------
    // Instance properties
    // -------------------

    /**
    * Timeout period (in ms) until an async request will be aborted, and
    * the onTimeout function will be called
    */
    req.timeout = null;

    /**
    *	Since some browsers cache GET requests via XMLHttpRequest, an
    * additional parameter called AjaxRequestUniqueId will be added to
    * the request URI with a unique numeric value appended so that the requested
    * URL will not be cached.
    */
    req.generateUniqueUrl = true;

    /**
    * The url that the request will be made to, which defaults to the current 
    * url of the window
    */
    req.url = window.location.href;

    /**
    * The method of the request, either GET (default), POST, or HEAD
    */
    req.method = "GET";

    /**
    * Whether or not the request will be asynchronous. In general, synchronous 
    * requests should not be used so this should rarely be changed from true
    */
    req.async = true;

    /**
    * The username used to access the URL
    */
    req.username = null;

    /**
    * The password used to access the URL
    */
    req.password = null;

    /**
    * The parameters is an object holding name/value pairs which will be 
    * added to the url for a GET request or the request content for a POST request
    */
    req.parameters = new Object();

    /**
    * The sequential index number of this request, updated internally
    */
    req.requestIndex = AjaxRequest.numAjaxRequests++;

    /**
    * Indicates whether a response has been received yet from the server
    */
    req.responseReceived = false;

    /**
    * The name of the group that this request belongs to, for activity 
    * monitoring purposes
    */
    req.groupName = null;

    /**
    * The query string to be added to the end of a GET request, in proper 
    * URIEncoded format
    */
    req.queryString = "";

    /**
    * After a response has been received, this will hold the text contents of 
    * the response - even in case of error
    */
    req.responseText = null;

    /**
    * After a response has been received, this will hold the XML content
    */
    req.responseXML = null;

    /**
    * After a response has been received, this will hold the status code of 
    * the response as returned by the server.
    */
    req.status = null;

    /**
    * After a response has been received, this will hold the text description 
    * of the response code
    */
    req.statusText = null;

    /**
    * An internal flag to indicate whether the request has been aborted
    */
    req.aborted = false;

    /**
    * The XMLHttpRequest object used internally
    */
    req.xmlHttpRequest = null;

    // --------------
    // Event handlers
    // --------------

    /**
    * If a timeout period is set, and it is reached before a response is 
    * received, a function reference assigned to onTimeout will be called
    */
    req.onTimeout = null;

    /**
    * A function reference assigned will be called when readyState=1
    */
    req.onLoading = null;

    /**
    * A function reference assigned will be called when readyState=2
    */
    req.onLoaded = null;

    /**
    * A function reference assigned will be called when readyState=3
    */
    req.onInteractive = null;

    /**
    * A function reference assigned will be called when readyState=4
    */
    req.onComplete = null;

    /**
    * A function reference assigned will be called after onComplete, if 
    * the statusCode=200
    */
    req.onSuccess = null;

    /**
    * A function reference assigned will be called after onComplete, if 
    * the statusCode != 200
    */
    req.onError = null;

    /**
    * If this request has a group name, this function reference will be called 
    * and passed the group name if this is the first request in the group to 
    * become active
    */
    req.onGroupBegin = null;

    /**
    * If this request has a group name, and this request is the last request 
    * in the group to complete, this function reference will be called
    */
    req.onGroupEnd = null;

    // Get the XMLHttpRequest object itself
    req.xmlHttpRequest = AjaxRequest.getXmlHttpRequest();
    if (req.xmlHttpRequest == null) { return null; }

    // -------------------------------------------------------
    // Attach the event handlers for the XMLHttpRequest object
    // -------------------------------------------------------
    req.xmlHttpRequest.onreadystatechange =
	function() {
	    if (req == null || req.xmlHttpRequest == null) { return; }
	    if (req.xmlHttpRequest.readyState == 1) { req.onLoadingInternal(req); }
	    if (req.xmlHttpRequest.readyState == 2) { req.onLoadedInternal(req); }
	    if (req.xmlHttpRequest.readyState == 3) { req.onInteractiveInternal(req); }
	    if (req.xmlHttpRequest.readyState == 4) { req.onCompleteInternal(req); }
	};

    // ---------------------------------------------------------------------------
    // Internal event handlers that fire, and in turn fire the user event handlers
    // ---------------------------------------------------------------------------
    // Flags to keep track if each event has been handled, in case of 
    // multiple calls (some browsers may call the onreadystatechange 
    // multiple times for the same state)
    req.onLoadingInternalHandled = false;
    req.onLoadedInternalHandled = false;
    req.onInteractiveInternalHandled = false;
    req.onCompleteInternalHandled = false;
    req.onLoadingInternal =
		function() {
		    if (req.onLoadingInternalHandled) { return; }
		    AjaxRequest.numActiveAjaxRequests++;
		    if (AjaxRequest.numActiveAjaxRequests == 1 && typeof (window['AjaxRequestBegin']) == "function") {
		        AjaxRequestBegin();
		    }
		    if (req.groupName != null) {
		        if (typeof (AjaxRequest.numActiveAjaxGroupRequests[req.groupName]) == "undefined") {
		            AjaxRequest.numActiveAjaxGroupRequests[req.groupName] = 0;
		        }
		        AjaxRequest.numActiveAjaxGroupRequests[req.groupName]++;
		        if (AjaxRequest.numActiveAjaxGroupRequests[req.groupName] == 1 && typeof (req.onGroupBegin) == "function") {
		            req.onGroupBegin(req.groupName);
		        }
		    }
		    if (typeof (req.onLoading) == "function") {
		        req.onLoading(req);
		    }
		    req.onLoadingInternalHandled = true;
		};
    req.onLoadedInternal =
		function() {
		    if (req.onLoadedInternalHandled) { return; }
		    if (typeof (req.onLoaded) == "function") {
		        req.onLoaded(req);
		    }
		    req.onLoadedInternalHandled = true;
		};
    req.onInteractiveInternal =
		function() {
		    if (req.onInteractiveInternalHandled) { return; }
		    if (typeof (req.onInteractive) == "function") {
		        req.onInteractive(req);
		    }
		    req.onInteractiveInternalHandled = true;
		};
    req.onCompleteInternal =
		function() {
		    if (req.onCompleteInternalHandled || req.aborted) { return; }
		    req.onCompleteInternalHandled = true;
		    AjaxRequest.numActiveAjaxRequests--;
		    if (AjaxRequest.numActiveAjaxRequests == 0 && typeof (window['AjaxRequestEnd']) == "function") {
		        AjaxRequestEnd(req.groupName);
		    }
		    if (req.groupName != null) {
		        AjaxRequest.numActiveAjaxGroupRequests[req.groupName]--;
		        if (AjaxRequest.numActiveAjaxGroupRequests[req.groupName] == 0 && typeof (req.onGroupEnd) == "function") {
		            req.onGroupEnd(req.groupName);
		        }
		    }
		    req.responseReceived = true;
		    req.status = req.xmlHttpRequest.status;
		    req.statusText = req.xmlHttpRequest.statusText;
		    req.responseText = req.xmlHttpRequest.responseText;
		    req.responseXML = req.xmlHttpRequest.responseXML;
		    if (typeof (req.onComplete) == "function") {
		        req.onComplete(req);
		    }
		    if (req.xmlHttpRequest.status == 200 && typeof (req.onSuccess) == "function") {
		        req.onSuccess(req);
		    }
		    else if (typeof (req.onError) == "function") {
		        req.onError(req);
		    }

		    // Clean up so IE doesn't leak memory
		    delete req.xmlHttpRequest['onreadystatechange'];
		    req.xmlHttpRequest = null;
		};
    req.onTimeoutInternal =
		function() {
		    if (req != null && req.xmlHttpRequest != null && !req.onCompleteInternalHandled) {
		        req.aborted = true;
		        req.xmlHttpRequest.abort();
		        AjaxRequest.numActiveAjaxRequests--;
		        if (AjaxRequest.numActiveAjaxRequests == 0 && typeof (window['AjaxRequestEnd']) == "function") {
		            AjaxRequestEnd(req.groupName);
		        }
		        if (req.groupName != null) {
		            AjaxRequest.numActiveAjaxGroupRequests[req.groupName]--;
		            if (AjaxRequest.numActiveAjaxGroupRequests[req.groupName] == 0 && typeof (req.onGroupEnd) == "function") {
		                req.onGroupEnd(req.groupName);
		            }
		        }
		        if (typeof (req.onTimeout) == "function") {
		            req.onTimeout(req);
		        }
		        // Opera won't fire onreadystatechange after abort, but other browsers do. 
		        // So we can't rely on the onreadystate function getting called. Clean up here!
		        delete req.xmlHttpRequest['onreadystatechange'];
		        req.xmlHttpRequest = null;
		    }
		};

    // ----------------
    // Instance methods
    // ----------------
    /**
    * The process method is called to actually make the request. It builds the
    * querystring for GET requests (the content for POST requests), sets the
    * appropriate headers if necessary, and calls the 
    * XMLHttpRequest.send() method
    */
    req.process =
		function() {
		    if (req.xmlHttpRequest != null) {
		        // Some logic to get the real request URL
		        if (req.generateUniqueUrl && req.method == "GET") {
		            req.parameters["AjaxRequestUniqueId"] = new Date().getTime() + "" + req.requestIndex;
		        }
		        var content = null; // For POST requests, to hold query string
		        for (var i in req.parameters) {
		            if (req.queryString.length > 0) { req.queryString += "&"; }
		            req.queryString += encodeURIComponent(i) + "=" + encodeURIComponent(req.parameters[i]);
		        }
		        if (req.method == "GET") {
		            if (req.queryString.length > 0) {
		                req.url += ((req.url.indexOf("?") > -1) ? "&" : "?") + req.queryString;
		            }
		        }
		        req.xmlHttpRequest.open(req.method, req.url, req.async, req.username, req.password);
		        if (req.method == "POST") {
		            if (typeof (req.xmlHttpRequest.setRequestHeader) != "undefined") {
		                req.xmlHttpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
		            }
		            content = req.queryString;
		        }
		        if (req.timeout > 0) {
		            setTimeout(req.onTimeoutInternal, req.timeout);
		        }
		        //var test = 'finished';
		        try {
		            //alert('sending');
		            req.xmlHttpRequest.send(content);
		            //alert('sent');
		        } catch (ex) {
		            test = ex;
		        }
		        //alert(test);
		    }
		};

    /**
    * An internal function to handle an Object argument, which may contain
    * either AjaxRequest field values or parameter name/values
    */
    req.handleArguments =
		function(args) {
		    for (var i in args) {
		        // If the AjaxRequest object doesn't have a property which was passed, treat it as a url parameter
		        if (typeof (req[i]) == "undefined") {
		            req.parameters[i] = args[i];
		        }
		        else {
		            req[i] = args[i];
		        }
		    }
		};

    /**
    * Returns the results of XMLHttpRequest.getAllResponseHeaders().
    * Only available after a response has been returned
    */
    req.getAllResponseHeaders =
		function() {
		    if (req.xmlHttpRequest != null) {
		        if (req.responseReceived) {
		            return req.xmlHttpRequest.getAllResponseHeaders();
		        }
		        alert("Cannot getAllResponseHeaders because a response has not yet been received");
		    }
		};

    /**
    * Returns the the value of a response header as returned by 
    * XMLHttpRequest,getResponseHeader().
    * Only available after a response has been returned
    */
    req.getResponseHeader =
		function(headerName) {
		    if (req.xmlHttpRequest != null) {
		        if (req.responseReceived) {
		            return req.xmlHttpRequest.getResponseHeader(headerName);
		        }
		        alert("Cannot getResponseHeader because a response has not yet been received");
		    }
		};

    return req;
}

// ---------------------------------------
// Static methods of the AjaxRequest class
// ---------------------------------------

/**
* Returns an XMLHttpRequest object, either as a core object or an ActiveX 
* implementation. If an object cannot be instantiated, it will return null;
*/
AjaxRequest.getXmlHttpRequest = function() {
    if (window.XMLHttpRequest) {
        return new XMLHttpRequest();
    }
    else if (window.ActiveXObject) {
        // Based on http://jibbering.com/2002/4/httprequest.html
        /*@cc_on@*/
        /*@if (@_jscript_version >= 5)
        try {
            return new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                return new ActiveXObject("Microsoft.XMLHTTP");
            } catch (E) {
                return null;
            }
        }
        @end@*/
    }
    else {
        return null;
    }
};

/**
* See if any request is active in the background
*/
AjaxRequest.isActive = function() {
    return (AjaxRequest.numActiveAjaxRequests > 0);
};

/**
* Make a GET request. Pass an object containing parameters and arguments as 
* the second argument.
* These areguments may be either AjaxRequest properties to set on the request 
* object or name/values to set in the request querystring.
*/
AjaxRequest.get = function(args) {
    AjaxRequest.doRequest("GET", args);
};

/**
* Make a POST request. Pass an object containing parameters and arguments as 
* the second argument.
* These areguments may be either AjaxRequest properties to set on the request 
* object or name/values to set in the request querystring.
*/
AjaxRequest.post = function(args) {
    AjaxRequest.doRequest("POST", args);
};

/**
* The internal method used by the .get() and .post() methods
*/
AjaxRequest.doRequest = function(method, args) {
    if (typeof (args) != "undefined" && args != null) {
        var myRequest = new AjaxRequest();
        myRequest.method = method;
        myRequest.handleArguments(args);
        myRequest.process();
    }
};

/**
* Submit a form. The requested URL will be the form's ACTION, and the request 
* method will be the form's METHOD.
* Returns true if the submittal was handled successfully, else false so it 
* can easily be used with an onSubmit event for a form, and fallback to 
* submitting the form normally.
*/
AjaxRequest.submit = function(theform, args) {
    var myRequest = new AjaxRequest();
    if (myRequest == null) { return false; }
    var serializedForm = AjaxRequest.serializeForm(theform);
    myRequest.method = theform.method.toUpperCase();
    myRequest.url = theform.action;
    myRequest.handleArguments(args);
    myRequest.queryString = serializedForm;
    myRequest.process();
    return true;
};

/**
* Serialize a form into a format which can be sent as a GET string or a POST 
* content.It correctly ignores disabled fields, maintains order of the fields 
* as in the elements[] array. The 'file' input type is not supported, as 
* its content is not available to javascript. This method is used internally
* by the submit class method.
*/
AjaxRequest.serializeForm = function(theform) {
    var els = theform.elements;
    var len = els.length;
    var queryString = "";
    this.addField =
		function(name, value) {
		    if (queryString.length > 0) {
		        queryString += "&";
		    }
		    queryString += encodeURIComponent(name) + "=" + encodeURIComponent(value);
		};
    for (var i = 0; i < len; i++) {
        var el = els[i];
        if (!el.disabled) {
            switch (el.type) {
                case 'text': case 'password': case 'hidden': case 'textarea':
                    this.addField(el.name, el.value);
                    break;
                case 'select-one':
                    if (el.selectedIndex >= 0) {
                        this.addField(el.name, el.options[el.selectedIndex].value);
                    }
                    break;
                case 'select-multiple':
                    for (var j = 0; j < el.options.length; j++) {
                        if (el.options[j].selected) {
                            this.addField(el.name, el.options[j].value);
                        }
                    }
                    break;
                case 'checkbox': case 'radio':
                    if (el.checked) {
                        this.addField(el.name, el.value);
                    }
                    break;
            }
        }
    }
    return queryString;
};

// -----------------------
// Static Class variables
// -----------------------

/**
* The number of total AjaxRequest objects currently active and running
*/
AjaxRequest.numActiveAjaxRequests = 0;

/**
* An object holding the number of active requests for each group
*/
AjaxRequest.numActiveAjaxGroupRequests = new Object();

/**
* The total number of AjaxRequest objects instantiated
*/
AjaxRequest.numAjaxRequests = 0;

function showHtml(table, elementname, clearcontent) {
    var url = 'table.aspx?t=' + table
    getContent(url, elementname, clearcontent);
}
var gcCache = new Object();
var msgTest = "asdf";
function getContent(url, element, clearcontent, startmsg, latestonly) {
    //alert(element + ":" + url);

    if (clearcontent) {
        //if clearing content, don't append the text.
        try {
            if (latestonly && startmsg && document.getElementById(element).innerHTML == msgTest) {
                gcCache[element] = url;
                return;
            }
            if (startmsg) {
                document.getElementById(element).innerHTML = startmsg;
                msgTest = document.getElementById(element).innerHTML;
            }
        }
        catch (e) { }
        AjaxRequest.get(
			{
			    'url': url
				, 'onSuccess': function(req) {
				    if (element)
				        try {
				        if (document.getElementById(element))
				            document.getElementById(element).innerHTML = req.responseText;
				    }
				    catch (e) {
				        document.getElementById(element).innerHTML = '';
				        var t = document.createElement('div');
				        t.innerHTML = req.responseText;
				        document.getElementById(element).appendChild(t);
				    } finally {
				        if (gcCache[element] != null) {
				            var tempUrl = gcCache[element];
				            gcCache[element] = null;
				            getContent(tempUrl, element, true, startmsg, latestonly);
				        }
				    }
				}
				, 'onError': function(req) { }
			}
		);
        return;
    }

    AjaxRequest.get(
		{
		    'url': url
			, 'async': true
			, 'onSuccess': function(req) {
			    if (element)
			        try {
			        if (document.getElementById(element))
			            document.getElementById(element).innerHTML += req.responseText;
			    }
			    catch (e) {
			        var t = document.createElement('div');
			        t.innerHTML = req.responseText;
			        document.getElementById(element).appendChild(t);
			    }
			}
			, 'onError': function(req) { }
		}
	);
}
function getUrlString(url) {
    var xmlHttp;
    try {

        // Firefox, Opera 8.0+, Safari
        xmlHttp = new XMLHttpRequest();
        //alert(xmlHttp)
    }

    catch (e) {
        // Internet Explorer
        try {
            xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
            alert(xmlHttp)
        }
        catch (e) {
            try {
                xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
                alert(xmlHttp)
            }
            catch (e) {
                alert("Your browser does not support AJAX!");
                return false;
            }
        }
    }

    var arui = new Date();
    xmlHttp.open("GET", url + '&AjaxRequestUniqueId=' + arui.getTime(), false);
    xmlHttp.send(null);
    return xmlHttp.responseText;

}



function isNumeric(sText) {
    var ValidChars = "-0123456789.";
    var IsNumber = true;
    var Char;


    for (i = 0; i < sText.length && IsNumber == true; i++) {
        Char = sText.charAt(i);
        if (ValidChars.indexOf(Char) == -1) {
            IsNumber = false;
        }
    }
    return IsNumber;

}



function updateQuantity(id, q) {
    if (q == '') {
        getContent('default.aspx?t=ShoppingCart&id=' + id + '&o=4');
    } else if (isNumeric(q) && isNumeric(id)) {
        getContent('savedesign.aspx?t=ShoppingCart&f=quantity&v=' + q + '&id=' + id + '&o=3');
    }
}
function clearApplyMsg(i) {
    var el = document.getElementById('savemsg');
    if (el) {
        if (el.innerHTML == 'Changes applied successfully.') {
            el.style.color = 'rgb(' + i + ',' + i + ',' + i + ')';
            if (i < 255) {
                i = i + 5;
                timer = setTimeout('clearApplyMsg(' + i + ')', 10);
            } else {
                el.innerHTML = '';
                el.style.color = 'black';
            }
        } else {
            timer = setTimeout('clearApplyMsg(' + i + ')', 1000);
        }
    }
}

var timer;
function clearT() {
    el = document.getElementById('savemsg');
    if (el) {
        document.getElementById('savemsg').style.color = 'black';
        clearTimeout(timer);
    }
}

function setInnerHtml(elementId, content) {
    var el = null;
    if (elementId) { el = document.getElementById(elementId); }
    if (el) {
        try {
            el.innerHTML = content;
        } catch (e) {
            el.innerHTML = '';
            var t = document.createElement('div');
            t.innerHTML = content;
            el.appendChild(t);
        }
    }
}
