
//Request queue was added to solve issues where multiple requests were harmfully interleaving
//The issue was encountered where the callback was executed before an abort operation could complete, resulting in a data not available error
//Now we add all requests to a queue, and before aborting the request we drop the queue, checking in the callback to see if it has been dropped
function RequestQueue()
{
    this._Requests = new Array();
    this._Dropped = new Array();
    this._DroppedIndex = 0;
    this._RequestIndex = 0;
}
RequestQueue.prototype = 
{
    AddRequest : function(id)
    {
        this._Requests[this._RequestIndex] = id;
        this._RequestIndex = (this._RequestIndex + 1) % 10;
    },
    DropRequests : function()
    {
        for(var i=0;i<this._Requests.length;i++)
        {
            this._Dropped[this._DroppedIndex%10] = this._Requests[i];
            this._DroppedIndex = (this._DroppedIndex + 1) % 10;
        }
        this._Requests = new Array();
        this._RequestIndex = 0;
    },
    IsDropped : function(id)
    {
        for(var i=0;i<this._Dropped.length;i++)
        {
            if(this._Dropped[i] == id) 
            {
                return true;
            }
        }
        return false;
    }
}

/**
 * PageCallback object
 * 
 * maintains a list functions which need executing on page load and/or 
 * Ajax completion and execute them when required
 */
var PageCallback = {
	
	activated: false,
	functions: new Array(),
	
	/**
	 * addCallback method
	 * 
	 * adds a callback to the list to be called
	 * 
	 * @param Function fn
	 * @param boolean executeOnce - whether to remove the function after the first call
	 */
	addCallback: function(fn, executeOnce) {
		
		if(fn == null)
		    return;
		    
		//default to false
		executeOnce = executeOnce || false;

		if (!this.activated) {
			//attach to post-Ajax event
			AjaxAnywhere.prototype.onAfterResponseProcessing = function() { PageCallback.execute(); }
			//attach to onload, preserving existing functions

			if (typeof(window.onload) == 'function') {
				var oldOnload = window.onload;
				window.onload = function() { oldOnload(); PageCallback.execute(); }
			} else {
				window.onload = function() { PageCallback.execute(); }
			}
			
			this.activated = true;
		}
		this.functions[this.functions.length] = {'callback': fn, 'once': executeOnce};
	},
	
	/**
	 * removeCallback method
	 * 
	 * removes a callback if present and returns whether it was removed
	 * 
	 * @param Function fn
	 * @return boolean
	 */
	removeCallback: function(fn) {
		var removed = false;
		for (var x = 0; x < this.functions.length; x++) {
			if (this.functions[x].callback == fn) {
				this.functions.splice(x, 1);
				removed = true;
			}
		}
		return removed;
	},
	
	/**
	 * execute method
	 * 
	 * called when the Ajax completes / page loads to call each callback
	 */
	execute: function() 
	{

	    var localFunctions = [];
	    for(var localI = 0;localI < this.functions.length;localI++)
	    {
	        localFunctions[localI] = this.functions[localI];
	    }
		for (var x = 0; x < localFunctions.length; x++) {
			var fn = localFunctions[x].callback;
			try
			{
			    fn();
			}
			catch(e)
			{
			    CliDebug("Error occurred with post ajax Events for " + fn +  ":" + e.message);
			}
			//remove if this should only be executed once
			if (localFunctions[x].once) this.removeCallback(localFunctions[x].callback);
		}
	}
	
}

/*
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.
*/

