/*
Copyright 2005  Vitaliy Shevchuk (shevit@users.sourceforge.net)

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

*/



function AjaxAnywhere() {

    this.id = AjaxAnywhere.defaultInstanceName;
    this.formName = null;
    this.notSupported = false;
    this.delayBeforeContentUpdate = true;
    this.delayInMillis = 100;
    this.callbackExecuted = true;

    if (window.XMLHttpRequest) {
        this.req = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        try {
            this.req = new ActiveXObject("Msxml2.XMLHTTP");
        } catch(e) {
            try {
                this.req = new ActiveXObject("Microsoft.XMLHTTP");
            } catch(e1) {
                this.notSupported = true;
                /* XMLHTTPRequest not supported */
            }
        }
    }

    if (this.req == null || typeof this.req == "undefined")
        this.notSupported = true;
}

AjaxAnywhere.defaultInstanceName = "default";

AjaxAnywhere.ASYNCH_KEY = "automated.test.session=false";
AjaxAnywhere.SYNCH_KEY = "automated.test.session=true";


/**




 */
AjaxAnywhere.parseQueryString = function(){
    if (location.href.indexOf(AjaxAnywhere.ASYNCH_KEY)!=-1)
        document.cookie = AjaxAnywhere.ASYNCH_KEY;
    else if (location.href.indexOf(AjaxAnywhere.SYNCH_KEY)!=-1)
        document.cookie = AjaxAnywhere.SYNCH_KEY;
}
AjaxAnywhere.parseQueryString();

/**


 */
AjaxAnywhere.prototype.isAsynch = function (){
    return document.cookie.indexOf(AjaxAnywhere.SYNCH_KEY)==-1;
}

/**

 */
AjaxAnywhere.prototype.substitutedSubmitButtons = new Array();
AjaxAnywhere.prototype.substitutedSubmitButtonsInfo = new Object();

/**

 */
AjaxAnywhere.prototype.findForm = function () {
    var form;
    if (this.formName != null)
        form = document.forms[this.formName];
    else if (document.forms.length > 0)
        form = document.forms[0];

    if (typeof form != "object")
        alert("AjaxAnywhere error: Form with name [" + this.formName + "] not found");
    return form;
}


/**

 */
AjaxAnywhere.prototype.bindById = function () {
    var key = "AjaxAnywhere." + this.id;
    window[key] = this;
}

/**

 */
AjaxAnywhere.findInstance = function(id) {
    var key = "AjaxAnywhere." + id;
    return window[key];
}

/**


 */
AjaxAnywhere.prototype.submitAJAX = function(additionalPostData, submitButton) {


    if(!this.waitForRequestCompleted()) return;

    if (this.notSupported)
        return this.onSubmitAjaxNotSupported(additionalPostData, submitButton);

    if (additionalPostData == null || typeof additionalPostData == "undefined")
        additionalPostData = "";

    this.bindById();

    var form = this.findForm();

    var actionAttrNode = form.attributes["action"];
    var url = actionAttrNode == null?null:actionAttrNode.nodeValue;
    if ((url == null) || (url == ""))
        url = location.href;

    var pos = url.indexOf("#");
        if (pos!=-1)
            url = url.substring(0,pos);
        if ((url == null) || (url == ""))
            url = location.href;
        pos = url.indexOf("#");
        if (pos!=-1)
            url = url.substring(0,pos);

    var zones = this.getZonesToReload(url, submitButton);

    if (zones == null) {

        this.submitOld(form,submitButton)
        return;
    }

    this.dropPreviousRequest();

    this.req.open("POST", url, this.isAsynch());

    this.req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");

    var postData = this.preparePostData(submitButton);


    if (zones != "")
        postData = 'aazones=' + encodeURIComponent(zones) + "&" + postData; // + "&" + additionalPostData;


    if(additionalPostData!="") postData += "&" + additionalPostData;


    this.sendPreparedRequest(postData);

}

/**





 */
AjaxAnywhere.prototype.waitForRequestCompleted = function()
{
	if(!this.callbackExecuted)
	{
		for(var i=0; i<20 && !this.callbackExecuted; i++)
		{
			delay(100);
	    }
	    
	    if(!this.callbackExecuted) return false;
	}
	return true;
}

/**

 */
