
/***************************************
  chat.js
***************************************/



// chatURL - the URL for updating chat messages
var chatURL="http://www.starwarsknights.com/chat/chat.php";

// getColorURL - the URL for retrieving the chosen rgb color
var getColorURL="http://www.starwarsknights.com/chat/get_color.php";

// getUsernameURL - the URL for getting intial username
var getUsernameURL="http://www.starwarsknights.com/chat/chat.php";

// create XMLHttpRequest object for updating the chat messages
var xmlHttpGetMessages=createXmlHttpRequestObject();

// decoupling the send/get objects for better response time
var xmlHttpSendMessages=createXmlHttpRequestObject();

// create XMLHttpRequest object for updating the color
var xmlHttpGetColor=createXmlHttpRequestObject();

// create XMLHttpRequest object for initially getting username if possible
var xmlHttpGetUsername=createXmlHttpRequestObject();

// how often to access the server in milliseconds
var updateInterval=1000;
if (document.all) {
    updateInterval=2000;  //IE users tend to have more problems keeping up so slow it down for them
}

// debug setting, if set to true, display detailed error message
var debugMode=true;

// superdebug
var superDebug=false;

// intitialize messages cache
var cache=new Array();

// last message ID - the most recent message from the server
var lastMessageID = -1;

// mouseX mouseY - the mouse coordinates of the event
var mouseX, mouseY;
var timeoutRead, timeoutWrite;
//-------------------------------------------------
//  core functions
//-------------------------------------------------

/* creates an XMLHttpRequest Instance */
function createXmlHttpRequestObject()
{
    var xmlhttp;
    // this should work for all browsers except IE6 and older
    if (document.all) {
        // assume IE6 or older
        var XmlHttpVersions=new Array("MSXML2.XMLHTTP.6.0",
                                      "MSXML2.XMLHTTP.5.0",
                                      "MSXML2.XMLHTTP.4.0",
                                      "MSXML2.XMLHTTP.3.0",
                                      "MSXML2.XMLHTTP",
                                      "Microsoft.XMLHTTP");
        // try every prod id until one works
        for (var i=0; i<XmlHttpVersions.length && !xmlhttp; i++)
        {
            try
            {
                xmlhttp=new ActiveXObject(XmlHttpVersions[i]);
            }
            catch (e) {}
        }
        
    }
    if (!xmlhttp) {
        try
        {
            xmlhttp=new XMLHttpRequest();
            
        }
        catch (e)
        {
            // assume IE6 or older
            var XmlHttpVersions=new Array("MSXML2.XMLHTTP.6.0",
                                          "MSXML2.XMLHTTP.5.0",
                                          "MSXML2.XMLHTTP.4.0",
                                          "MSXML2.XMLHTTP.3.0",
                                          "MSXML2.XMLHTTP",
                                          "Microsoft.XMLHTTP");
            // try every prod id until one works
            for (var i=0; i<XmlHttpVersions.length && !xmlhttp; i++)
            {
                try
                {
                    xmlhttp=new ActiveXObject(XmlHttpVersions[i]);
                }
                catch (e) {}
            }
            
        }
    }
    // return the created object or display an error message
    if (!xmlhttp) {
        alert("Error creating the XMLHttpRequest object.");
    }
    return xmlhttp;

}
function setTopic(topic,author) {
    document.getElementById('topicDiv').innerHTML = topic +" --"+author;
    return;
}
/* this function initiates the chat; it executes when the chat page loads */
function init()
{
    // get a ref to the textbox where the user writes new msgs
    var oMessageBox=document.getElementById("messageBox");
    
    var oButton=document.getElementById("btnInit");
    oButton.style.visibility="hidden";
    var oPrelude=document.getElementById("prelude");
    oPrelude.innerHTML="";
    
    // figure out the user's timezone offset
    var oTimezoneOffset=document.getElementById("timezoneOffset");
    var d=new Date();
    
    // eg. GMT-4:30 ->  270;   GMT+1:30 -> -90
    var tzTotalMinutes=d.getTimezoneOffset();
    // eg. 270 % 60 = 30;   -90 % 60 = 30;
    var tzJustMinutes=tzTotalMinutes % 60;
    
    // eg.  0-(270-30)/60= -4;  0-(-90+30)/60 = 1;
    var tzJustHours= tzTotalMinutes>0 ? 0 - ((tzTotalMinutes-tzJustMinutes) / 60) : 0 - ((tzTotalMinutes+tzJustMinutes) / 60);
    // eg. -4 ; +1;
    if (tzJustHours>0) {
        tzJustHours="+" + tzJustHours;
    }
    tzJustMinutes=tzJustMinutes+"";
    if (tzJustMinutes.length == 1) {
        tzJustMinutes="0"+tzJustMinutes;
    }
    // eg. -4:30 ;  +1:30
    oTimezoneOffset.value=tzJustHours+":"+tzJustMinutes;
    
    // prevenet autofill
    oMessageBox.setAttribute("autocomplete","off");
    
    //fix the Text will look like this appearance
    updateTextView();
    
    // ensure the user has a random name when the form loads
    //checkUsername();
    timeoutRead=setTimeout("requestUsername();",updateInterval);
    timeoutWrite=setTimeout("pollForQueuedMessagesToSend();",updateInterval);
    
    // initiate updating of the chat window
    requestNewMessages();
}
// --- end of core functions ---

