
/**
 * File contains JS Library for AJAX management
 *
 * JavaScript  version 1
 * @category   JavaScript Libraries
 * @author     Eugene A. Kalosha <aristarch@zfort.net>
 * @copyright  (c) 2004-2006 by ZFort Group
 * @version    SVN: $Id: 208$
 * @link       http://www.zfort.net
 * @since      File available since Release 2.3.0
 */

    /**
     * AJAX Page Request  Types
     */
    PHP2Ajax.AJAXPAGE_RESPONSE_TYPE_DATA    = 'DATA';
    PHP2Ajax.AJAXPAGE_RESPONSE_TYPE_HTML    = 'HTML';
    PHP2Ajax.AJAXPAGE_RESPONSE_TYPE_BOTH    = 'BOTH';

    PHP2Ajax.AJAXPAGE_PARENT_ONLOAD_EVENT_PARAMETER  = '__setParentOnLoadEvent';

    /**
     * PHP2Ajax is the namespace for AJAX JavaScript functions and Classes.
     *
     * @author   Eugene A. Kalosha <aristarch@zfort.net>
     * @version  $Id: ajaxpage.js, v 2.3.0 2006/10/24 $
     * @access   public
     * @package  php2
     */
    PHP2Ajax.AJAXPageBase = function(ajaxPageId, url, responseType, ajaxPageContainerId)
    {
        // --- Creating Page and linking it with Page Container --- //
        this.id               = ajaxPageId;
        this.setPageContainer(((ajaxPageContainerId != null) ? ajaxPageContainerId : this.id));

        /**
         * All Controls collection
         */
        this.all = new Object();

        // --- Set Base Page Parameters --- //
        this.setUrl(url);
        this.setResponseType(responseType);

        // --- Creating Preloader --- //
        this.preLoader = new PHP2Ajax.LoadManager('ajaxPreLoader' + "_" + this.id, this.pageContainerId, PHP2Ajax.LOADER_TYPE_OVERPAGE);

        // --- Additional Properties --- //
        this.isParentPageOnLoad        = false;
        this.__semaphoreOnCallStarted  = false;
    }

    /**
     * Sets Url for AJAX Page
     *
     * @param   string url
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.setUrl = function (url)
    {
        this.url = url;
    }

    /**
     * Sets Response Type for AJAX Page
     *
     * @param   string responseType
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.setResponseType = function(responseType)
    {
        this.responseType = responseType;
    }

    /**
     * Sets HTML Container for Current Page
     *
     * @param   string ajaxPageContainerId id of HTML Container Element
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.setPageContainer = function(ajaxPageContainerId)
    {
        this.pageContainerId  = ajaxPageContainerId;
        this.currentPage      = document.getElementById(this.pageContainerId);
    }

    /**
     * Loads AJAX Page and set onLoad handlers
     *
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.load = function(postData, handler, callBackHandler)
    {
        if (postData == null) var postData = new Object();

        postData = this.getPostData(postData);

        this.call(handler, postData, callBackHandler);
        this.preLoader.show();
    }

    /**
     * Call AJAX Page Server Method
     *
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.call = function(handler, postData, callBackHandler)
    {
        if (this.serverResponse == null) this.serverResponse = new PHP2Ajax.JSONRequest(this.url);
        this.serverResponse.clear();
        if (handler) this.serverResponse.call(handler);

        for (postItemName in postData)
        {
            this.serverResponse.add(postItemName, postData[postItemName]);
        }

        // --- Set Parent Page OnLoad Event for AJAX Page --- //
        if (this.isParentPageOnLoad)
        {
            this.isParentPageOnLoad = false;
            this.serverResponse.add(PHP2Ajax.AJAXPAGE_PARENT_ONLOAD_EVENT_PARAMETER, 'true');
        }

        if (callBackHandler != null) this.serverResponse.setPageCallBackHandler(callBackHandler);
        this.serverResponse.setHandler(this.onLoadCaller);
        this.serverResponse.onResponseError = this.onResponseErrorCaller;
        this.serverResponse.onHTTPError     = this.onHTTPError;
        this.serverResponse.currentObject   = this;
        this.serverResponse.execute();

        // --- Process On Call Started Semaphore --- //
        if (this.__semaphoreOnCallStarted && (typeof(this.onConcurrentCallStarted) == "function")) this.onConcurrentCallStarted();
        this.__semaphoreOnCallStarted = true;
    }

    /**
     * AJAX Page onLoad Event Handler Caller
     *
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.onLoadCaller = function()
    {
        // --- Unset On Call Started Semaphore --- //
        this.currentObject.__semaphoreOnCallStarted = false;

        this.currentObject.onResponseLoad();
        if (typeof(this.currentObject.onLoad) == "function") this.currentObject.onLoad();
    }

    /**
     * AJAX Page onLoad Event Handler Caller
     *
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.onResponseErrorCaller = function()
    {
        this.currentObject.onResponseError();
    }

    /**
     * AJAX Page onHTMLLoad System Event Handler
     *
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.onResponseLoad = function()
    {
        // --- Get Server Response Data Structure --- //
        var serverResponseData = this.serverResponse.getResponse();
        var response           = serverResponseData.Response;

        var errorDebugInfo = (serverResponseData.PHPTMPDebug != null) ? serverResponseData.PHPTMPDebug : '';
        if (typeof(serverResponseData.PHPAJAXDebugInfo) != undefined) this.loadDebugInfo(serverResponseData.PHPAJAXDebugInfo, errorDebugInfo);

        // --- Try lo Load HTML Data in the AJAX Page --- //
        if (serverResponseData.ResponseType == null) serverResponseData.ResponseType = PHP2Ajax.AJAXPAGE_RESPONSE_TYPE_HTML;
        if (((serverResponseData.ResponseType == PHP2Ajax.AJAXPAGE_RESPONSE_TYPE_HTML) || (serverResponseData.ResponseType == PHP2Ajax.AJAXPAGE_RESPONSE_TYPE_BOTH)) && (response.HTMLContent != null))
        {
            this.loadHTML(response.HTMLContent);
        }

        // --- Try to Change Controls Data in the AJAX Page --- //
        if (((serverResponseData.ResponseType == PHP2Ajax.AJAXPAGE_RESPONSE_TYPE_DATA) || (serverResponseData.ResponseType == PHP2Ajax.AJAXPAGE_RESPONSE_TYPE_BOTH)) && (response.ControlsData != null))
        {
            this.loadControlsData(response.ControlsData);
        }

        // --- Processing on Load event Handler --- //
        // --- if (typeof(this.onLoad) == "function") this.onLoad();

        // --- Processing Client Handler --- //
        if ((response.ClientHandler != null) && (typeof(this[response.ClientHandler]) == "function")) this[response.ClientHandler]();

        // --- Processing Client Messages --- //
        if (serverResponseData.ClientMessages.Count > 0) this.showClientMessages(serverResponseData.ClientMessages.Messages);

        // --- Processing JS Objects --- //
        this.loadJSObjectsList(response.JSObjectsList);

        // --- Hiding PreLoader --- //
        this.preLoader.hide();
    }

    /**
     * Process Client Messages from AJAX Server
     *
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.loadJSObjectsList = function(jsObjectslist)
    {
        try
        {
            var currentObject = this;
            var notLoadedObjects = new Object();
            var notLoadedObjectsCount = 0;

            if ((jsObjectslist != null) && (typeof(jsObjectslist) == "object"))
            {
                for (objectIndex in jsObjectslist)
                {
                    var jsObjectName = jsObjectslist[objectIndex];
                    var evalResult = true;
                    var evalString = "if (typeof(" + jsObjectName + ") != 'undefined') { " + jsObjectName + ".owner = currentObject; } else {evalResult = false;}";
                    eval(evalString);

                    if (!evalResult)
                    {
                        notLoadedObjects[notLoadedObjectsCount++] = jsObjectName;
                    }
                }
                // alert(typeof(PHP2Controls.AJAXPageNavigator) + " " + evalString);

                if (notLoadedObjectsCount > 0)
                {
                    var iterativeLoader = function ()
                    {
                        currentObject.loadJSObjectsList(notLoadedObjects);
                    }

                    var timerId = setTimeout(iterativeLoader, 300);
                }

                // alert(notLoadedObjectsCount);
            }
        }
        catch (eLoadException)
        {
            alert(eLoadException);
        }
    }

    /**
     * Process Client Messages from AJAX Server
     *
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.showClientMessages = function(clientMessagesList)
    {
        this.pageMessages = new PHP2Controls.MessageBox();

        for (messageNum in clientMessagesList)
        {
            this.pageMessages.add(clientMessagesList[messageNum].Message);
        }
        this.pageMessages.show();
    }

    /**
     * Push func function name to functions list
     *
     * @param   array functionsList
     * @param   array func
     */
    PHP2Ajax.AJAXPageBase.prototype.pushFunction = function(functionsList, func)
    {
        if (func != null)
        {
            var reg_declaration = /function\s*/ig;
            var reg_skobko      = /\s*\(/ig;

            func_string = func.shift();

            func_name = func_string.replace(reg_declaration, '');
            func_name = func_name.replace(reg_skobko, '');
            func_name = func_name.replace('/\s*/si', '');

            functionsList.push(func_name);
        } // if
    }

    /**
     * Push javascript tolist
     *
     * @param   array js_arr
     * @param   array js_str
     */
    PHP2Ajax.AJAXPageBase.prototype.pushJS = function(js_arr, js_str)
    {
        var functions_list = new Array();
        var reg_script     = /<\/?script.*?>/ig;
        var reg_function   = /function\s+.+\s*\(/ig;

        if (js_str != null)
        {
            js_string = js_str.shift();
            js_string = js_string.replace(reg_script, '');

            func = reg_function.exec(js_string);
            this.pushFunction(functions_list, func);

            while (func)
            {
                func = reg_function.exec(js_string);
                this.pushFunction(functions_list, func);
            } // while

            for (i = 0; i < functions_list.length; i ++)
            {
                req_replace = new RegExp('function\\s*' + functions_list[i] + '\\s*\\(', "ig");
                js_string = js_string.replace(req_replace, 'window.' + functions_list[i] + ' = function(');
            } // for

            js_arr.push(js_string);
        } // if
    }

    /**
     * Loads HTML code with Java Scripts in the AJAX Page.
     *
     * @param   string innerHTMLCode
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.loadHTML = function(innerHTMLCode)
    {
        var js_arr = new Array();
        var js_reg = /<script.*?>(.|[\r\n])*?<\/script>/ig;


        var js_str = js_reg.exec(innerHTMLCode);
        this.pushJS(js_arr, js_str);


        while (js_str)
        {
            js_str = js_reg.exec(innerHTMLCode);
            this.pushJS(js_arr, js_str);
        } // while

        innerHTMLCode = innerHTMLCode.replace(js_reg,'');

        this.currentPage.innerHTML = '';
        if (this.currentPage.insertAdjacentHTML == undefined)
        {
            dom = this.currentPage;
            var df;
            var r = dom.ownerDocument.createRange();
            r.selectNodeContents(dom);
            r.collapse(true);
            df = r.createContextualFragment( innerHTMLCode );
            dom.insertBefore(df, dom.firstChild );
        } // if
        else
        {
            this.currentPage.insertAdjacentHTML("afterbegin", innerHTMLCode);
        } // else

        // --- Loading Controls In the AJAX Page Controls Collection --- //
        this.all = new Object();
        this.addControlsByTagName('input');
        this.addControlsByTagName('select');
        this.addControlsByTagName('textarea');

        // --- Loading Java Scripts in IE --- //
        for (var i=0; i < js_arr.length; i++)
        {
            eval(js_arr[i]);
        } // for


    }
    /**
     * Loads Controls Data in the AJAX Page.
     *
     * @param   string controlsData
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.loadControlsData = function(controlsData)
    {
        for (controlId in controlsData)
        {
            if (typeof(this.all[controlId]) != "undefined")
            {
                for (attributeName in controlsData[controlId]) this.all[controlId][attributeName] = controlsData[controlId][attributeName];
            }
        }
    }

    /**
     * AJAX Page onLoad Event Handler. To override in descendant.
     *
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.onLoad = function()
    {
        // --- alert('Page Loaded Successfully');
    }

    /**
     * Sets Parent Page onLoad Event for AJAX Page.
     *
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.setParentOnLoadEvent = function()
    {
        this.isParentPageOnLoad = true;
    }

    /**
     * On Response Error Method
     *
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.onResponseError = function()
    {
        alert("Error: " + this.serverResponse.response.Error.Code + ". " + this.serverResponse.response.Error.Message);
    	// this.alert = new PHP2Controls.Alert("Error: " + this.serverResponse.response.Error.Code + ". " + this.serverResponse.response.Error.Message);
        this.preLoader.hide();
    }

    /**
     * On HTTP Error Event Handler
     *
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.onHTTPError = function()
    {
        alert("Error: 'The server respond with a bad status code: " + this.httpRequest.status);
    	// this.currentObject.alert = new PHP2Controls.Alert("Error: 'The server respond with a bad status code: " + this.httpRequest.status);
        this.currentObject.preLoader.hide();
    }

    /**
     * On Concurrent Call Process Started Event Handler
     *
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.onConcurrentCallStarted = function()
    {
    }

    /**
     * Add Controls To AJAX Page Controls Collection
     *
     * @param   HTMLElement controlObject
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.addControl = function(controlObject)
    {
        // var controlObject = document.getElementById(controlId);
        if (controlObject != null)
        {
            var controlId = (controlObject.id ? controlObject.id : controlObject.name);
            this.all[controlId]        = controlObject;
            this.all[controlId].owner  = this;

            // --- Set getActiveValue Method --- //
            this.all[controlId].getActiveValue = function()
            {
                if ((this.tagName.toLowerCase() == 'input') && (this.type.toLowerCase() == 'checkbox')) return (this.checked ? 'on' : '');
                if (this.value != null) return this.value;
                if (this.text  != null) return this.text;
            }
        }
    }

    /**
     * Add Controls To AJAX Page Controls Collection By Its Tag Name
     *
     * @param   string tagName
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.addControlsByTagName = function(tagName)
    {
        var elementsList = this.currentPage.getElementsByTagName(tagName);
        for (i = 0; i < elementsList.length; i++)
        {
            this.addControl(elementsList[i]);

            // --- Loading AJAX Buttons --- //
            if ((tagName.toLowerCase() == 'input') && (elementsList[i].type.toLowerCase() == 'button'))
            {
                if (elementsList[i].onclick == null) elementsList[i].onclick = this.onAJAXButtonClick;
            }
        }
    }

    // --- Additional Methods --- //

    /**
     * Return POST/GET DATA for AJAX Page
     *
     * @param   Object postData Initial Post Data
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.getPostData = function(postData)
    {
        if (postData == null) var postData = new Object();

        for (controlId in this.all)
        {
            // --- Loading AJAX Buttons --- //
            if ((this.all[controlId].tagName.toLowerCase() == 'input') && (this.all[controlId].type.toLowerCase() == 'button'))
            {

            }
            else if ((this.all[controlId].tagName.toLowerCase() == 'input') && (this.all[controlId].type.toLowerCase() == 'radio')) // --- Hook for Radio Buttons --- //
            {
                if ((this.all[controlId].checked)) this.addActiveValue(postData, controlId);
            }
            else
            {
                this.addActiveValue(postData, controlId);
            }
        }

        return postData;
    }

    /**
     * Adds Active Value for AJAX Page Request
     *
     * @param   Object postData
     * @param   String controlId
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.addActiveValue = function(postData, controlId)
    {
        if (typeof(this.all[controlId].name) != "undefined")
        {
            postData[this.all[controlId].name] = this.all[controlId].getActiveValue();
        }
        else
        {
            postData[controlId] = this.all[controlId].getActiveValue();
        }
    }

    /**
     * Sets Active Value for AJAX Page Request
     *
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.getActiveValue = function()
    {
        if (this.value != null)
        {
            return this.value;
        }

        return '';
    }

    /**
     * On AJAX button Click
     *
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.onAJAXButtonClick = function()
    {
        var postData = new Object();
        postData[this.name] = this.value;

        this.owner.load(postData);
    }

    /**
     * On AJAX button Click
     *
     * @return  void
     */
    PHP2Ajax.AJAXPageBase.prototype.loadDebugInfo = function(debugInfo, errorsDebugInfo)
    {
        var debugBlock = document.getElementById('_debugArea');
        if (debugBlock == null) debugBlock = document.getElementById('ajaxDebugInfoBlock');

        if (debugBlock == null)
        {
            document.body.insertAdjacentHTML("beforeEnd", '<div id="ajaxDebugInfoBlock"></div>');
            debugBlock = document.getElementById('ajaxDebugInfoBlock');
        }

        if (debugBlock != null) debugBlock.innerHTML = debugInfo;

        if (errorsDebugInfo)
        {
            var errorDebugBlock = document.getElementById('PHPTMPDebug');
            if (errorDebugBlock != null) errorDebugBlock.innerHTML = errorsDebugInfo;
        }
        else
        {
            // --- Hiding Errors Debug Info Block --- //
            if (document.getElementById('PHPTMPDebugBlock') != null) document.getElementById('PHPTMPDebugBlock').style.display = 'none';
        }
    }