AjaxAnywhere.prototype.getAJAX = function(url, zonesToRefresh) {


	if(!this.waitForRequestCompleted()) return;

    if (this.notSupported)
        return this.onGetAjaxNotSupported(url);

    this.bindById();

    if (zonesToRefresh == null || typeof zonesToRefresh == "undefined")
        zonesToRefresh = "";
    var urlDependentZones = this.getZonesToReload(url);
    if (urlDependentZones == null) {
        location.href = url;
        return;
    }

    if (urlDependentZones.length != 0)
        zonesToRefresh += "," + urlDependentZones;

    this.dropPreviousRequest();

    url += (url.indexOf("?") != -1) ? "&" : "?";

    url += "aaxmlrequest=true&aa_rand=" + Math.random();


    if (zonesToRefresh != null && zonesToRefresh != "")
        url += '&aazones=' + encodeURIComponent(zonesToRefresh);

    this.req.open("GET", url, this.isAsynch());

    this.sendPreparedRequest("");
}

/**

 */
AjaxAnywhere.prototype.sendPreparedRequest = function (postData) {
    this.req.setRequestHeader("Accept", "text/xml");

    var callbackKey = this.id + "_callbackFunction";
    if (typeof window[callbackKey] == "undefined")
        window[callbackKey] = new Function("AjaxAnywhere.findInstance(\"" + this.id + "\").callback(); ");
    this.req.onreadystatechange = window[callbackKey];

    this.showLoadingMessage();

    this.callbackExecuted = false;

    this.req.send(postData);

    this.onRequestSent();

    if ((!this.isAsynch()) && (!this.callbackExecuted )){
        window[callbackKey](); // look like firefox does not execute the callback for synch xmlhttprequest call.
    }

}

/**

 */
AjaxAnywhere.prototype.dropPreviousRequest = function() {
    if (this.req.readyState != 0 && this.req.readyState != 4) {

        this.req.abort();
        this.handlePrevousRequestAborted();
    }
}

/**


 */
AjaxAnywhere.prototype.preparePostData = function(submitButton) {
    var form = this.findForm();
    var result = "aaxmlrequest=true"; // !MODIFIED var result = "&aaxmlrequest=true";
    for (var i = 0; i < form.elements.length; i++) {
        var el = form.elements[i];
        if(el.name=="") continue; // !MODIFIED ignore unnamed form elements
        if (el.tagName.toLowerCase() == "select") {
            for (var j = 0; j < el.options.length; j++) {
                var op = el.options[j];
                if (op.selected)
                    result += "&" + encodeURIComponent(el.name) + "=" + encodeURIComponent(op.value);
            }
        } else if (el.tagName.toLowerCase() == "textarea") {
            result += "&" + encodeURIComponent(el.name) + "=" + encodeURIComponent(el.value);
        } else if (el.tagName.toLowerCase() == "input") {
            if (el.type.toLowerCase() == "checkbox" || el.type.toLowerCase() == "radio") {
                if (el.checked)
                    result += "&" + encodeURIComponent(el.name) + "=" + encodeURIComponent(el.value);
            } else if (el.type.toLowerCase() == "submit") {
                if (el == submitButton) // is "el" the submit button that fired the form submit?
                    result += "&" + encodeURIComponent(el.name) + "=" + encodeURIComponent(el.value);
            } else if (el.type.toLowerCase() != "button") {
                result += "&" + encodeURIComponent(el.name) + "=" + encodeURIComponent(el.value);
            }
        }
    }
    if (typeof submitButton != 'undefined' && submitButton != null && submitButton.type.toLowerCase() == "image") {
        if (submitButton.name == null || submitButton.name == "" || typeof submitButton.name == "undefined")
            result += "&x=1&y=1"; // .x and .y coordinates calculation is not supported.
        else
            result += "&" + encodeURIComponent(submitButton.name) + ".x=1&" +
                      encodeURIComponent(submitButton.name) + ".y=1";
    }
    return result;
}

/**


 */
function delay(millis) {
    date = new Date();
    var curDate = null;
    do {
        curDate = new Date();
    }
    while (curDate - date < millis);
}

/**

 */
AjaxAnywhere.prototype.handleWrongContentType = function() 
{
	alert("AjaxAnywhere error : content-type in not text/xml : [" + this.req.getResponseHeader('content-type') + "]");
}

/**

 */
