// **************************************************************************************************************************
// Object for getting data by AJAX
// --------------------------------------------------------------------------------------------------------------------------
// - loaderObjectId          : HTMLElement Id (String) - Id of element for showing loading messages (must be DIV or SPAN)
// - loadingHTML             : String                  - HTML to show when loading is started; for loading more files
//                                                       use [ACTUAL_DESC] replacement mark
// - afterLoadHTML           : String                  - HTML to show after data are loaded
// - errorObjectId           : HTMLElement Id (String) - Id of element for showing error messages (must be DIV or SPAN)
// - generalErrorHTML        : String                  - text of general error, when AJAX is not supported by web browser
// - retreivingDataErrorHTML : String                  - text of error when there is problem of data transfer from server
// **************************************************************************************************************************
function AjaxDataReader(loaderObjectId, loadingHTML, afterLoadHTML, errorObjectId, generalErrorHTML, retreivingDataErrorHTML)
{
    // -------------------------------------------------------------------------------------------------
    // ATTRIBUTES - working with data
    // -------------------------------------------------------------------------------------------------
    
    // variable for general AJAX object
    var xmlhttp = null;

    // arrays for storage of result data
    var resultsXML = new Array();
    var resultsText = new Array();
    
    // variables for lastly loaded data
    var lastResultXML = null;
    var lastResultText = "";

    // indicators of actual object state
    var resultReady = false;
    var loadingData = false;
    
    // array for keeping loading front
    var loadingFront = new Array();
    
    // -------------------------------------------------------------------------------------------------
    // ATTRIBUTES - for working loading
    // -------------------------------------------------------------------------------------------------
    
    // messages for loading
    var loadingMessage = loadingHTML;
    var afterLoadMessage = afterLoadHTML;
    
    // object for showing messages
    var loaderObject = (loaderObjectId != null ? document.getElementById(loaderObjectId) : null);
    
    // -------------------------------------------------------------------------------------------------
    // ATTRIBUTES - for working with errors
    // -------------------------------------------------------------------------------------------------
    
    // default error messages
    var defaultGeneralErrorMessage = "Your browser does not support XMLHTTP.";
    var defaultRetreivingDataErrorMessage = "Problem retrieving XML data.";
    
    // variables for custom error messages
    var generalErrorMessage = generalErrorHTML;
    var retreivingDataErrorMessage = retreivingDataErrorHTML;
    
    // object for showing errors
    var errorObject = (errorObjectId != null ? document.getElementById(errorObjectId) : null);

    // -------------------------------------------------------------------------------------------------
    // GENERAL METHODS AND OBJECTS FOR DATA TRANSFER
    // -------------------------------------------------------------------------------------------------

    // Public method for getting data from URL. --------------------------------------------------------
    //     - This method works with one item data in final result.
    // -------------------------------------------------------------------------------------------------
    // - url                          : String - full URL location of data to load
    // - method2Execute               : String - full string call of method that should be executed 
    //                                           after data are loaded; for replacement of loaded data
    //                                           uses [DataXML] and [DataText]
    // - loadingDescription           : String - description of loading for concrete item
    // - afterLoadDescription         : String - result text for concrete item
    // - specialObjectId4LoadingTexts : String - special object for showing messages of loading of
    //                                           concrete item
    // - specialObjectId4ErrorTexts   : String - special object for showing error messages of loading
    //                                           of concrete item
    function getDataByItem(url, method2Execute, nodeName, loadingDescription, afterLoadDescription, 
        specialObjectId4LoadingTexts, specialObjectId4ErrorTexts, method2Execute4NoItems)
    {
        var methodName = "";
        var methodAdditiveParams = "";
        
        methodName = method2Execute.split("|")[0];
        if (method2Execute.split("|").length == 2)
             methodAdditiveParams = method2Execute.split("|")[1];

        getDataByItems(url, "readXMLResults([DataXML], '"+nodeName+"', '"+methodName+"([DATA],[INDEX],[COUNT],[ATTRIBUTES]"+methodAdditiveParams+");'"+
            ((method2Execute4NoItems != "") && (method2Execute4NoItems != null) ? ",'"+method2Execute4NoItems + "'" : "")+");", 
            loadingDescription, afterLoadDescription, 
            specialObjectId4LoadingTexts, specialObjectId4ErrorTexts, method2Execute4NoItems);
    }
    this.getDataByItem = getDataByItem;

    // Public method for getting data from URL. --------------------------------------------------------
    //     - This method works with all items data in final result.
    // -------------------------------------------------------------------------------------------------
    // - url                          : String - full URL location of data to load
    // - method2Execute               : String - full string call of method that should be executed 
    //                                           after data are loaded; for replacement of loaded data
    //                                           uses [DataXML] and [DataText]
    // - loadingDescription           : String - description of loading for concrete item
    // - afterLoadDescription         : String - result text for concrete item
    // - specialObjectId4LoadingTexts : String - special object for showing messages of loading of
    //                                           concrete item
    // - specialObjectId4ErrorTexts   : String - special object for showing error messages of loading
    //                                           of concrete item
    function getDataByItems(url, method2Execute, loadingDescription, afterLoadDescription, 
        specialObjectId4LoadingTexts, specialObjectId4ErrorTexts, method2Execute4NoItems)
    {
        // adding new item to front
        if (url != null)
        {
            if (url != "")
            {
                // creating new front item
                var newFrontItem = new LoadingFrontItem(url, method2Execute, loadingDescription, 
                    afterLoadDescription, specialObjectId4LoadingTexts, specialObjectId4ErrorTexts, 
                    method2Execute4NoItems);
                // adding item into front
                loadingFront[loadingFront.length] = newFrontItem;
            }
        }
        
        // work with concrete data loading
        if (!loadingData)
        {
            // if there are no data to load, exit loading method
            if (loadingFront.length == 0)
                return;
        
            // setting indication parameters into loading state
            loadingData = true;
            resultReady = false;

            // setting right object according to web browser
            if (window.XMLHttpRequest)
            {
                // code for Mozilla, etc.
                xmlhttp = new XMLHttpRequest();
            } 
            else 
            {
                // code for MS Internet Explorer
                try
                {
                    xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
                }
                catch (error)
                {
                    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");                    
                }
            }

            if (xmlhttp != null) 
            {
                // setting the action after receiving data
                xmlhttp.onreadystatechange = function()
                { 
                    if (xmlhttp.readyState == 4)  // check if receiving action is completed
                    {
                        if(xmlhttp.status == 200) // check if there is not any error
                        {
                            // ******************************************************************************
                            // work with received data ------------------------------------------------------
                            
                            // adding loaded data into fields
                            var xmlResponse = null;
                            xmlResponse = load_xml_content_string(xmlhttp.responseText);
                            if (xmlhttp.responseXML == null)
                            {
                                try
                                {
                                    xmlResponse = load_xml_content_string(xmlhttp.responseText);
                                } catch (error) {}
                            }
                            else
                            {
                                xmlResponse = xmlhttp.responseXML;
                            }
                            resultsXML[resultsXML.length] = xmlResponse;
                            resultsText[resultsText.length] = xmlhttp.responseText;
                            
                            // adding data into variables for lastly loaded data
                            lastResultXML = xmlResponse;
                            lastResultText = xmlhttp.responseText;
                            
                            // changing indicators
                            resultReady = true;
                            loadingData = false;
                            
                            // running method for loaded data
                            if (loadingFront[0].getMethod().indexOf("[DataText]") > -1)
                            {
                                eval(loadingFront[0].getMethod().toString().replace("[DataText]",removeNewLines(lastResultText.replace('\\','\\\\'))));
                            }
                            else
                            {
                                eval(loadingFront[0].getMethod().toString().replace("[DataXML]","lastResultXML"));
                            }
                            
                            // message loading started
                            showMessage(loadingFront[0].getAfterLoadDescription(), afterLoadMessage, 
                                (loadingFront[0].getLoadingTextsObj() != null ? loadingFront[0].getLoadingTextsObj() : loaderObject));
                            
                            // removing now completly worked out item
                            loadingFront.splice(0,1);
                            
                            // executing next loading according to the loading front
                            if (loadingFront.length > 0)
                            {
                                getDataByItems();
                            }
                            
                            // end of work with received data -----------------------------------------------
                            // ******************************************************************************
                        }
                        else
                        {
                            // error message when we are not able to transfer data
                            showMessage(retreivingDataErrorMessage, defaultRetreivingDataErrorMessage, 
                                errorObject);
                        }
                    }
                };
                
                // message loading started
                showMessage(loadingFront[0].getLoadingDescription(), loadingMessage, 
                    (loadingFront[0].getLoadingTextsObj() != null ? loadingFront[0].getLoadingTextsObj() : loaderObject));
                    
                // start data transfer
                xmlhttp.open("GET", loadingFront[0].getUrl(), true); //+ (loadingFront[0].getUrl().indexOf("?") > -1 ? "&" : "?") + 
                    //"dsasfkiugbgadwqtruzozs=" + Math.random().toString(), true);
                xmlhttp.send(null);
            }
            else
            {
                // general error message when the browser does not support general AJAX object
                showMessage(generalErrorMessage, defaultGeneralErrorMessage, errorObject);
            }
        }
    }
    this.getDataByItems = getDataByItems;
    
    // Converts pure String into parseable XML object. -------------------------------------------------
   	function load_xml_content_string(xmlData) {
		if (window.ActiveXObject) {
			//for IE
			xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
			xmlDoc.async="false";
			xmlDoc.loadXML(xmlData);
			return xmlDoc;
		} else if (document.implementation && document.implementation.createDocument) {
			//for Mozila
			parser=new DOMParser();
			xmlDoc=parser.parseFromString(xmlData,"text/xml");
			return xmlDoc;
		}
	}
	
	// Removes all line ends from the text. ------------------------------------------------------------
	function removeNewLines(text)
	{
	    var result = text;
	    while (result.indexOf("\n") > -1)
	    {
	        result = result.replace("\n", " ");
	    }
	    return result;
	}

    
    // Method for showing message. ---------------------------------------------------------------------
    // - actualMessage  : String                - actual message to show - not obligated
    // - defaultMessage : String                - default message to show - obligated
    // - object4Message : HTMLElement reference - HTML element for viewing message - not obligated
    function showMessage(actualMessage, defaultMessage, object4Message)
    {
        if (actualMessage == null)
        {
            if (object4Message == null)
            {
                //if (defaultMessage != null) alert(defaultMessage);
            }
            else
            {
                object4Message.innerHTML = defaultMessage;
            }
        }
        else
        {
            if (actualMessage != "")
            {
                if (object4Message == null)
                {
                    //if (actualMessage != null) alert(actualMessage);
                }
                else
                {
                    object4Message.innerHTML = actualMessage;
                }
            }
        }
    }
    
    // Method for reading data from the XML object. ----------------------------------------------------
    // - xmlData        : XmlDataObject - object with data to read
    // - method2Execute : String        - string command for execution of method to worked out one item
    //                                    => for actual item is used translation mark [DATA]
    //                                    => for actual index is used translation mark [INDEX]
    //                                    => for count of items is used translation mark [COUNT]
    //                                    => for attribute values in field by attributes names [ATTRIBUTES]
    function readXMLResults(xmlData, centralItemsName, method2Execute, method2Execute4NoItems)
    {
        //alert((new XMLSerializer()).serializeToString(xmlData));
        var items = xmlData.getElementsByTagName(centralItemsName);
        if (items.length > 0)
        {
            for (var i = 0; i < items.length; i++)
            {
                var attributes = new Array();
                for (var y = 0; y < items[i].attributes.length; y++)
                {
                    attributes[items[i].attributes[y].name] = items[i].attributes[y].nodeValue;
                }
                eval(method2Execute.replace("[DATA]", "items[i]").replace("[INDEX]","i").replace("[COUNT]","items.length").replace("[ATTRIBUTES]","attributes"));
            }
        }
        else
        {
			// if there are no records and method for no-records reaction is defined, eval the method
            if ((method2Execute4NoItems != null) && (method2Execute4NoItems != ""))
			{
				eval(method2Execute4NoItems);
			}
        }
    }
    
}