//-----------------------------------------------
//  support functions
//-----------------------------------------------

/* kickstart a broken chat */
function kickstart()
{
    // clear any pending timeouts
    clearTimeout(timeoutRead);
    clearTimeout(timeoutWrite);
    timeoutRead=setTimeout("requestNewMessages();", updateInterval);
    timeoutWrite=setTimeout("pollForQueuedMessagesToSend();",updateInterval);
}

/* get a random username if the username is blank */
function checkUsername()
{
    var oUser=document.getElementById("username");
    if (oUser.value == "")
        oUser.value="Guest"+Math.floor(Math.random() * 1000);
}

/* function that appends the new msgs to the chat list */
function displayMessages(idArray,colorArray,nameArray,timeArray,messageArray,fontFaceArray,fontSizeArray,ipArray,isStaffArray,isTopicArray)
{
    // each loop adds a new msg
    for (var i=0; i<idArray.length; i++)
    {
        
        lastMessageID=idArray.item(i).firstChild.data;
        // get msg details
        var color    = colorArray.item(i).firstChild.data.toString();
        var time='';
        try {
            time     = timeArray.item(i).firstChild.data.toString();
        }
        catch(e) {
            time = '';
        }


        var name;     
        var message;  
        var fontFace; 
        var fontSize; 
        var ip;       
        var isStaff;  
        var monochrome;
        var isTopic;
        try {
            name     = nameArray.item(i).firstChild.data.toString();
            message  = messageArray.item(i).firstChild.data.toString();
            fontFace = fontFaceArray.item(i).firstChild.data.toString();
            fontSize = fontSizeArray.item(i).firstChild.data.toString();
            ip       = ipArray.item(i).firstChild.data.toString();
            isStaff  = isStaffArray.item(i).firstChild.data.toString();
            isTopic  = isTopicArray.item(i).firstChild.data.toString();
            monochrome = document.getElementById('monochrome').value;
        }
        catch(e)  { throw e }
        
        var monospan = monochrome=='' ? '' : "<span name=\"monospan\" class='"+monochrome+"'>";
        var endmonospan = monochrome=='' ? '' : "</span>";
        
        // compose the HTML
        var htmlMessage="";
        if (isTopic=="1") {
            htmlMessage="<div class='setTopic'><div>"+name+" sets topic:</div>";
            setTopic(message,name);
        }
        else if (isStaff=="1") {
        	// ST: Reformatted message header a bit...
            // htmlMessage +="<div><span name=\"msginfo\" class=\"msginfo\">"+monospan+"["+ip+"]"+endmonospan+"</span><span name=\"msginfo\" class=\"staffinfo\">"+monospan+" "+ name + endmonospan + "</span><span name=\"msginfo\" class=\"dateinfo\">"+monospan+" (" + time +")"+endmonospan+"</span></div>";
            htmlMessage +="<div class=\"posthead\"><span name=\"msginfo\" class=\"staffinfo\">"+monospan+"&nbsp;"+ name + endmonospan + "</span><span name=\"msginfo\" class=\"msginfo\">"+monospan+" - #"+ip+" "+endmonospan+"</span>&nbsp;<span name=\"msginfo\" class=\"dateinfo\">"+monospan+" (" + time +")"+endmonospan+"</span></div>";
        }
        else {
        	// ST: Reformatted message header a bit...
            // htmlMessage +="<div><span name=\"msginfo\" class=\"msginfo\">"+monospan+" ["+ip+"] "+ name + endmonospan+"</span><span name=\"msginfo\" class=\"dateinfo\">"+monospan+" (" + time +") "+endmonospan+"</span></div>";
            htmlMessage +="<div class=\"posthead\"><span name=\"msginfo\" class=\"msginfo\">"+monospan+"&nbsp;"+name+" - #"+ ip + endmonospan+"</span><span name=\"msginfo\" class=\"dateinfo\">"+monospan+"&nbsp; (" + time +") "+endmonospan+"</span></div>";
        }
        htmlMessage +="<div name=\"msg\" class=\"item\" style=\"color:" + color + "; font-family:"+fontFace+"; font-size:"+fontSize+"pt;\">";
        if (isTopic=="1") htmlMessage+="</div>";
        htmlMessage +=monospan+message+endmonospan;
        htmlMessage +="</div>";
        
        // display it
        displayMessage(htmlMessage);
    }
}
/* sets the contents of the online users box */
function displayOnlineUsers(idArray,nameArray,staleArray,lockArray,chatLocked)
{
    var oUsers=document.getElementById("onlineusers");
    var monochrome=document.getElementById("monochrome").value;
    
    var monoSpan = monochrome=='' ? '' : "<span class='"+monochrome+"'>";
    var endMonoSpan = monochrome=='' ? '' : "</span>";

    var txt;
    txt='<table width=100%>';
    for (var i=0; i<idArray.length; i++)
    {
        var userid=idArray.item(i).firstChild.data.toString();
        var username=nameArray.item(i).firstChild.data.toString();
        var stale=staleArray.item(i).firstChild.data.toString();
        var lock=lockArray.item(i).firstChild.data.toString();
        
        var userLocked = 0;
        if (lock=="1") {
            userLocked=1;
        }
        else if (lock=="2") {
            userLocked=0;
        }
        else if (chatLocked=="1") {
            userLocked=1;
        }
        var onlineImg    = stale == 'true' ? '<img src="chat/user_offline.gif" alt="-" height="10" width="10">' : '<img src="chat/user_online.gif" alt="*" height="10" width="10">';
        onlineImg +=       userLocked  == 1 ? '<img src="chat/user_lock.gif" alt="-" height="10" width="10">' : '';
        txt+='<tr><td align="left">'+onlineImg+monoSpan+'<span class="tenpx" onclick="var oTarget=document.getElementById(\'messageBox\'); oTarget.value=\'<pm '+userid+'>\'+oTarget.value;oTarget.focus();">ID#&nbsp;'+userid+'</span>'+endMonoSpan+'</td><td align="left">'+monoSpan+'<span class="tenpx" onclick="var oTarget=document.getElementById(\'messageBox\'); oTarget.value=\'<pm '+userid+'>\'+oTarget.value; oTarget.focus();">'+username+'</span>'+endMonoSpan+'</td></tr>';
    }
    txt+='</table>';
    if (idArray.length>0) {
        oUsers.innerHTML=txt;
    }
}
/* displays the msgs */
function displayMessage(htmlMessage)
{
    // get the scroll object
    var oScroll=document.getElementById("scroll");
    
    // check if the scroll is down
    var scrollDown=(oScroll.scrollHeight-oScroll.scrollTop <= oScroll.offsetHeight+30);
    
    // display the message
    oScroll.innerHTML += unescape(htmlMessage);
    
    // scroll down the scrollbar
    oScroll.scrollTop = scrollDown ? oScroll.scrollHeight : oScroll.scrollTop;
}