AjaxAnywhere.prototype.callback = function() {

    if (this.req.readyState == 4) {
        this.callbackExecuted = true;

        this.onBeforeResponseProcessing();
        this.hideLoadingMessage();

        if (this.req.status == 200) {

            if (this.req.getResponseHeader('content-type').toLowerCase().substring(0, 8) != 'text/xml') {
                this.handleWrongContentType();
                return;
            }

            var docs = this.req.responseXML.getElementsByTagName("document");
            var redirects = this.req.responseXML.getElementsByTagName("redirect");
            var zones = this.req.responseXML.getElementsByTagName("zone");
            var exceptions = this.req.responseXML.getElementsByTagName("exception");
            var scripts = this.req.responseXML.getElementsByTagName("script");
            var images = this.req.responseXML.getElementsByTagName("image");

            if (redirects.length != 0) {
                var newURL = redirects[0].firstChild.data;
                location.href = newURL;
            }
            if (docs.length != 0) {
                var newContent = docs[0].firstChild.data;


                delete this.req;

                document.close();
                document.write(newContent);
                document.close();
            }

            if (images.length != 0) {
                var preLoad = new Array(images.length);
                for (var i = 0; i < images.length; i++) {
                    var img = images[i].firstChild;
                    if (img != null) {
                        preLoad[i] = new Image();
                        preLoad[i].src = img.data;
                    }
                }
                if (this.delayBeforeContentUpdate) {
                    delay(this.delayInMillis);
                }
            }

            if (zones.length != 0) {
                for (var i = 0; i < zones.length; i++) {
                    var zoneNode = zones[i];

                    var name = zoneNode.getAttribute("name");
                    var id = zoneNode.getAttribute("id");

                    var html = "";

                    for (var childIndex = 0; childIndex < zoneNode.childNodes.length; childIndex++) {
                        html += zoneNode.childNodes[childIndex].data
                    }

                    var zoneHolder = name!=null?
                                     document.getElementById("aazone." + name):
                                     document.getElementById(id);

                    if (zoneHolder != null && typeof(zoneHolder) != "undefined") {

                        if(this.prepareZoneUpdate(name, zoneHolder, html)) {
                    	    zoneHolder.innerHTML = html;
                        }
                    }

                }
            }
            if (exceptions.length != 0) {
                var e = exceptions[0];
                var type = e.getAttribute("type");
                var stackTrace = e.firstChild.data;
                this.handleException(type, stackTrace);
            }

            if (scripts.length != 0) {
                for (var $$$$i = 0; $$$$i < scripts.length; $$$$i++) {

                    var script = scripts[$$$$i].firstChild;
                    if (script != null) {
                        script = script.data;
                        if (script.indexOf("document.write") != -1) {
                            this.handleException("document.write", "This script contains document.write(), which is not compatible with AjaxAnywhere : \n\n" + script);
                        } else {

                            eval("var aaInstanceId = \""+this.id+"\"; \n"+script);
                        }
                    }
                }

                var globals = this.getGlobalScriptsDeclarationsList(script);
                if (globals != null)
                    for (var i in globals) {
                        var objName = globals[i];
                        try {
                            window[objName] = eval(objName);
                        } catch(e) {
                        }
                    }
            }

        } else {
            if (this.req.status != 0)
                this.handleHttpErrorCode(this.req.status);
        }
        this.restoreSubstitutedSubmitButtons();
        this.onAfterResponseProcessing();

    }


}

/**

 */
AjaxAnywhere.prototype.showLoadingMessage = function() {

    var div = document.getElementById("AA_" + this.id + "_loading_div");
    if (div == null) {
        div = document.createElement("DIV");

        document.body.appendChild(div);
        div.id = "AA_" + this.id + "_loading_div";

        div.innerHTML = "&nbsp;Loading...";
        div.style.position = "absolute";
        div.style.border = "1 solid black";
        div.style.color = "white";
        div.style.backgroundColor = "blue";
        div.style.width = "100px";
        div.style.heigth = "50px";
        div.style.fontFamily = "Arial, Helvetica, sans-serif";
        div.style.fontWeight = "bold";
        div.style.fontSize = "11px";
    }
    div.style.top = document.body.scrollTop + "px";
    div.style.left = (document.body.offsetWidth - 100 - (document.all?20:0)) + "px";

    div.style.display = "";
}

/**

 */
AjaxAnywhere.prototype.hideLoadingMessage = function() {
    var div = document.getElementById("AA_" + this.id + "_loading_div");
    if (div != null)
        div.style.display = "none";

}

/**




 */
AjaxAnywhere.prototype.substituteFormSubmitFunction = function() {
    if (this.notSupported)
        return;

    this.bindById();

    var form = this.findForm();

    form.submit_old = form.submit;
    var code = "var ajax = AjaxAnywhere.findInstance(\"" + this.id + "\"); " +
               "if (typeof ajax !='object' || ! ajax.isFormSubmitByAjax() ) " +
               "ajax.findForm().submit_old();" +
               " else " +
               "ajax.submitAJAX();"
    form.submit = new Function(code);

}

