//AJAX CLASSES

function moo()
{
    alert('Moo!');
}

var Ajax = new Object();

Ajax.READY_STATE_UNINITIALIZED = 0;
Ajax.READY_STATE_LOADING = 1;
Ajax.READY_STATE_LOADED = 2;
Ajax.READY_STATE_INTERACTIVE = 3;
Ajax.READY_STATE_COMPLETE = 4;

Ajax.SUCCESS_RESPONSE = 200;
Ajax.NOT_FOUND_RESPONSE = 404;
Ajax.FORBIDDEN_RESPONSE = 403;

Ajax.GET_METHOD = 'GET';
Ajax.POST_METHOD = 'POST';
Ajax.CONTENT_TYPE_HEADER = 'Content-Type';
Ajax.CONTENT_TYPE_TEXT = 'text/plain';
Ajax.CONTENT_TYPE_XML = 'text/xml';
Ajax.CONTENT_TYPE_FORM_DATA = 'application/x-www-form-urlencoded';
Ajax.MICROSOFT_OLD_ACTIVE_X_HTTP_REQUEST_OBJECT = 'Microsoft.XMLHTTP';
Ajax.MICROSOFT_NEW_ACTIVE_X_HTTP_REQUEST_OBJECT = 'Msxml2.XMLHTTP';

Ajax.REQUEST_ID_PARAMETER_NAME = "requestId";

Ajax.GET_MODE = false;
Ajax.POST_MODE = true;

var Dom = new Object();

Dom.ELEMENT_NODE = 1;
Dom.ATTRIBUTE_NODE = 2;
Dom.TEXT_NODE = 3;
Dom.CDATA_SELECTION_NODE = 4;
Dom.ENTITY_REFERENCE_NODE = 5;
Dom.ENTITY_NODE = 6;
Dom.PROCESSING_INSTRUCTION_NODE = 7;
Dom.COMMENT_NODE = 8;
Dom.DOCUMENT_NODE = 9;

Dom.MICROSOFT_OLD_ACTIVE_X_DOM_DOCUMENT_OBJECT = 'Msxml.DOMDocument';
Dom.MICROSOFT_NEW_ACTIVE_X_DOM_DOCUMENT_OBJECT = 'Msxml2.DOMDocument';

//Represents a name value name pair parameter which can be used for example in URLs
Ajax.Parameter = function( name, value )
{
    this.name = name;
    this.value = value;
}
Ajax.Parameter.prototype =
{
    getName:function()
    {
        return this.name;
    },
    setName:function( name )
    {
        this.name = name;
    },
    getValue:function()
    {
        return this.value;
    },
    setValue:function( value )
    {
        this.value = value;
    },
    toURLParamString:function()
    {
        if ( this.value != null )
        {
            return (this.name + "=" + encodeURI(this.value.toString()));
        }
        else
        {
            return (this.name + "=null");
        }
    },
    toParamString:function()
    {
        if ( this.value != null )
        {
            return (this.name + "=" + this.value.toString());
        }
        else
        {
            return (this.name + "=null");
        }
    }
}

//Represents a name value name pair parameter which can be used for example in URLs
Ajax.Parameters = function()
{
    this.parameterArray = new Array();
}
Ajax.Parameters.prototype =
{
    add:function( name, value )
    {
        return this.parameterArray.push(new Ajax.Parameter(name, value));
    },
    getNoOfParameters:function()
    {
        return this.parameterArray.length;
    },
    isEmpty:function()
    {
        return this.parameterArray.length == 0;
    },
    toURLParamString:function()
    {
        var urlString = "";
        var first = true;
        for ( var parameterIndex = 0; parameterIndex < this.parameterArray.length; parameterIndex++ )
        {
            if ( first )
            {
                first = false;
            }
            else
            {
                urlString += '&';
            }
            urlString += this.parameterArray[parameterIndex].toURLParamString();
        }
        return urlString;
    },
    toParamString:function()
    {
        var paramString = "";
        var first = true;
        for ( var parameterIndex = 0; parameterIndex < this.parameterArray.length; parameterIndex++ )
        {
            if ( first )
            {
                first = false;
            }
            else
            {
                paramString += ',';
            }
            paramString += this.parameterArray[parameterIndex].toParamString();
        }
        return paramString;
    }
}