// constructor;
function AjaxAnywhere() {

    this.id = AjaxAnywhere.defaultInstanceName;
    this.formName = null;
    this.notSupported = false;
    this.delayBeforeContentUpdate = true;
    this.delayInMillis = 100;
    this.callbackExecuted = true;
	this.asynch = true;
	this.requestQueue = new RequestQueue();
	this.disableShowLoading = false;		// added to override the showing of the spinner
	this.doNotUseHistoryOverride = false;	// added to override the use of ajaxHistory for the request
	
    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 = Math.random();

AjaxAnywhere.ASYNCH_KEY = "automated.test.session=false";
AjaxAnywhere.SYNCH_KEY = "automated.test.session=true";


/**
* this features are added for better support of in-browser automated test frameworks like Selenium
* if URL or query string contains "automated.test.sessionh=false" this method sets a session cookie to indicate that
* for this session XmlHttpRequest must operate in synchronous mode.
* click() method of in-browser test framework must not return untill page zones are correctly updated
*/
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();

/**
* returns true if curreny session is markes to work in synchronous mode for better compatibility with in-browser test,
* like Selenium
*/

AjaxAnywhere.prototype.isAsynch = function (){
    return this.asynch;
}

AjaxAnywhere.prototype.setAsynch = function (blValue){
    this.asynch = blValue;
}

/**
* Stores substitutes SubmitButton names in to redo sustitution if a button was eventually inside a refresh zone.
*/
AjaxAnywhere.prototype.substitutedSubmitButtons = new Array();
AjaxAnywhere.prototype.substitutedSubmitButtonsInfo = new Object();

/**
* Returns a Form object that corresponds to formName property of this AjaxAnywhere class instance.
*/
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;
}


/**
* Binds this instance to window object using "AjaxAnywhere."+this.id as a key.
*/
AjaxAnywhere.prototype.bindById = function () {
    var key = "AjaxAnywhere." + this.id;
    window[key] = this;
}

/**
* Finds an instance by id.
*/
AjaxAnywhere.findInstance = function(id) {
    var key = "AjaxAnywhere." + id;
    return window[key];
}

/**
* This function is used to submit all form fields by AJAX request to the server.
* If the form is submited with &lt;input type=submit|image&gt;, submitButton should be a reference to the DHTML object. Otherwise - undefined.
*/
AjaxAnywhere.prototype.submitAJAX = function(additionalPostData, submitButton) {

    if (this.notSupported)
        return this.onSubmitAjaxNotSupported(additionalPostData, submitButton);

    if (additionalPostData == null || typeof additionalPostData == "undefined")
        additionalPostData = "";

    this.bindById();

    var form = this.findForm();
	
	//CliDebug("Found form : " + form);

//    var actionAttrNode = form.attributes["action"];
	
//	//CliDebug("Found form action attribute : " + actionAttrNode);
	
    var url = form.getAttribute("action") == null?null:form.getAttribute("action");
    if ((url == null) || (url == ""))
        url = location.href;

    //Test that we are not trying to ajax between http and https, if so we'll make it a full page request
    if(url.length > 5 &&
    ((document.location.href.substring(0,5) == "http:" && url.substring(0,5) == "https") || (document.location.href.substring(0,5) == "https" && url.substring(0,5) == "http:"))
    )
    {
        this.submitOld(form,submitButton);
        return;
    }
    
	//CliDebug("Posting form to : " + url);

    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);
	//CliDebug("Posting zones : " + zones);	
    if (zones == null) {
    
		//CliDebug("submitOld");
	    // submit in tradiditional way :
        this.submitOld(form,submitButton);
        return;
    }
	//CliDebug("Dropping previous request");	
    this.dropPreviousRequest();
	//CliDebug("Dropped previous request");	
    this.req.open("POST", url, this.isAsynch());

    this.req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");

	//CliDebug("Preparing postData");	
    var postData = this.preparePostData(submitButton);
	//CliDebug("Prepared postData");	
    if (zones != "")
        postData = '&aazones=' + encodeURIComponent(zones) + "&" + postData + "&" + additionalPostData;
    else
        postData += "&" + additionalPostData;
		
	if(zones.indexOf("ioko") == -1){
		this.showLoadingMessage();
	}
	
    this.sendPreparedRequest(postData);

}
/**
* sends a GET request to the server.
*/
AjaxAnywhere.prototype.getAJAX = function(url, zonesToRefresh, disableShowLoading, doNotUseHistoryOverride) 
{
	this.disableShowLoading = disableShowLoading || false;
	this.doNotUseHistoryOverride = doNotUseHistoryOverride || false;

    var dubbgerDummy = null;
    this.sendAJAX("GET", url, zonesToRefresh, "");
}

AjaxAnywhere.prototype.postAJAX = function(url, zonesToRefresh, postData)
{
    this.sendAJAX("POST", url, zonesToRefresh, postData);
}