/**

 *





 *


 */
AjaxAnywhere.prototype.substituteSubmitButtonsBehavior = function (keepExistingOnClickHandler, elements) {
    if (this.notSupported)
        return;

    var form = this.findForm();
    if (elements == null || typeof elements == "undefined") { // process all elements
        elements = new Array();
        for (var i = 0; i < form.elements.length; i++) {
            elements.push(form.elements[i]);
        }

        var inputs = document.getElementsByTagName("input");
        for (var i = 0; i < inputs.length; i++) {
            var input = inputs[i];
            if (input.type != null && typeof input.type != "undefined" &&
                input.type.toLowerCase() == "image" && input.form == form) {
                elements.push(input);
            }
        }

        for (var i = 0; i < elements.length; i++) {
            var el = elements[i];
            if (el.tagName.toLowerCase() == "input" && (el.type.toLowerCase() == "submit"
                    || el.type.toLowerCase() == "image")) {
                this.substituteSubmitBehavior(el, keepExistingOnClickHandler);

            }
        }
    } else { //process only specified elements
        for (var i = 0; i < elements.length; i++) {
            var el = elements[i];
            if (el == null)
                continue;

            if (typeof el != "object")
                el = form.elements[el];

            if (typeof el != "undefined") {
                if (el.tagName.toLowerCase() == "input" && (el.type.toLowerCase() == "submit"
                        || el.type.toLowerCase() == "image"))
                    this.substituteSubmitBehavior(el, keepExistingOnClickHandler);
            }
        }
    }

}

/**

 *

 */
AjaxAnywhere.prototype.substituteSubmitBehavior = function (el, keepExistingOnClickHandler) {

    var inList = false;
    for (var i = 0; i < this.substitutedSubmitButtons.length; i++) {
        var btnName = this.substitutedSubmitButtons[i];
        if (btnName == el.name) {
            inList = true;
            break;
        }
    }
    if (!inList)
        this.substitutedSubmitButtons.push(el.name);

    this.substitutedSubmitButtonsInfo[el.name] = keepExistingOnClickHandler;

    if (keepExistingOnClickHandler && (typeof el.onclick != "undefined") && ( el.onclick != null) && ( el.onclick != "")) {
        el.AA_old_onclick = el.onclick;
    }

    el.onclick = handleSubmitButtonClick;
    el.ajaxAnywhereId = this.id;
}

/**
 *

 */
AjaxAnywhere.prototype.restoreSubstitutedSubmitButtons = function() {
    if (this.substitutedSubmitButtons.length == 0)
        return;

    var form = this.findForm();

    for (var i = 0; i < this.substitutedSubmitButtons.length; i++) {
        var name = this.substitutedSubmitButtons[i];
        var el = form.elements[name];
        if (el != null && typeof el != "undefined") {
            if (el.onclick != handleSubmitButtonClick) {
                var keepExistingOnClickHandler = this.substitutedSubmitButtonsInfo[el.name];
                this.substituteSubmitBehavior(el, keepExistingOnClickHandler);
            }
        } else {

            if (name != null && typeof name != "undefined" && name.length != 0) {
                var elements = document.getElementsByName(name);
                if (elements != null)
                    for (var j = 0; j < elements.length; j++) {
                        el = elements[j];
                        if (el != null && typeof el != "undefined"
                                && el.tagName.toLowerCase() == "input"
                                && typeof el.type != "undefined" && el.type.toLowerCase() == "image") {
                            if (el.onclick != handleSubmitButtonClick) {
                                var keepExistingOnClickHandler = this.substitutedSubmitButtonsInfo[el.name];
                                this.substituteSubmitBehavior(el, keepExistingOnClickHandler);
                            }
                        }
                    }
            }
        }
    }
}

/**

 */
function handleSubmitButtonClick(_event) {

    if (typeof this.AA_old_onclick != "undefined") {
        if (false == this.AA_old_onclick(_event))
            return false;
        if (typeof window.event != "undefined")
            if (window.event.returnValue == false)
                return false;
    }
    var onsubmit = this.form.onsubmit;
    if (typeof onsubmit == "function") {
        if (false == onsubmit(_event))
            return false;
        if (typeof window.event != "undefined")
            if (window.event.returnValue == false)
                return false;
    }
    AjaxAnywhere.findInstance(this.ajaxAnywhereId).submitAJAX('', this);

    return false;
}

/**


 */
AjaxAnywhere.prototype.isFormSubmitByAjax = function () {
    return true;
}

/**







 */