Ajax.ContentLoader = function( url, parent, contentHandlingFunction, parameters, sendMethod, xml, asynchronous )
{
    this.url = url;
    this.contentHandlingFunction = contentHandlingFunction;
    this.errorMessage = null;
    this.requestObject = null;
    this.parameters = parameters;
    if ( this.parameters == null )
    {
        this.parameters = new Ajax.Parameters();
    }
    this.xml = xml;
    this.asynchronous = asynchronous;
    this.sendMode = Ajax.GET_MODE;
    if ( sendMethod != null && sendMethod != Ajax.POST_METHOD )
    {
        this.sendMode = Ajax.POST_MODE;
    }
    else
    {
        this.appendRequestId();
    }
}
Ajax.ContentLoader.prototype =
{
    loadRequestObject:function()
    {
        this.requestObject = null;
        if ( window.XMLHttpRequest )
        {
            try
            {
                this.requestObject = new XMLHttpRequest();
            }
            catch ( error )
            {
                this.errorMessage = "Error creating native AJAX request";
            }
        }
        else if ( window.ActiveXObject )
        {
            try
            {
                this.requestObject = new ActiveXObject(Ajax.MICROSOFT_NEW_ACTIVE_X_HTTP_REQUEST_OBJECT);
            }
            catch ( oldMicrosoft )
            {
                try
                {
                    this.requestObject = new ActiveXObject(Ajax.MICROSOFT_OLD_ACTIVE_X_HTTP_REQUEST_OBJECT);
                }
                catch ( noneOfTheAbove )
                {
                    this.errorMessage = "Error creating ActiveX AJAX request";
                }
            }
        }
        else
        {
            this.errorMessage = "AJAX Not Supported";
        }
    },
    createXMLDocument:function()
    {
        var xmlDocument = null;
        if ( document.implementation && document.implementation.createDocument )
        {
            xmlDocument = document.implementation.createDocument("", "", null);
        }
        else if ( typeof ActiveXObject != "undefined" )
        {
            var msActiveXXmlDoc = null;
            try
            {
                msActiveXXmlDoc = new ActiveXObject(Dom.MICROSOFT_NEW_ACTIVE_X_DOM_DOCUMENT_OBJECT);
            }
            catch ( notSupported )
            {
                msActiveXXmlDoc = new ActiveXObject(Dom.MICROSOFT_OLD_ACTIVE_X_DOM_DOCUMENT_OBJECT);
            }
            xmlDocument = msActiveXXmlDoc;
        }
        return xmlDocument;
    },
    parseResponseTextToXML:function()
    {
        if ( this.requestObject != null && this.requestObject.responseText != null && this.requestObject.responseText.length > 0 )
        {
            try
            {
                var domParser = new DOMParser();
                return (domParser.parseFromString(this.requestObject.responseText, Ajax.CONTENT_TYPE_XML));
            }
            catch ( error )
            {
                this.errorMessage = 'XML parse error parsing response text to XML';
            }
        }
        return null;
    },
    overideMimeType:function( mimeType )
    {
        if ( this.requestObject != null && mimeType != null && this.requestObject.overrideMimeType )
        {
            this.requestObject.overrideMimeType(mimeType);
        }
    },
    generateRequestId:function()
    {
        return Math.floor(Math.random() * 1000000);
    },
    appendRequestId:function()
    {
        this.parameters.add(Ajax.REQUEST_ID_PARAMETER_NAME, this.generateRequestId());
    },
    initRequest:function()
    {
        this.loadRequestObject();
        if ( this.requestObject != null )
        {
            var loader = this;
            this.requestObject.onreadystatechange = function()
            {
                loader.handleStateChange.call(loader);
            }
            return true;
        }
        else
        {
            return false;
        }
    },
    sendGetRequest:function()
    {
        if ( this.requestObject != null )
        {
            var getURL = this.url;
            if ( this.parameters != null && !this.parameters.isEmpty() )
            {
                getURL += ('?' + this.parameters.toURLParamString());
            }
            this.requestObject.open(Ajax.GET_METHOD, getURL, this.asynchronous);
            this.requestObject.send(null);
            return true;
        }
        else
        {
            return false;
        }
    },
    sendPostRequest:function()
    {
        if ( this.requestObject != null )
        {
            this.requestObject.open(Ajax.POST_METHOD, this.url, this.asynchronous);
            try
            {
                this.requestObject.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            }
            catch( functionNotSupported )
            {
            }
            this.requestObject.send(this.parameters);
            return true;
        }
        else
        {
            return false;
        }
    },
    sendRequest:function()
    {
        if ( this.requestObject != null )
        {
            if ( this.sendMode == Ajax.GET_MODE )
            {
                return this.sendGetRequest();
            }
            else if ( this.sendMode == Ajax.POST_MODE )
            {
                return this.sendPostRequest();
            }
            else
            {
                return this.sendGetRequest();
            }
        }
        else
        {
            return false;
        }
    },
    getRequestStatus:function()
    {
        var status = 0;
        if ( this.requestObject != null )
        {
            try
            {
                status = this.requestObject.status;
            }
            catch ( mozillaBug )
            {
                status = Ajax.SUCCESS_RESPONSE;
            }
        }
        return status;
    },
    isRequestFinished:function()
    {
        return this.requestObject != null && (this.requestObject.readyState == Ajax.READY_STATE_COMPLETE);
    },
    isRequestSuccessful:function()
    {
        return (this.getRequestStatus() == Ajax.SUCCESS_RESPONSE);
    },
    closeRequest:function()
    {
        try
        {
            this.requestObject.close();
        }
        catch( notSupported )
        {
        }
    },
    cleanupAfterResponse:function()
    {
        this.requestObject = null;
    },
    handleStateChange:function()
    {
        if ( this.isRequestFinished() )
        {
            if ( this.isRequestSuccessful() )
            {
                this.closeRequest();
                this.handleResponse();
            }
            this.cleanupAfterResponse();
        }
    },
    handleResponse:function()
    {
        if ( this.requestObject != null && this.contentHandlingFunction != null )
        {
            var caller = this;
            var contentType = this.requestObject.getResponseHeader(Ajax.CONTENT_TYPE_HEADER);
            if ( contentType )
            {
                if ( contentType == Ajax.CONTENT_TYPE_XML )
                {
                    this.contentHandlingFunction.call(caller, this.requestObject.responseXML);
                }
                else
                {
                    this.contentHandlingFunction.call(caller, this.requestObject.responseText);
                }
            }
            else
            {
                this.contentHandlingFunction.call(caller, this.requestObject.responseText);
            }
        }
    }
}