AjaxAnywhere.prototype.sendAJAX = function(method, url, zonesToRefresh, requestBody)
{
    //Test that we are not trying to ajax between http and https, if so we'll make it a full page request
    if(url.length > 5 &&
    ((document.location.href.substring(0,5) == "http:" && url.substring(0,5) == "https") || (document.location.href.substring(0,5) == "https" && url.substring(0,5) == "http:"))
    )
    {
        if(method.toUpperCase() == "POST")
        {
             this.changeToSynchronousPost(requestBody, url);
             return;
        }
        else    
        {
            location.href = url;  
            return;
        }
    }
    
    
    if (this.notSupported)
        return this.onGetAjaxNotSupported(url);

    this.bindById();
	
	if((zonesToRefresh.indexOf("content") != -1) && (!this.doNotUseHistoryOverride)) {
		if (window.ajaxHistory) ajaxHistory.addHistory(url);
	}

    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();
    // avoid caching

    if (zonesToRefresh != null && zonesToRefresh != "")
        url += '&aazones=' + encodeURIComponent(zonesToRefresh);

    this.req.open(method, url, this.isAsynch());
	if(zonesToRefresh.indexOf("ioko") == -1){
		this.showLoadingMessage();
	}
	//hard coded in to allow post requests to get through to spring, 
	//TODO: refactor this to make it prettier
	if(method == "POST")
	{
	    var headernames = new Array();
	    var headervalues = new Array();
	    headernames[0] = "Content-Type";
	    headervalues[0] = "application/x-www-form-urlencoded";
	    this.sendPreparedRequest(requestBody, headernames, headervalues);
	}
	else
	{
        this.sendPreparedRequest(requestBody);
    }
}

AjaxAnywhere.prototype.changeToSynchronousPost = function(postData, url)
{
    var CreateEl = document.createElement;
    var form = CreateEl("form");
    form.action = url;
    form.method = "post"
    var fields = postData.split('&');
    for(var i=0;i<fields.length;i++)
    {
        var field = CreateEl("input");
        field.type = "text";
        field.name=fields.split('=')[0];
        field.value=fields.split('=')[1];
        form.appendChild(field);
    }
    document.body.appendChild(form);
    form.submit();
}

/**
* @private
*/
AjaxAnywhere.prototype.sendPreparedRequest = function (postData) 
{
    this.sendPreparedRequest(postData, null, null);
}
AjaxAnywhere.prototype.sendPreparedRequest = function (postData, additionalHeaderNames, additionalHeaderValues) {
	
    this.req.setRequestHeader("Accept", "text/xml");

    if(additionalHeaderNames != null)
    {
        for(var i=0;i<additionalHeaderNames.length;i++)
        {
            this.req.setRequestHeader(additionalHeaderNames[i],additionalHeaderValues[i]);
        }
    }
    
    //we need to uniquely identify this callback and add it to the request queue, to allow it to be invalidated if required
    var RequestID = Math.random();
    this.requestQueue.AddRequest(RequestID);
        
    this.req.onreadystatechange = new Function("var callback = AjaxAnywhere.findInstance(\"" + this.id + "\");if(callback != null){callback.callback(" + RequestID + ");}");

    this.callbackExecuted = false;

    this.req.send(postData);

    this.onRequestSent();
}
/**
* Used internally by AjaxAnywhere. Aborts previous request if not completed.
*/
AjaxAnywhere.prototype.dropPreviousRequest = function() {
    if (this.req.readyState != 0 && this.req.readyState != 4) {
    
        //first invalidate the callback
        this.requestQueue.DropRequests();
        // abort previous request if not completed
        this.req.abort();
        this.requestQueue.DropRequests();
        this.handlePrevousRequestAborted();
    }
}