/* displays error msgs */
function displayError(message)
{
    // display error message with more tech details if debugMode is true
    displayMessage("Error accessing the server! " + (debugMode ? "<br/>" + message : ""));
}

/* handles keydown to detect when enter is pressed */
function handleKey(e,ipaddr)
{
    // get the event
    e =(!e) ? window.event : e;
    // get the code of the char pressed
    var code = (e.charCode) ? e.charCode :
               ((e.keyCode) ? e.keyCode :
               ((e.which) ? e.which : 0));
    // handle keydown event
    if (e.type=="keydown")
    {
        // if enter was pressed
        if (code==13)
        {
            // send the current message
            sendMessage(ipaddr);
        }
    }
}

/* removes leading and trailing spaces */
function trim(s)
{
    return s.replace(/(^\s+)|(\s+$)/g, "");
}

/* gets the mouse coordinates */
function getMouseXY(e)
{
    //browser specific
    if (window.ActiveXObject)
    {
        mouseX=window.event.x + document.body.scrollLeft;
        mouseY=window.event.y + document.body.scrollTop;
    }
    else
    {
        mouseX=e.pageX;
        mouseY=e.pageY;
    }
}
function updateTextView() {
    //called by onchange event of <select> tags
    var oFontSize=document.getElementById("fontsize");
    var oFontFace=document.getElementById("fontface");
    var oSampleText=document.getElementById("sampleText");
    var oColor=document.getElementById("color");
    
    var fontFace=oFontFace.options[oFontFace.selectedIndex].text; //hoops to jump through for IE6
    var fontSize=oFontSize.options[oFontSize.selectedIndex].text;
    
    if (fontSize>12) { fontSize=12; }
    if (fontSize<8)  { fontSize=8;  }
    //for IE6... (Mozilla understands font-size here but not the rest)
    oSampleText.style.cssText="font-family="+fontFace+"; font-size:"+fontSize+"pt; color="+oColor.value;
    
    //for Mozilla... but not IE6
    oSampleText.style.fontFamily=fontFace;
    oSampleText.style.color=oColor.value;
    
}    
function toggleSmilies() {
    // called by btnSmilies
    var oSmiliesButton=document.getElementById("btnSmilies");
    var oSmiliesBox=document.getElementById("divSmilies");
    if (oSmiliesBox.style.visibility=="hidden") { // show smilies
        oSmiliesButton.value="Hide smilies";
        oSmiliesBox.style.visibility="visible";
    }
    else { //hide smilies
        oSmiliesButton.value="Show smilies";
        oSmiliesBox.style.visibility="hidden";
    }
}
/* Send button calls this function */
function sendMessage()
{
    // save stuff to local variables before we go farther
    var oCurrentMessage = document.getElementById("messageBox");
    var currentUser     = document.getElementById("username").value;
    var currentColor    = document.getElementById("color").value;
    
    
    //var currentFontFace = document.getElementById("fontface").value;  //doesn't work for IE6
    //var currentFontSize = document.getElementById("fontsize").value;
    var oFontFace=document.getElementById("fontface");
    var currentFontFace = oFontFace.options[oFontFace.selectedIndex].text;
    var oFontSize=document.getElementById("fontsize");
    var currentFontSize =oFontSize.options[oFontSize.selectedIndex].text;
    var oStaffModeRequest=document.getElementById('staffModeRequest');
    var staffModeRequest = oStaffModeRequest.value;
    var oUUID = document.getElementById("uuid");
    var uuid = oUUID.value;
    var message         = oCurrentMessage.value;
    
    if (superDebug=="true")
       displayMessage("attempting to send message...."+message);

    
    // don't send blank messages
    if (trim(message) != "" && trim(currentColor) != "" && message.indexOf('<?')==-1 )
    {
        // if we need to send and retrieve messages
        message=message.replace(/\+/g,"%2B");
        params="mode=Send" +
                   "&id="     + encodeURIComponent(lastMessageID) +
                   "&color="  + encodeURIComponent(currentColor) +
                   "&name="   + encodeURIComponent(currentUser) +
                   "&message="+ escape(message) +
                   "&fontface="+ encodeURIComponent(currentFontFace)+
                   "&fontsize="+ encodeURIComponent(currentFontSize)+
                   "&uuid="+encodeURIComponent(uuid)+
                   "&staffreq="+ encodeURIComponent(staffModeRequest);
                   

                   
                   
        // add the params to the queue
        cache.push(params)
        // clear the textbox
        oCurrentMessage.value="";
    }
}