AjaxAnywhere.prototype.setDelayBeforeLoad = function (isDelay) {
    this.delayBeforeContentUpdate = isDelay;
}

/**

 */
AjaxAnywhere.prototype.isDelayBeforeLoad = function () {
    return this.delayBeforeContentUpdate;
}

/**


 */
AjaxAnywhere.prototype.setDelayTime = function (delayMillis) {
    this.delayInMillis = delayMillis;
}

/**

 */
AjaxAnywhere.prototype.getDelayTime = function () {
    return this.delayInMillis;
}

/**



 */
AjaxAnywhere.prototype.handleException = function(type, details) {
    alert(details);
}

/**



 */
AjaxAnywhere.prototype.handleHttpErrorCode = function(code) {
    var details = confirm("AjaxAnywhere default error handler. XMLHttpRequest HTTP Error code:" + code + " \n\n Would you like to view the response content in a new window?");
    if (details) {
        var win = window.open("", this.id + "_debug_window");
        if (win != null) {
            win.document.write("<html><body><xmp>" + this.req.responseText);
            win.document.close();
            win.focus();
        } else {
            alert("Please, disable your pop-up blocker for this site first.");
        }
    }
}

/**

 */
AjaxAnywhere.prototype.handlePrevousRequestAborted = function() {

}

/**



 */
AjaxAnywhere.prototype.getGlobalScriptsDeclarationsList = function(script) {
    return null;
}

/**


 *

 *


 *
 */
AjaxAnywhere.prototype.getZonesToReload = function(url, submitButton) {
    return this.getZonesToReaload();

}

/**

 */
AjaxAnywhere.prototype.getZonesToReaload = function(url, submitButton) {
    return "";
}

/**

 */
AjaxAnywhere.prototype.onRequestSent = function () {
};

/**

 */
AjaxAnywhere.prototype.onBeforeResponseProcessing = function () {
};

/**

 */
AjaxAnywhere.prototype.onAfterResponseProcessing = function () {
};

/**


 */
AjaxAnywhere.prototype.onGetAjaxNotSupported = function (url) {
    location.href = url;
    return false;
};

/**


 */
AjaxAnywhere.prototype.onSubmitAjaxNotSupported = function (additionalPostData, submitButton) {
    var form = this.findForm();

    var actionAttrNode = form.attributes["action"];
    var url = actionAttrNode == null?null:actionAttrNode.nodeValue;
    var url_backup = url;
    if (typeof additionalPostData != 'undefined' && additionalPostData != null) {
        url += (url.indexOf("?") != -1) ? "&" : "?";
        url += additionalPostData;
        form.attributes["action"].nodeValue= url;


        form.setAttribute("method", "post");
    }

    this.submitOld(form,submitButton);

    form.attributes["action"].nodeValue= url_backup;
    return false;
};

/**


 */
AjaxAnywhere.prototype.submitOld = function (form,submitButton){
    var submitHolder = null;
    if (submitButton!=null && typeof submitButton!="undefined"){
        submitHolder = document.createElement("input");
        submitHolder.setAttribute("type","hidden");
        submitHolder.setAttribute("name",submitButton.name);
        submitHolder.setAttribute("value",submitButton.value);
        form.appendChild(submitHolder);

    }

    if (typeof form.submit_old == "undefined")
        form.submit();
    else
        form.submit_old();

    if (submitButton!=null ){
        form.removeChild(submitHolder);
    }
}



/**









 */
AjaxAnywhere.prototype.prepareZoneUpdate = function(name, zoneHolder, html) {
	return true;
};


/**



 */
AjaxAnywhere.prototype.excludeZones = function(zones, toExclude) {
	var z=zones.split(",");
	var x=toExclude.split(",");

	for(var i=0; i<z.length; i++) {
		var zone=z[i];


		for(var ix=z.length-1; ix>i; ix--) {
			if(z[ix]==zone) z.splice(ix, 1);
		}


		for(var ix=0; ix<x.length; ix++) {
			if(x[ix]==zone) {
				z.splice(i, 1);
				i--;
				break;
			}
		}
	}

	return z.join(",");
}

/**







 */
AjaxAnywhere.prototype.unwrapZoneDivs = function(zones) {
	var z=zones.split(",");
	
	for (var i=0; i<z.length; i++) {
        var id="aazone."+z[i];
        var zoneHolder = document.getElementById(id);
        
        zoneHolder.parentNode.setAttribute('id', id);
    	$(zoneHolder).contents().unwrap();
	}
}




ajaxAnywhere = new AjaxAnywhere();
ajaxAnywhere.bindById();