/**
* Internally used to prepare Post data.
* If the form is submited with &lt;input type=submit|image&gt;, submitButton is a reference to the DHTML object. Otherwise - undefined.
*/
AjaxAnywhere.prototype.preparePostData = function(submitButton) {
    var form = this.findForm();
    var result = "&aaxmlrequest=true";
    for (var i = 0; i < form.elements.length; i++) {
        var el = form.elements[i];
        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;
}

/**
* Pauses the thread of execution for the specified number of milliseconds
* @private
*/
function delay(millis) {
    date = new Date();
    var curDate = null;
    do {
        curDate = new Date();
    }
    while (curDate - date < millis);
}

/**
* Handle wrong content type. 
*/
AjaxAnywhere.prototype.handleWrongContentType = function() 
{
    try
    {
        CliLogAAJS( "content-type is not text/xml : [" + this.req.getResponseHeader('content-type') + "]", "", "aa.js:handleWrongContentType" );
    }
    catch( e ){}
    
    CliDisplayError( CliErrorAction_General, 20002 );
}

/**
* A callback. internally used
*/
AjaxAnywhere.prototype.callback = function(requestId)
{
    //check to see that this id has not been invalidated (in the process of aborting).
    if(this.requestQueue.IsDropped(requestId))
        return;
        
    if( this.req.readyState == 4 )
    {
		this.callbackExecuted = true;
        this.onBeforeResponseProcessing();
        this.hideLoadingMessage();

        //account for mozilla bug with reading the status property
        var requestStatus = -1;
        try{requestStatus = this.req.status;}
        catch(e){hide_waiting();}
        
        if( requestStatus == 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;
                var forceFullPageRedirect = false;
                
                try {	// IE way
                	if (redirects[0].getAttribute('fullpageredirect') == 'true') {
                		forceFullPageRedirect = true;
                	}
                } catch (e) {}
                // and try other browsers
                try {
                	if (!forceFullPageRedirect && (redirects[0].attributes && redirects[0].attributes['fullpageredirect'] && redirects[0].attributes['fullpageredirect'].value == 'true')) {
                		forceFullPageRedirect = true;
                	}
                } catch (e) {}
				
				// legacy solution
                if((newURL.indexOf("home.do") != -1) || (newURL.indexOf("playLiveTv.do") != -1) || (newURL.indexOf("after.login=true") != -1)) {
                	forceFullPageRedirect = true;
                }
                
			    if(forceFullPageRedirect){
				    document.location.href = newURL;
			    } else {
            	    ajaxAnywhere.getAJAX(newURL, "appnav,content");
			    }
			    return;
            }
            if (docs.length != 0) {
                var newContent = docs[0].firstChild.data;

                //cleanup ressources
                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
                    }
                    
                    //DAH MOD
                    // The video details page uses a specific layout (the aazone.content and aazone.detailoverlay
                    // are in the template in contrast to the layout as in all other pages.  This was implemented to
                    // avoid recursive login loops when deep linking to a video page.  Therefore, here we have to strip
                    // out the content else the rendered page will contain 2 aazone.content's and 2 aazone.detailoverlay's
                    // which causes problems with ForeFox.
                    var startIndex = html.indexOf('<!-- VideoContentTemplate.vm - start -->');
                    if (startIndex>-1) {
                    	var endIndex = html.indexOf('<!-- VideoContentTemplate.vm - end -->');
                    	var content = html.substring( startIndex, endIndex + 38);
                    	html = content;
                    }

                    var zoneHolder = document.getElementById("aazone." + name);
                                     
					
					//GP MOD
					// Looks for a method to use to populate the div, if not available
					// sets div.
					try
					{
						self[ 'set_' + name ]( html );
					} 
					catch(e) 
					{  
                       if (zoneHolder != null && typeof(zoneHolder) != "undefined") 
                       {
                            //DAH MOD
                            // The PlaySyndicateTemplate has multiple ajax zones, and performs full replaces of zones rather than
                            // overlaying as in other templates.  Therefore when updating the zones, do not overwrite the end zone tags.
                            if (name=="syndicatePlayerBottom" || name=="syndicatePlayerTop") {
                                var startIndex = zoneHolder.innerHTML.indexOf('<!-- @end of zone [' + name + ']@ -->');
                                if (startIndex>-1) {
                    	            html = html + zoneHolder.innerHTML.substring(startIndex);
                                }
                            }
                            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++) {
                    // use $$$$i variable to avoid collision with "i" inside user script
                    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) { }
                    }
            }
			try { hide_waiting(); }catch(e){}
        }
        else
        {
            if( requestStatus != 0 )
            {
                if( window.CliSwitchToOfflineMode != null ) {
                    CliSwitchToOfflineMode();
                }
                else if (_cliController.isClientPageUrl(location.href)) {
                    _cliController.getKontikiHosted().launchOfflineLibrary();
                }
            }
        }
        
        this.restoreSubstitutedSubmitButtons();
        this.onAfterResponseProcessing();
    }// readyState == 4
    
}