// --- end of suppor functions ---



//-------------------------------------------------------
// AJAX request functions
//-------------------------------------------------------
function requestUsername()
{
    var uuid=document.getElementById('uuid').value;
    var d=new Date();
    var tzTotalMinutes=d.getTimezoneOffset();
    if (xmlHttpGetUsername)
    {
        try
        {   
                // store params used to make the request
                var params="mode=GetUsername" +
                "&uuid="+encodeURIComponent(uuid) +
                "&tz="+encodeURIComponent(tzTotalMinutes);
                
                // call the server page to execute the server-side operations
                xmlHttpGetUsername.open("POST",getUsernameURL,true);
                xmlHttpGetUsername.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
                xmlHttpGetUsername.onreadystatechange=handleReceivingUsername;
                xmlHttpGetUsername.send(params);
                
        }
        catch(e)
        {
            displayError("requestUsername catch: "+e.toString());
        }
        
    }

}


/* makes asynch requests to retrieve new msgs, post msgs, and delete msgs */
function requestNewMessages()
{
    // retrieve the username and color from the page
    var currentUser =document.getElementById("username").value;
    var currentColor=document.getElementById("color").value;
    var uuid=document.getElementById("uuid").value;
    var tz=document.getElementById("timezoneOffset").value;
    
    if (superDebug=="true")
       displayMessage("requestNewMessages...");
    // continue only if xmlHttpGetMessages is not void
    if (xmlHttpGetMessages)
    {
        try
        {
            // don't start another server operation if such an operation is in progress
            if (xmlHttpGetMessages.readyState==4 || xmlHttpGetMessages.readyState==0)
            {
                // store params used to make the request
                var params="";
                
                // if there are requests stored in queue, take the oldest
                    
                    params="mode=RetrieveNew"+
                           "&uuid="+encodeURIComponent(uuid)+
                           "&id="+lastMessageID+
                           "&tz="+encodeURIComponent(tz);
                           
                // call the server page to execute the server-side operations
                xmlHttpGetMessages.open("POST",chatURL,true);
                xmlHttpGetMessages.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
                xmlHttpGetMessages.onreadystatechange=handleReceivingMessages;
                xmlHttpGetMessages.send(params);
                
            }
            else
            {
                // check again later for new messages
                timeoutRead=setTimeout("requestNewMessages();", updateInterval);
            }
        }
        catch(e)
        {
            displayError("requestNewMessages catch: "+e.toString());
        }
    }
}