// **************************************************************************************************************************
// Object for storage of data for one item in AJAX loading front.
// --------------------------------------------------------------------------------------------------------------------------
// - itemUrl                  : String - full URL location of data to load
// - itemMethod               : String - method to execute after sucessful loading
// - itemLoadingDescription   : String - loading description
// - itemAfterLoadDescription : String - text to show after loading
// - itemLoadingTextsObjId    : String - Id of HTML element for viewing of loading texts
// - itemErrorTextsObjId      : String - Id of HTML element for viewing of error texts
// **************************************************************************************************************************
function LoadingFrontItem(itemUrl, itemMethod, itemLoadingDescription, itemAfterLoadDescription, itemLoadingTextsObjId, 
    itemErrorTextsObjId, itemMethod4NoItems)
{
    // -------------------------------------------------------------------------------------------------
    // ATTRIBUTES
    // -------------------------------------------------------------------------------------------------

    // attributes
    var url = "";
    var method = "";
    var method4NoItems = "";
    var loadingDescription = null;
    var afterLoadDescription = null;
    
    var loadingTextsObj = null;
    var errorTextsObj = null;
    
    // -------------------------------------------------------------------------------------------------
    // ATTRIBUTES - filling from the constructor
    // -------------------------------------------------------------------------------------------------
    this.url = (itemUrl != null ? itemUrl : this.url);
    this.method = (itemMethod != null ? itemMethod : this.method);
    this.method4NoItems = (itemMethod4NoItems != null ? itemMethod4NoItems : this.method4NoItems);
    this.loadingDescription = (itemLoadingDescription != null ? itemLoadingDescription : loadingDescription);
    this.afterLoadDescription = (itemAfterLoadDescription != null ? itemAfterLoadDescription : afterLoadDescription);
    
    this.loadingTextsObj = (itemLoadingTextsObjId != null ? document.getElementById(itemLoadingTextsObjId) : loadingTextsObj);
    this.errorTextsObj = (itemErrorTextsObjId != null ? document.getElementById(itemErrorTextsObjId) : errorTextsObj);
    
    // -------------------------------------------------------------------------------------------------
    // METHODS FOR GETTING DATA
    // -------------------------------------------------------------------------------------------------
    
    // Returns url attribute. --------------------------------------------------------------------------
    function getUrl()
    {
        return this.url;
    }
    this.getUrl = getUrl;
    
    // Returns method attribute. -----------------------------------------------------------------------
    function getMethod()
    {
        return this.method;
    }
    this.getMethod = getMethod;
    
    // Returns method to execute when there are no loaded items. ---------------------------------------
    function getMethod4NoItems()
    {
        return this.method;
    }
    this.getMethod4NoItems = getMethod4NoItems;
    
    // Returns loading description attribute. ----------------------------------------------------------
    function getLoadingDescription()
    {
        return this.loadingDescription;
    }
    this.getLoadingDescription = getLoadingDescription;
    
    // Returns after load description. -----------------------------------------------------------------
    function getAfterLoadDescription()
    {
        return this.afterLoadDescription;
    }
    this.getAfterLoadDescription = getAfterLoadDescription;
    
    // Returns object for showing loading texts. -------------------------------------------------------
    function getLoadingTextsObj()
    {
        return this.loadingTextsObj;
    }
    this.getLoadingTextsObj = getLoadingTextsObj;
    
    // Returns object for showing error texts. ---------------------------------------------------------
    function getErrorTextsObj()
    {
        return this.errorTextsObj;
    }
    this.getErrorTextsObj = getErrorTextsObj;
    
    // -------------------------------------------------------------------------------------------------
    // METHODS FOR SETTING DATA
    // -------------------------------------------------------------------------------------------------
    
    // Sets url attribute. -----------------------------------------------------------------------------
    // - value : String - new URL
    function setUrl(value)
    {
        this.url = value;
    }
    this.setUrl = setUrl;
    
    // Sets method attribute. --------------------------------------------------------------------------
    // - value : String - new method
    function setMethod(value)
    {
        this.method = value;
    }
    this.setMethod = setMethod;
    
    // Sets method attribute. --------------------------------------------------------------------------
    // - value : String - new method
    function setMethod4NoItems(value)
    {
        this.method4NoItems = value;
    }
    this.setMethod4NoItems = setMethod4NoItems;
    
    // Sets loading description attribute. -------------------------------------------------------------
    // - value : String - new loading description
    function setLoadingDescription(value)
    {
        this.loadingDescription = value;
    }
    this.setLoadingDescription = setLoadingDescription;
    
    // Sets after load description. --------------------------------------------------------------------
    // - value : String - new after load description
    function setAfterLoadDescription(value)
    {
        this.afterLoadDescription = value;
    }
    this.setAfterLoadDescription = setAfterLoadDescription;
    
    // Sets object for showing loading texts. ----------------------------------------------------------
    // - value : HTMLElement reference - new object for showing loading texts
    function setLoadingTextsObj(value)
    {
        this.loadingTextsObj = value;
    }
    this.setLoadingTextsObj = setLoadingTextsObj;
    
    // Sets object for showing error texts. ------------------------------------------------------------
    // - value : HTMLElement reference - new object for showing error texts
    function setErrorTextsObj(value)
    {
        this.errorTextsObj = value;
    }
    this.setErrorTextsObj = setErrorTextsObj;
    
}


