﻿/*
innerHTML, innerTEXT.... what else
sjove eksempler.?
hvad med formularer... fx drop-downs...?
kun id'er.. ikke classer?
Kan man bruge POST i stedet for GET?
*/

// lav eksempler med formularer også ... fx onchange i et felt, opdateringer på skærm... men hvad med data i andre formularer..... det skal være muligt at tagergette <option> fx i en dropdown...
// tjek lige : http://docs.composite.net/C1/HTML/FrontendFAQ.aspx?q=Can+I+call+C1+Functions+AJAX+style+from+JavaScript+or+Flash%3F



/*
To-the-bone C1/AJAX, by Mads Yhde, a public demonstration of my noob state of mind
transforming into (hopefully) Zen-like master of web development state... Really... 
I'm not sure what I'm doing so please copy-paste at your own risk. The goal is to be 
approximately right, rather than precisely wrong.

Use this script for rapid functionality and rich user experience - the only requirement 
is that you say my name aloud 10 times, blindfolded, while standing upside down. 

Leave me a token of appreciation if you want. All comments are welcome. Cheers

may@acto.dk or http://www.linkedin.com/in/madsyhde


**************
HOW TO USE:
1. Make sure all prerequisites are fullfilled 
2. Call JavaScript function iAjax() 
3. See example of use below

PEREQUISITES:
- Page HTML: <meta name="pageId" value="<contains the current C1 page id>"/>
- Page HTML: <script type="text/javascript" src="/Frontend/Ajax/Ajax.js"></script>
- C1 datatype: Datatypes Ajax.ValiXsltFunctions with valid namespace + functioname combination i.e. "TestNamespace.NameOfXsltFunction".
- Files: all files in the subfolder /Frontend/Ajax

IAJAX() FUNCTION PARAMETERS ((*) REQUIRED):
- HtmlElementId (*): The ID of the HTML element that should be AJAX'ed.
- XsltFunctionName (*): Name of the XSLT function to be executed.
- HtmlElementIdSpinner: The ID of the HTML element that should display a spinner while request is in process. Leave empty if no spinning is needed.
- CustomParams: Formatted: "&x1=y1&x2=y2", please notice in XSLT the syntax is different for ampersand (&): "&amp;x1=y1&amp;x2=y2".
- Culture: Force a specific language "da-DK", "en-US". Otherwise it will take the culture from the context.
- Debug: true / false - default false. Gives javascript alerts with information in context.

EXAMPLES OF USE:
    
Notice in the Example HTML below that you can make use of the different javascript events such as "onmouseover", "onclick", "onmouseout". For more JavaScript events look here: TODO.

Example HTML: 
<html>
    <head>
        <meta name="PageId" value="c1 page guid"/>
        <script type="text/javascript" src="/Frontend/Ajax/Ajax.js"></script>
    </head>
    <body>
        <div id="DiffentKindsOfAjaxCalls">
            <a onmouseover="iAjax('Ajaxify', 'Navigation.Siblings', 'AjaxSpinnerDiv');">Siblings (mouseover)</a>
            <a onclick="iAjax('Ajaxify', 'Navigation.Children', 'AjaxSpinnerDiv');">Children (onclick)</a>
            <a onmouseout="iAjax('Ajaxify', 'News.NewsArchive', 'AjaxSpinnerDiv');">NewsArchive (onmouseout)</a>
            <a onclick="iAjax('Ajaxify', 'Navigation.Children', 'AjaxSpinnerDiv', '&amp;ElementId=123&amp;sort=descending', 'en-US', true);">Children with custom parameters and debug info (onclick)</a>
            <a onclick="iAjax('Ajaxify', 'Navigation.Children', 'AjaxSpinnerDiv', '', '', true);">Children with debug info (onclick)</a>
        </div>
        <div id="AjaxSpinnerDiv"></div>
        <hr/>
        <div id="Ajaxify">AJAX container before asynchronous call</div>
    </body>
</html>
*/