/* polls for queued messages to send */
function pollForQueuedMessagesToSend()
{
    // retrieve the username and color from the page
    var currentUser =document.getElementById("username").value;
    var currentColor=document.getElementById("color").value;
    var uuid=document.getElementById("uuid").value;
    if (xmlHttpSendMessages)
    {
        if (xmlHttpSendMessages.readyState==4 || xmlHttpSendMessages.readyState==0)
        {
            if (superDebug=="true")
               displayMessage("pollForQueuedMessagesToSend...");
       
       
            // if there are requests stored in queue, take the oldest
            var params="";
            if (cache.length>0)
            {
                params=cache.shift();
                xmlHttpSendMessages.open("POST",chatURL,true);
                xmlHttpSendMessages.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
                xmlHttpSendMessages.onreadystatechange=handleSendingMessages;
                xmlHttpSendMessages.send(params);
        
            }
            timeoutWrite=setTimeout("pollForQueuedMessagesToSend();",updateInterval);            
        }
    }
    else {
        xmlHttpSendMessages=null;
        xmlHttpSendMessages=createXmlHttpRequestObject();
        timeoutWrite=setTimeout("pollForQueuedMessagesToSend();",updateInterval);
    }
}

/* makes a server call to get the rgb code for a clicked color */
function getColor(e)
{
    if (document.getElementById("monochrome").value != '') {
        return;
    }
    
    getMouseXY(e);
    // only proceed if xmlHttpGetColor is legit
    if (xmlHttpGetColor)
    {
        // initialize the offset position with the mouse current position
        var offsetX=mouseX;
        var offsetY=mouseY;
        
        // get our points of reference
        var oPalette=document.getElementById("palette");
        var oTd = document.getElementById("colorpicker");
        var oT1 = document.getElementById("content");
        var oTmain = document.getElementById("table_main");
        //var oT1gR2C1=document.getElementById("table1gR2C1");
        
        // compute the offset in our window
        if (window.ActiveXObject)
        {
            offsetX = window.event.offsetX;
            offsetY = window.event.offsetY;
        }
        else
        {
            if (superDebug) {
                var msg="raw X: "+offsetX+"<br>";
                msg +="raw Y: "+offsetY+"<br>";
                msg +="PaletteX: "+oPalette.offsetLeft+"<br>";
                msg +="PaletteY: "+oPalette.offsetTop+"<br>";
                msg +="TdX: "+oTd.offsetLeft+"<br>";
                msg +="TdY: "+oTd.offsetTop+"<br>";
                msg +="T1X: "+oT1.offsetLeft+"<br>";
                msg +="T1Y: "+oT1.offsetTop+"<br>";
                msg +="TmainX: "+oTmain.offsetLeft+"<br>";
                msg +="TmainY: "+oTmain.offsetTop+"<br>";
                //msg +="T1gX: "+oT1g.offsetLeft+"<br>";
                //msg +="T1gY: "+oT1g.offsetTop+"<br>";
                //msg +="T1gR2C1X: "+oT1gR2C1.offsetLeft+"<br>";
                //msg +="T1gR2C1Y: "+oT1gR2C1.offsetTop+"<br>";
                
                displayMessage(msg);
            }
            offsetX -= oPalette.offsetLeft+oTd.offsetLeft+oT1.offsetLeft+oTmain.offsetLeft+122; //122 is side-nav menu width
            offsetY -= oPalette.offsetTop+oTd.offsetTop+oT1.offsetTop+oTmain.offsetTop; //166 is banner img height
        }
        var params="?offsetx="+offsetX+"&offsety="+offsetY;
        if (superDebug) {
            displayMessage(params);
        }
        // call server asynch. to find out the clicked color
        try
        {
            if (xmlHttpGetColor.readyState==4 || xmlHttpGetColor.readyState==0)
            {
                xmlHttpGetColor.open("GET", getColorURL+params, true);
                xmlHttpGetColor.onreadystatechange = handleGettingColor;
                xmlHttpGetColor.send(null);
            }
        }
        catch (e)
        {
            // display error msg
            displayError("getColor catch: "+xmlHttpGetColor.statusText);
        }
    }
}
// --- end of AJAX request functions ----