/**
*  Default sample loading message show function. Overrride it if you like.
*/
AjaxAnywhere.prototype.showLoadingMessage = function() {

	if(!this.disableShowLoading && self["show_waiting"]){
		show_waiting();
	}

    //var div = document.getElementById("AA_loading_div");
    //if (div != null) {
	//    div.style.display = "block";
	//}
}

/**
*  Default sample loading message hide function. Overrride it if you like.
*/
AjaxAnywhere.prototype.hideLoadingMessage = function() {
    var div = document.getElementById("AA_loading_div");
    if (div != null)
        div.style.display = "none";

}

/**
* This function is used to facilitatte AjaxAnywhere integration with existing projects/frameworks.
* It substitutes default Form.sumbit().
* The new implementation calls AjaxAnywhere.isFormSubmitByAjax() function to find out if the form
* should be submitted in traditional way or by AjaxAnywhere.
*/
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);

}
/**
* Substitutes the default behavior of &lt;input type=submit|image&gt; to submit the form via AjaxAnywhere.
*
* @param {boolean} indicates if existing onClick handlers should be preserved.
* If keepExistingOnClickHandler==true,
* Existing handler will be called first if it returns false, or if event.returnValue==false, AjaxAnywhere will not
* continue form submission.
* If keepExistingOnClickHandler==false or undefines, existing onClick event handlers will be replaced.
*
* @param {Array} list of submitButtons and submitImages names. If the parameter is omitted or undefined,
* all elements will be processed
*/
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);
            }
        }
    }

}
/**
* Performs a single element behavior substitution
*
* @private
*/
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;
}

/**
*
* @private
*/
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 {
            //input type=image
            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);
                            }
                        }
                    }
            }
        }
    }
}

/**
* @private
*/
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;
}
/**
* Override this function if you use AjaxAnywhere.substituteFormSubmitFunction() to
* dynamically inform AjaxAnywhere of the method you want to use for the form submission.
*/
AjaxAnywhere.prototype.isFormSubmitByAjax = function () {
    return true;
}

/**
* Some browsers (notably IE) do not load images from thier cache when content is updated using
* innerHTML. As a result, each image is re-requested from the server even though the image exists
* in the cache. To work around this issue, AjaxAnywhere preloads images present in the new content
* and intrduces a brief dely (default of 100 milleseconds) before calling innerHTML.
* See http://support.microsoft.com/default.aspx?scid=kb;en-us;319546 for further details.
* This function can be used to change this behaviour.
* @param (boolean) isDelay
*/
AjaxAnywhere.prototype.setDelayBeforeLoad = function (isDelay) {
    this.delayBeforeContentUpdate = isDelay;
}

/**
* Returns the current delay behavior.
*/
AjaxAnywhere.prototype.isDelayBeforeLoad = function () {
    return this.delayBeforeContentUpdate;
}

/**
* Sets the delay period in milliseconds. The default delay is 100 milliseconds.
* @param (int) delayMillis
*/
AjaxAnywhere.prototype.setDelayTime = function (delayMillis) {
    this.delayInMillis = delayMillis;
}

/**
* Returns the delay period in milliseconds.
*/
AjaxAnywhere.prototype.getDelayTime = function () {
    return this.delayInMillis;
}

/**
*   If an exception is throws on the server-side during AJAX request, it will be processed
* by this function.
*/
AjaxAnywhere.prototype.handleException = function( type, details )
{
    try
    {
        CliLogAAJS( details, "", "aa.js:handleException" );
    }
    catch( e ){}
    
    CliDisplayError( CliErrorAction_General, 20003 );
}


/**
* Override it if you need.
*/
AjaxAnywhere.prototype.handlePrevousRequestAborted = function()
{
}


/**
*   If the HTML received in responce to AJAX request contains JavaScript that defines new
* functions/variables, they must be propagated to the proper context. Override this method
* to return the Array of function/variable names.
*/
AjaxAnywhere.prototype.getGlobalScriptsDeclarationsList = function(script) {
    return null;
}

/**
* This function should be overridden by AjaxAnywhere user to implement client-side
* determination of zones to reload.
*
* If the form is submited with &lt;input type=submit|image&gt;, submitButton is a reference to the DHTML object. Otherwise - undefined.
*
* @Returns a comma separated list of zones to reload, or "document.all" to reload
* the whole page. Returns null if the request must be sent in traditional way
*
*/
AjaxAnywhere.prototype.getZonesToReload = function(url, submitButton) {
    return this.getZonesToReaload(); // backward compatibility only
}
/**
* depreceted : wrond spelling : Reaload will be removed in later versions
*/
AjaxAnywhere.prototype.getZonesToReaload = function(url, submitButton) {
    return "";
}