function iAjax(HtmlElementId, XsltFunctionName, HtmlElementIdSpinner, CustomParams, Culture, Debug) 
{
    // *****************
    // Qualify inddata
    // *****************
    HtmlElementIdSpinner = (HtmlElementIdSpinner == undefined) ? '' : HtmlElementIdSpinner;
    CustomParams = (CustomParams == undefined) ? '' : CustomParams;
    Culture = (Culture == undefined) ? '' : Culture;
    Debug = (Debug == undefined) ? false : Debug;

    var HtmlElement = document.getElementById(HtmlElementId);
    var HtmlElementSpinner = document.getElementById(HtmlElementIdSpinner);

    // If required values are not present then we abort mission. If the container with @id attribute to display result does not exist then abort mission
    if (HtmlElementId.length == 0 || XsltFunctionName.length == 0 || HtmlElement == null) {
        return;
    }

    // *****************
    // Debug handling
    // *****************
    if (Debug) { alert("DEBUG\n\nYou are in debug mode - displaying all sorts of valuable information...\n\nInput parameteres:\n\nHtmlElementId: " + HtmlElementId + "\nHtmlElementIdSpinner: " + HtmlElementIdSpinner + "\nXsltFunctionName: " + XsltFunctionName + "\nCustomParams: " + CustomParams + "\nCulture: " + Culture); }
    if (Debug) { alert("DEBUG:\n\nCheck if HtmlElementId: '" + HtmlElementId + "' exixts... " + (HtmlElement != null) + "\n\nCheck if HtmlElementIdSpinner: '" + HtmlElementIdSpinner + "' exixts... " + (HtmlElementSpinner != null));}

    // *****************
    // Scopes handling
    // *****************
    var datascope = "";
    var culturescope = "";
    var pagescope = "";
    var functionscope = "";
    var functionparamsscope = "";

    // Data scope
    if (getQSparameter("dataScope").length > 0) {
        datascope = "&dataScope=" + getQSparameter("dataScope");
    }

    // Culture scope
    if (Culture.length > 0) {
        culturescope = "&cultureScope=" + Culture;
    }
    else if (getQSparameter("cultureScope").length > 0) {
        culturescope = "&cultureScope=" + getQSparameter("cultureScope");
    }

    // Page scope
    var currentpageid = document.getElementsByName("PageId").item(0).attributes.getNamedItem("content").value; // OBS: reading from the <meta name="PageId" value=""/>  ... this is not absolutely necessary unless you call a XSLT function that requires the page scope - i.e. a sitemap function
    if (currentpageid.length > 0) {
        pagescope = "pageId=" + currentpageid;
    }

    // Function scope
    if (XsltFunctionName.length > 0) {
        functionscope = "&XsltFunctionName=" + XsltFunctionName;
    }

    // Function params scope
    if (CustomParams.length > 0 && CustomParams.substr(0, 1) == "&") {
        functionparamsscope = CustomParams;
    }


    // *****************
    // It's a Kind of Magic
    // *****************
    $(HtmlElement.nodeName + "#" + HtmlElementId).fadeOut('slow', function () {

        var URL = "/Frontend/Ajax/AjaxData.ashx?" + pagescope + functionscope + functionparamsscope + culturescope + datascope;

        if (Debug) { alert("DEBUG:\n\nURL: \n" + URL); }

        // create the connection
        xmlhttp = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
        xmlhttp.open("GET", URL, true);

        xmlhttp.onreadystatechange = function () {
            if (HtmlElementIdSpinner != '') {
                var spinner = '3'; // '2' or '3' also valid spinners
                HtmlElementSpinner.innerHTML = '<img alt=\""\ src=\"/Frontend/Ajax/AjaxSpinner' + spinner + '.gif\"/>';
            }

            if (Debug) {
                alert("DEBUG\n\nLooking for.. readystate=4 and status=200\n\nCurrent readyState: " + xmlhttp.readyState + "\ncurrent httpstatus: " + xmlhttp.status);
            }

            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                HtmlElement.innerHTML = xmlhttp.responseText;

                for (var i = 0; i < HtmlElement.getElementsByTagName('script').length; i++) {
                    eval((HtmlElement.getElementsByTagName('script')[i]).text);
                }

                HtmlElementSpinner.innerHTML = '';
            }

            // Getting the status is only valid if we check for readyState also (otherwise IE will throw unspecified error)
            if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
                HtmlElementSpinner.innerHTML = '[ERROR ' + xmlhttp.status + ']';
            }
        }


        HtmlElement.innerHTML = "";
        xmlhttp.send(null);
    });

	$(HtmlElement.nodeName + "#" + HtmlElementId).fadeIn();

}

function getQSparameter(name) {
    name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regexS = "[\\?&]" + name + "=([^&#]*)";
    var regex = new RegExp(regexS);
    var results = regex.exec(window.location.href);
    if (results == null)
        return "";
    else
        return results[1];
}