//-----------------------------------------------
// AJAX response handlers (callbacks)
//-----------------------------------------------

/* function that handles the http response when updating messages */
function handleReceivingUsername()
{
    // continue if process is completed
    if (xmlHttpGetUsername.readyState == 4)
    {
        // continue if response is 'OK'
        if (xmlHttpGetUsername.status==200)
        {
            try
            {
                // process server response
                readUsername();
            }
            catch(e)
            {
                // the readMessages functions threw an exception
                // display that error message
                displayError("handleReceivingUsername catch: "+e.toString());
            }
        }
        else
        {
            // something went wrong
            displayError("handleReceivingUsername not ok: "+xmlHttpGetUsername.statusText);
        }
    }
    //xmlHttpGetUsername=null; //done with this...
}



/* function that handles the http response when sending messages */
function handleSendingMessages()
{
    // continue if process is completed
    if (xmlHttpSendMessages.readyState == 4)
    {
        // continue if response is 'OK'
        if (xmlHttpSendMessages.status==200)
        {
            try
            {
                // process server response
                acknowledgeSendReceipt();
            }
            catch(e)
            {
                // the readMessages functions threw an exception
                // display that error message
                displayError("handleSendingMessages catch: "+e.toString());
            }
        }
        else
        {
            // something went wrong
            displayError("handleSendingMessages not ok: "+xmlHttpSendMessages.statusText);
        }
    }
}

