function AEtext(pAEid, pAE_HTML_Node, pAE_ParamList, pAE_Parent)
{
    // Set this object up as a descendant of the activeElement class
    // The screen name is set to be the same as the global pageAE object instance

    D.debugStartFunction("AEtext", arguments);
    
    this.superclass = activeElement;
    this.superclass(pAEid, "AEtext", "", pAE_HTML_Node, pAE_ParamList, pAE_Parent);
    
    this.aeInitialise = function() // Overloads master aeInitialise function
    {
        /*
        Overrides aeInitialise from master activeElement class.
        
        Called after new AE has been created.  Populates HTML nodes with startup text and
        performs any other initialisation for this AE
        */
        
        D.debugStartFunction("AEtext:aeInitialise", arguments);

        // NOTE: This is a temporary solution until the Navigation algorithm requests its own
        // data.
        
        // Need to invoke Navigation algorithm to access template information for website

        D.debug("About to call aeGetAlgorithmObject from AE, id = " + this.aeGetAEid());
        this.AE_NavData = this.aeGetAlgorithmObject("Navigation");
        
        var NavigationStatus;
        
        this.aeSetStatus("RequestingData");
        NavigationStatus = this.aeGetAlgorithmStatus("Navigation");
        
        D.debug("NavigationStatus = " + NavigationStatus);
        
        if (NavigationStatus && NavigationStatus == "Initialised")
        {
            this.aeSendNavXMLRequest();
        }

        // Propogate to any controlled AEs under this one
        
        for (var i=0; i<this.AE_controlledAE_Count; i++)
        {
            this.AE_controlledAE_List[i].aeInitialise();
        }
        
        D.debugEndFunction("aeInitialise");
    }

    this.aeScreenChange = function(pScreen)
    {
        D.debugStartFunction("AEtext.aeScreenChange", arguments);
        //this.aeUpdateHTML_Nodes("AEtext: Screen changed to " + pScreen);
        
        this.aeUpdateContent();

        // Cascade to all child AEs
        
        for (var i=0; i<this.aeGetNumControlledAEs(); i++)
        {
            D.debug("Cascading to AEid " + this.AE_controlledAE_List[i].AE_AEid);
            this.AE_controlledAE_List[i].aeScreenChange(pScreen);
        }
        D.debugEndFunction();
    }
    
    this.aeSendNavXMLRequest = function()
    {
        D.debugStartFunction("SendNavXMLRequest");
            
        var NavHeader = new Array;
        var dataPayload; // this will contain XML-tagged data, specific to this AEtype
        var RequestXML;
        var DataRequest;
        
        D.debug("Sending Request");
        
        NavHeader['msgseqnum']   = this.aeGetMsgSeqNum();
        NavHeader['requesttype'] = 'datarequest';
        NavHeader['loggingflag'] = 'true';
        NavHeader['aetype']      = this.aeGetAEtype();
        NavHeader['aeid']        = this.aeGetAEid();
    
        RequestXML = this.aeCreateRequestHeaderXML(NavHeader);
        
        dataPayload = this.aeXMLnodeCreate('datarequesttype', 'NavXML');
        dataPayload = this.aeXMLnodeCreate('datarequest', dataPayload);
    
        RequestXML += dataPayload;
        DataRequest = this.aeXMLnodeCreate('activeelementrequest', RequestXML);
        
        this.aeSetAlgorithmStatus("Navigation", "RequestingData");
        this.aeSendRequest(DataRequest);
        
        D.debugEndFunction();
    }

    this.aeCreateDataRequestXML = function(pOperation, pPath)
    {
        /*
        This will send a request to the "text" service on the server.
        
        pOperation is one of:
        - getFile: The contents of the specified file are returned from the configured location
        - getRandomFile: A random file is returned from the specified directory in the confugured location

        pPath is either the name of a file or a directory depending upon pOperation
        */
        
        var dataPayload; // this will contain XML-tagged data, specific to this AEtype
        
        dataPayload = this.aeXMLnodeCreate('datarequesttype', "text");
        dataPayload += this.aeXMLnodeCreate('operation', pOperation);
        dataPayload += this.aeXMLnodeCreate('path', pPath);
        dataPayload = this.aeXMLnodeCreate('datarequest', dataPayload);
        
        return dataPayload;
    }

    this.aeUpdateContent = function()
    {
        D.debugStartFunction("AEtext:UpdateContent", arguments);
        
        var dataHeader = new Array;
        var dataRequest;
        var requestXML;
        var path = "DummyPath";
        var sendFlag = false;
        var requestOperation = "";
        
        dataHeader['msgseqnum']   = this.aeGetMsgSeqNum();
        dataHeader['requesttype'] = 'datarequest';
        dataHeader['loggingflag'] = 'true';
        dataHeader['aetype']      = this.aeGetAEtype();
        dataHeader['aeid']        = this.aeGetAEid();

        if (this.AE_paramList == "template")
        {
            // First, check whether we need to reload template, as this changes everything
            // If this first time Navigation Algorithm may not be loaded yet, so check
            
            if (this.aeGetAlgorithmStatus("Navigation") == "DataLoaded")
            {
                var newScreen = this.aeGetScreenName();
                var oldScreen = this.aeGetPrevScreenName();
                
                var oldTemplate = oldScreen == null ? null : this.AE_NavData.NavGetTemplateName(oldScreen);
                var newTemplate = this.AE_NavData.NavGetTemplateName(newScreen)
 
                D.debug("Old screen is " + oldScreen + ", new screen is " + newScreen); 
                D.debug("Old template is " + oldTemplate + ", new template is " + newTemplate); 
    
                if (newTemplate == oldTemplate)
                {
                    // Same template so do nothing
                    
                    D.debug("Template AE, no change so do nothing");
                }
                else
                {
                    D.debug("Changing template from " + oldTemplate + " to " + newTemplate);
                    path = "textTemplate" + this.AE_NavData.NavGetTemplateName(this.aeGetScreenName()) + ".txt";
                    sendFlag = true;
                    requestOperation = "getFile";
                }
            }
        }
        else if ( this.AE_paramList == "fixed" )
        {
            path = "textFixed" + this.aeGetAEid() + ".txt";
            sendFlag = true;
            requestOperation = "getFile";
        }
        else if ( this.AE_paramList == "variable" )
        {
            path = "textVariable" + this.aeGetScreenName() + this.aeGetAEid() + ".txt";
            sendFlag = true;
            requestOperation = "getFile";
        }
        else if ( this.AE_paramList == "fixed-random")
        {
            // Pick random file from directory associated with this AEid
            
            path = "textFixedRandom" + this.aeGetAEid()
            sendFlag = true;
            requestOperation = "getRandomFile";
        }
        else
        {
            // AEparam should be one of 'fixed' or 'variable' or 'template'. To get here, it is none - not good
            D.error("Unrecognised parameter in text AE: " + this.AE_paramList);
            sendFlag = false;
        }
        
        if (sendFlag)
        {
            requestXML = this.aeCreateRequestHeaderXML(dataHeader);
            requestXML += this.aeCreateDataRequestXML(requestOperation, path);
            dataRequest = this.aeXMLnodeCreate('activeelementrequest', requestXML);
            this.aeSendRequest(dataRequest);
        }
        D.debugEndFunction();
    }
    
    this.aeProcessResponseData = function(pXML)
    {
        D.debugStartFunction("AEtext.aeProcessResponseData", arguments);
        
        // Currently only process one type of response - Nav XML, but
        // this should be more generic logic.
        
        this.AE_NavData.NavProcessNavXML(pXML);
        this.aeSetAlgorithmStatus("Navigation", "DataLoaded");
        this.aeSetStatus("DataLoaded");
        
        // Need to update content for everything in case other AEs waiting for the file to be loaded
        
        this.aeGetMasterAE().aeScreenChange(this.aeGetScreenName());
        
        D.debugEndFunction("AEtext: aeProcessResponse");
    }
 
    this.aeInitialise();
    this.aeUpdateContent();
    
    D.debugEndFunction("AEtext");
}