/**
* Override this method to implement a custom action
*/
AjaxAnywhere.prototype.onRequestSent = function () {

};
/**
* Override this method to implement a custom action
*/
AjaxAnywhere.prototype.onBeforeResponseProcessing = function () {
};
/**
* Override this method to implement a custom action
*/
AjaxAnywhere.prototype.onAfterResponseProcessing = function () {
};

/**
* Provides a default implementation from graceful degradation for getAJAX()
* calls location.href=url if XMLHttpRequest is unavailable, reloading the entire page .
*/
AjaxAnywhere.prototype.onGetAjaxNotSupported = function (url) {
    location.href = url;
    return false;
};

/**
* Provides a default implementation from graceful degradation for submitAJAX()
* calls form.submit() if XMLHttpRequest is unavailable, reloading the entire page
*/
AjaxAnywhere.prototype.onSubmitAjaxNotSupported = function (additionalPostData, submitButton) {

	//CliDebug("onSubmitAjaxNotSupported");

    var form = this.findForm();

    var url = form.getAttribute("action") == null?null:form.getAttribute("action");
    var url_backup = url;
    if (typeof additionalPostData != 'undefined' && additionalPostData != null) {
        url += (url.indexOf("?") != -1) ? "&" : "?";
        url += additionalPostData;
        form.setAttribute("action",url);
        // only POST method allows sending additional
        // date by altering form action URL.
        form.setAttribute("method", "post");
    }

    this.submitOld(form,submitButton);
	form.setAttribute("action",url_backup);
    return false;
};
/**
* submit the form in tradiditional way :
* @private
*/

AjaxAnywhere.prototype.submitOld = function (form,submitButton){
	//CliDebug("submitOld");
    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);
    }
}

function CliLogAAJS( message, tag, category )
{
    if( window._cliController != null )
    {
        if( _cliController.getTracer().shouldTraceError() )
        {
            _cliController.getTracer().WriteError( tag, message, category );
        }
    }
    else if( window.app != null )
    {
        if( app.TraceError() )
        {
            app.WriteTraceError( "aa.js: " + message );
        }
    }
}

// default instance.
ajaxAnywhere = new AjaxAnywhere();
ajaxAnywhere.bindById();

iokoAjaxAnywhere = new AjaxAnywhere();
iokoAjaxAnywhere.setAsynch(false);

/**
 * AjaxHistory
 *
 * uses the hidden iframe to track the AA calls and re-enable the back button
 *
 * initialise with ajaxHistory.initialize(callbackFn)
 * alternatively, set callback using ajaxHistory.setCallback(callbackFn)
 * add URLs with ajaxHistory.addHistory(url)
 */
var ajaxHistory = (function() {
				
	var _page1 = null;
	var _page2 = null;
	
	var _callback = function(url) {};
	var _iframe = null;
	var _initialUrl = null;
	var _lastUrl = null;
	var _storedCallback = null;
	
	return {
		
		initialize: function(callback) {
			if (callback) _callback = callback;
			_iframe = window.frames['historyIframe'];
			_lastUrl = _initialUrl = location.href;
		},
		
		addHistory: function(url) {
			if (url != _lastUrl) {
				try {
					var page = (_iframe.location.href.indexOf(_page1) == -1) ? _page1 : _page2;
					_lastUrl = url;
					_iframe.location = page + '?' + url;
				} catch (e) {
				
				}
			}
		},
		
		historyChanged: function(url) {
			if (url != _lastUrl) {
				_lastUrl = url;
				_callback(url);
			}
		},
		
		initialLoad: function() {
			if (_initialUrl) this.historyChanged(_initialUrl);
		},
		
		setCallback: function(callback) {
			_callback = callback;
		},
		
		setPages: function(page1, page2) {
			_page1 = page1;
			_page2 = page2;
		}

	}
	
})();

//set up
function ajaxBack(url) {
	ajaxAnywhere.getAJAX(url, 'content');
	if (window.revertNav) window.revertNav();
}
ajaxHistory.setCallback(ajaxBack);