/* function that handles the http response when updating messages */
function handleReceivingMessages()
{
    // continue if process is completed
    if (xmlHttpGetMessages.readyState == 4)
    {
        // continue if response is 'OK'
        if (xmlHttpGetMessages.status==200)
        {
            try
            {
                // process server response
                readMessages();
            }
            catch(e)
            {
                // the readMessages functions threw an exception
                // display that error message
                displayError("handleReceivingMessages catch: "+e.toString());
            }
        }
        else
        {
            // something went wrong
            displayError("handleReceivingMessages not ok: "+xmlHttpGetMessages.statusText);
        }
    }
}

/* handles the color response from the server */
function handleGettingColor()
{
    // if the process is completed, decide what to do with the response
    if (xmlHttpGetColor.readyState==4)
    {
        // if response is 'OK'
        if (xmlHttpGetColor.status == 200)
        {
            try
            {
                // change the color
                changeColor();
            }
            catch(e)
            {
                // changeColor() threw an exception
                // display the error message
                displayError("handleGettingColor catch: "+xmlHttpGetColor.statusText);
            }
        }
        else
        {
            // something went wrong
            displayError("handleGettingColor not ok: "+xmlHttpGetColor.statusText);
        }
    }
}
// --- end of AJAX response handlers (callbacks) ---

//----------------------------------------
// AJAX response readers
//----------------------------------------
function readUsername() {
    response=xmlHttpGetUsername.responseText;
    if (superDebug) {
        displayMessage(response);
    }
    
    // server error?
    if (response.indexOf("ERRNO") >= 0
        || response.indexOf("error:") >= 0
        || response.length==0)
    {
        throw(response.length == 0 ? "Can't get username!" : "readUsername says: " + response);
    }

    if (xmlHttpGetUsername.responseXML.documentElement) {
        response =xmlHttpGetUsername.responseXML.documentElement;
    }
    else
    {
        throw "wtf? "+response;
    }
    var resultArray  = response.getElementsByTagName("result");
    var usernameArray    = response.getElementsByTagName("username");
    
    var result=resultArray.item(0).firstChild.data.toString();
    var username;
    if (result=='success') {
        username=usernameArray.item(0).firstChild.data.toString();
    }
    else {
        username="Guest"+Math.floor(Math.random() * 1000);
    }
    var oUser=document.getElementById("username");
    oUser.value=username;
}

function acknowledgeSendReceipt() {
    //no need to call setTimeout at the end of this routine since the pollForQueuedMessages does that unless xmlHttpSendMessages isn't defined
    var response=xmlHttpSendMessages.responseText;
    if (superDebug==true) {
        displayMessage("acknowledgeSendReceipt says:<br><pre>"+response+"</pre><br>");
    }
    if (response.indexOf("ERRNO")>=0
        || response.indexOf("error:")>=0
        || response.length==0)
    {
        throw(response.length==0 ? "Server did not return send receipt!" : "acknowledgeSendReceipt throws: "+response);
    }
    if (xmlHttpSendMessages.responseXML.documentElement) {
        response=xmlHttpSendMessages.responseXML.documentElement;
    }
    else
    {
        throw "wtf ack? "+response;
    }
    var receipt=response.getElementsByTagName("receipt").item(0).firstChild.data;
    if (superDebug==true) {
        displayMessage("send receipt: "+receipt+"<br>");
    }
    
}