//Class Utility
Dom.isOfClass = function( classNames, desiredClass )
{
    var classNameArray = classNames.split();
    for ( var index = 0; index < classNameArray.length; index++ )
    {
        if ( classNameArray[index] == desiredClass )
        {
            return true;
        }
    }
    return false;
}

//Page Update Functions
var JoklWebsite = new Object()

JoklWebsite.COMMAND_PARAMETER = 'command';
JoklWebsite.AJAX_PARAMETER = 'ajax';
JoklWebsite.GET_EIGHT_BALL_MESSAGE_COMMAND = 'get_eight_ball_message';
JoklWebsite.GET_FORTUNE_COMMAND = 'get_fortune';
JoklWebsite.EIGHT_BALL_MESSAGE_ELEMENT_ID = 'magic8BallAnswer';
JoklWebsite.FORTUNE_ELEMENT_ID = 'fortuneCookieAnswer';
JoklWebsite.WEBSITE_PORTAL_URL = './portal/website';

JoklWebsite.MessageLoader = function( portalUrl )
{
    this.portalUrl = portalUrl;
}
JoklWebsite.MessageLoader.prototype =
{
    sendRequest:function( url, responseHandlingFunction, sendMethod, parameters )
    {
        var thisObject = this;
        var loader = new Ajax.ContentLoader(url, thisObject, responseHandlingFunction, parameters, sendMethod, false, true);
        var success = loader.initRequest();
        if ( success )
        {
            success = loader.sendRequest();
        }
        return success;
    },
    requestEightBallMessage:function()
    {
        var parameters = new Ajax.Parameters();
        parameters.add(JoklWebsite.COMMAND_PARAMETER, JoklWebsite.GET_EIGHT_BALL_MESSAGE_COMMAND);
        this.sendRequest(this.portalUrl, this.receiveEightBallMessage, Ajax.POST_METHOD, parameters);
    },
    requestFortuneCookieMessage:function()
    {
        var parameters = new Ajax.Parameters();
        parameters.add(JoklWebsite.COMMAND_PARAMETER, JoklWebsite.GET_FORTUNE_COMMAND);
        this.sendRequest(this.portalUrl, this.receiveFortuneCookieMessage, Ajax.POST_METHOD, parameters);
    },
    receiveEightBallMessage:function( message )
    {
        if ( message )
        {
            var answer = document.getElementById(JoklWebsite.EIGHT_BALL_MESSAGE_ELEMENT_ID);
            if ( answer )
            {
                answer.firstChild.nodeValue = message;
            }
        }
    },
    receiveFortuneCookieMessage:function( message )
    {
        if ( message )
        {
            var answer = document.getElementById(JoklWebsite.FORTUNE_ELEMENT_ID);
            if ( answer )
            {
                answer.firstChild.nodeValue = message;
            }
        }
    }
}