/* function that processes the server's response when updating messages */
function readMessages()
{
    

    // retrieve the server's response
    var response = xmlHttpGetMessages.responseText;
    if (superDebug==true)
   {
       displayMessage("readMessages says:<br><pre>"+response+"</pre><br>");
   }
    // server error?
    if (response.indexOf("ERRNO") >=0
        || response.indexOf("error:") >=0
        || response.length==0)
    {
        throw(response.length == 0 ? "Server returned nothing!" : "readMessages throws: "+response);
    }
    
    // get the document element from the server's response
    if (xmlHttpGetMessages.responseXML.documentElement) {
        response =xmlHttpGetMessages.responseXML.documentElement;
    }
    else
    {
        throw "wtf? "+response;
    }
    
    
    
    /*    var polling_rate_seconds=response.getElementsByTagName("polling").item(0).firstChild.data;
        if (polling_rate_seconds < 1 ) {
            polling_rate_seconds=1;
        }
        else if (polling_rate_seconds>12) {
            polling_rate_seconds=12;
        }
        updateInterval=polling_rate_seconds * 1000;
    //}
    //catch (e) {
   // }
    */
    // retrieve the flag that says whether the chat window has been cleared
    
    var clearChat;
    try {
        clearChat=response.getElementsByTagName("clear").item(0).firstChild.data;
    }
    catch (e)   { }
    if (clearChat=="true")
    {
        // clear the chat window and reset the msg id
        document.getElementById("scroll").innerHTML="";
        lastMessageID=-1;
    }
    var chatTopic="";
    var chatTopicStarter="";
    try {
        chatTopic=response.getElementsByTagName("topic").item(0).firstChild.data;
        chatTopicStarter=response.getElementsByTagName("topic_starter").item(0).firstChild.data;
    }
    catch(e) { }
    if (chatTopic != "") {
        setTopic(chatTopic,chatTopicStarter);
    }
    var chatLocked;
    try {
        chatLocked=response.getElementsByTagName("chatlocked").item(0).firstChild.data;
    }
    catch (e) { }
    
    if (chatLocked==1)
    {
        
        document.getElementById("lock_notice").style.visibility='visible';
    }
    else {
        document.getElementById("lock_notice").style.visibility='hidden';
    }
    // retrieve arrays from the server's response
    try {
        var idArray       = response.getElementsByTagName("id");
        var colorArray    = response.getElementsByTagName("color");
        var nameArray     = response.getElementsByTagName("name");
        var timeArray     = response.getElementsByTagName("time");
        var messageArray  = response.getElementsByTagName("message");
        var fontFaceArray = response.getElementsByTagName("fontface");
        var fontSizeArray = response.getElementsByTagName("fontsize");
        var ipArray       = response.getElementsByTagName("ip");
        var isStaffArray  = response.getElementsByTagName("isstaff");
        var isTopicArray  = response.getElementsByTagName("istopic");
        var onlineIdArray = response.getElementsByTagName("onlineid");
        var onlineNameArray=response.getElementsByTagName("onlinename");
        var staleArray=response.getElementsByTagName("stale");
        var lockArray=response.getElementsByTagName("locked");
    
        // add the new messages to the chat window
        displayMessages(idArray,colorArray,nameArray,timeArray,messageArray,fontFaceArray,fontSizeArray,ipArray,isStaffArray,isTopicArray);
        
        // add users to the online user list
        displayOnlineUsers(onlineIdArray,onlineNameArray,staleArray,lockArray,chatLocked);

    
        // store the ID of the last received message
        //if (idArray.length>0)
        //{
        //    lastMessageID=idArray.item(idArray.length-1).firstChild.data;
        // }
    }
    catch(e) {
      kickstart();
      throw " <br>* oops:  a DB Error at msg id "+lastMessageID; //  displayError(e.description);
      
    }

    //restart sequence
    timeoutRead=setTimeout("requestNewMessages();", updateInterval);
}

/* function that changes the color */
function changeColor()
{
    response=xmlHttpGetColor.responseText;
    if (superDebug) {
        displayMessage(response);
    }
    
    // server error?
    if (response.indexOf("ERRNO") >= 0
        || response.indexOf("error:") >= 0
        || response.length==0)
    {
        throw(response.length == 0 ? "Can't change color!" : "changeColor says: " + response);
    }
    var oColor=document.getElementById("color");
    var oSampleText=document.getElementById("sampleText");
    var oFontSize=document.getElementById("fontsize");
    var oFontFace=document.getElementById("fontface");
    oColor.value=response;
    //oSampleText.style.color=response;
    var fontFace=oFontFace.options[oFontFace.selectedIndex].text; //hoops to jump through for IE6
    var fontSize=oFontSize.options[oFontSize.selectedIndex].text;
    if (fontSize>12) { fontSize=12; }
    if (fontSize<8)  { fontSize=8;  }    
    
    //for IE6... (Mozilla understands font-size here but not the rest)
    oSampleText.style.cssText="font-family="+fontFace+"; font-size:"+fontSize+"pt; color="+response+";";
    
    //for Mozilla...but not IE6
    oSampleText.style.fontFamily=fontFace; 
    oSampleText.style.color=response;
}
// --- end of AJAX response readers ---