JoklWebsite.PageContentLoader = function( portalUrl )
{
    this.portalUrl = portalUrl;
}
JoklWebsite.PageContentLoader.prototype =
{
    sendRequest:function( url, responseHandlingFunction, sendMethod, parameters )
    {
        var thisObject = this;
        var loader = new Ajax.ContentLoader(url, thisObject, responseHandlingFunction, parameters, sendMethod, true, true);
        var success = loader.initRequest();
        if ( success )
        {
            success = loader.sendRequest();
        }
        return success;
    },
    duplicateNodeAttributes:function( source, target )
    {
        var attributes = source.attributes;
        if ( attributes != null && attributes.length > 0 )
        {
            var currentAttributeName = null;
            var currentAttributeValue = null;
            for ( var index = 0; index < attributes.length; index++ )
            {
                currentAttributeName = attributes[index].nodeName
                currentAttributeValue = attributes[index].nodeValue
                if ( currentAttributeName.toLowerCase() == 'class' || currentAttributeName.toLowerCase() == 'classname' )
                {
                    target.className = currentAttributeValue;
                }
                else
                {
                    target.setAttribute(currentAttributeName, currentAttributeValue);
                }
            }
        }
    },
    duplicateElementNode:function( node )
    {
        var newElement = document.createElement(node.tagName);
        this.duplicateNodeAttributes(node, newElement);
        if ( node.childNodes != null && node.childNodes.length > 0 )
        {
            for ( var index = 0; index < node.childNodes.length; index++ )
            {
                var newChild = this.duplicateXMLNodeToDocument(node.childNodes[index]);
                newElement.appendChild(newChild);
            }
        }
        return newElement;
    },
    duplicateTextNode:function( node )
    {
        return document.createTextNode(node.nodeValue);
    },
    duplicateXMLNodeToDocument:function( node )
    {
        if ( node.nodeType == Dom.ELEMENT_NODE )
        {
            return this.duplicateElementNode(node);
        }
        else if ( node.nodeType == Dom.ATTRIBUTE_NODE )
        {
            return null;
        }
        else if ( node.nodeType == Dom.TEXT_NODE )
        {
            return this.duplicateTextNode(node);
        }
        else if ( node.nodeType == Dom.CDATA_SELECTION_NODE )
        {
            return null;
        }
        else if ( node.nodeType == Dom.ENTITY_REFERENCE_NODE )
        {
            return null;
        }
        else if ( node.nodeType == Dom.ENTITY_NODE )
        {
            return null;
        }
        else if ( node.nodeType == Dom.PROCESSING_INSTRUCTION_NODE )
        {
            return null;
        }
        else if ( node.nodeType == Dom.COMMENT_NODE )
        {
            return null;
        }
        else if ( node.nodeType == Dom.DOCUMENT_NODE )
        {
            return null;
        }
    },
    changePageTitle:function( xmlContent )
    {
        document.title = xmlContent.getElementsByTagName("title")[0].firstChild.data;
        ;
    },
    removeExistingPageContent:function()
    {
        var layoutTable = document.getElementById("layouttable");
        var endOfHead = document.getElementById("endofhead");
        var startOfFoot = document.getElementById("startoffoot");
        var tableBody = layoutTable.tBodies[0];
        var tableRows = tableBody.childNodes;
        var index = 0;
        while ( index < tableRows.length && tableRows[index] != endOfHead )
        {
            index++;
        }
        if ( tableRows[index] == endOfHead )
        {
            index++;
            while ( index < tableRows.length && tableRows[index] != startOfFoot )
            {
                tableBody.removeChild(tableRows[index]);
            }
        }
    },
    insertNewPageContent:function( xmlContent )
    {
        var startOfFoot = document.getElementById("startoffoot");
        var responseContent = xmlContent.getElementsByTagName("content")[0];
        var contentNodes = responseContent.childNodes;
        var layoutTable = document.getElementById("layouttable");
        var tableBody = layoutTable.tBodies[0];
        var newTag = null;
        for ( var index = 0; index < contentNodes.length; index++ )
        {
            var newDocumentNode = this.duplicateXMLNodeToDocument(contentNodes[index]);
            tableBody.insertBefore(newDocumentNode, startOfFoot);
        }
        var eightBall = document.getElementById('eightBallImage');
        if ( eightBall )
        {
            eightBall.onclick = this.requestEightBallMessage;
        }
        var fortuneCookie = document.getElementById('fortuneCookieImage');
        if ( fortuneCookie )
        {
            fortuneCookie.onclick = this.requestFortuneCookieMessage;
        }
    },
    recieveNewPageContentXML:function( xmlContent )
    {
        if ( xmlContent )
        {
            this.removeExistingPageContent();
            this.changePageTitle(xmlContent);
            this.insertNewPageContent(xmlContent);
        }
    },
    requestContent:function( contentUrl )
    {
        var parameters = new Ajax.Parameters();
        parameters.add(JoklWebsite.AJAX_PARAMETER, 'true');
        var success = this.sendRequest(contentUrl, this.recieveNewPageContentXML, 'POST', parameters);
        if ( !success )
        {
            var redirectURL = window.location.href;
            var lastSlashIndex = redirectURL.lastIndexOf('/');
            if ( lastSlashIndex < 8 )
            {
                redirectURL = redirectURL + contentUrl;
            }
            else
            {
                redirectURL = redirectURL.substring(0, (lastSlashIndex + 1)) + contentUrl;
            }
            window.location.href = redirectURL;
        }
    },
    linkToTag:function( tag )
    {
        if ( tag.onclick )
        {
            tag.onclick = moo;
        }
    },
    linkToTags:function( tags )
    {
        for ( var index = 0; index < tags.length; index++ )
        {
            this.linkToTag(tags[index]);
        }
    }
}
JoklWebsite.convertHyperlinksToAJAX = function()
{
    var hyperlinkArray = document.getElementsByTagName('a');
    for ( var index = 0; index < hyperlinkArray.length; index++ )
    {
        var currentLink = hyperlinkArray[index];
        var currentLinkParent = currentLink.parentNode;
        if ( Dom.isOfClass(hyperlinkArray[index].className, 'ajaxable') )
        {
            var linkAddress = currentLink.href;
            var currentContentRequester = new JoklWebsite.PageContentLoader(linkAddress);
            var childNodes = currentLink.childNodes;
            currentContentRequester.linkToTags(childNodes);
            for ( var childIndex = 0; childIndex < childNodes.length; childIndex++ )
            {
                var currentChild = childNodes[childIndex];
                currentLink.removeChild(currentChild);
                currentLinkParent.appendChild(currentChild);
            }
            currentLinkParent.removeChild(currentLink);
            index--;
        }
    }
}

var contentLoader = new JoklWebsite.PageContentLoader(JoklWebsite.WEBSITE_PORTAL_URL);
var messageLoader = new JoklWebsite.MessageLoader(JoklWebsite.WEBSITE_PORTAL_URL);
