/******************************************************************************
* Error codes
*******************************************************************************
*     These are error codes in case there is an error
******************************************************************************/
//Error for when the XMLHttpRequest is unsupported or cannot be created
//this is a fatal error on this script
var ERR_CREATE_REQ = new Number(0);
//Error for when the get request returns no data.  This is not a fatal error,
//it can be caused by a 404 or an unresponsive server
var ERR_RETURN_NULL = new Number(0);





/******************************************************************************
* Ready State codes
*******************************************************************************
*     These are error codes in case there is an error
******************************************************************************/
//Error for when the XMLHttpRequest is unsupported or cannot be created
//this is a fatal error on this script
var RS_UNINITIALIZED = new Number(0);
var RS_LOADING = new Number(1);
var RS_LOADED = new Number(2);
var RS_INTERACTIVE = new Number(3);
var RS_COMPLETED = new Number(4);





/******************************************************************************
* AsyncXMLGetRequest - Wrapper class for XMLHttpRequest
*******************************************************************************
*     this class is used as a wrapper class for XMLHttpRequest because browsers
*     are dumb and can't seem to support the same classes.  It also facilitates
*     the request queue, where each request that is made on the object waits
*     in the queue to be filled.
*   Properties:
*     xmlRequest - the queue of XMLHttpRequests
*     inRequest - a boolean that marks whether or not the queue is active
*     requestQueue - the queue of URLs to be requested
*     objectQueue - the queue of objects to be used in the "onService" routine
******************************************************************************/
function AsyncXMLGetRequest()
    {
    this.xmlRequest = new Array();
    this.inRequest = new Boolean(false);
    this.requestQueue = new Array();
    this.objectQueue = new Array();
    this.queueCount = new Number(0);
    }
/******************************************************************************
* AsyncXMLGetRequest::setup - setup method for AsyncXMLGetRequest
*******************************************************************************
*     allocates the newest item in the queue its own xml request.
******************************************************************************/
AsyncXMLGetRequest.prototype.setup = function()
    {
    try
        {
        this.xmlRequest[this.queueCount] = new ActiveXObject("Msxml2.XMLHTTP");
        } 
        catch (e) 
        {
        try 
            {
            this.xmlRequest[this.queueCount] = 
                            new ActiveXObject("Microsoft.XMLHTTP");
            } 
        catch (E) 
            {
            xmlhttp = null;
            }
        }
    if(this.xmlRequest[this.queueCount] == null 
        && typeof XMLHttpRequest!='undefined') 
        {
        this.xmlRequest[this.queueCount] = new XMLHttpRequest();
        }

    return;
    }
/******************************************************************************
* AsyncXMLGetRequest::queueGetRequest - queue method for AsyncXMLGetRequest
*******************************************************************************
*     this method queues a request
******************************************************************************/
AsyncXMLGetRequest.prototype.queueGetRequest = function(myUrl, myObject)
    {
    if(this.inRequest == false)
        {
        this.inRequest = true;

        this.requestQueue[this.queueCount] = myUrl;
        this.objectQueue[this.queueCount] = myObject;
        this.setup();
        onRequest(this.queueCount);
        this.queueCount++;

        this.sendGetRequest(myUrl, 0);
        }
    else if(this.inRequest == true)
        {
        this.requestQueue[this.queueCount] = myUrl;
        this.objectQueue[this.queueCount] = myObject;
        this.setup();
        onRequest(myRequest.objectQueue[this.queueCount], myRequest.requestQueue[this.queueCount]);
        this.queueCount++;
        }

    return;
    }
/******************************************************************************
* AsyncXMLGetRequest::sendGetRequest - sendGetRequest method for AsyncXMLGetRequest
*******************************************************************************
*     this method sends the specified request as GET
******************************************************************************/
AsyncXMLGetRequest.prototype.sendGetRequest = function(myUrl, qCount)
    {
    if(this.xmlRequest[qCount] == null)
        onRequestError(myRequest.objectQueue[0], ERR_CREATE_REQ, "Instance of XMLHttpRequest cannot be created or is null!");
    else
        {
        this.xmlRequest[qCount].open("GET", myUrl, true);
        this.xmlRequest[qCount].onreadystatechange = xmlHTTPStateChange;
        this.xmlRequest[qCount].send(null);
        }

    return;
    }
/******************************************************************************
* AsyncXMLGetRequest::sendPostRequest - sendPostRequest method for AsyncXMLGetRequest
*******************************************************************************
*     this method sends the specified request as POST
******************************************************************************/
AsyncXMLGetRequest.prototype.sendPostRequest = function(myUrl, qCount, postData)
    {
    if(this.xmlRequest[qCount] == null)
        onRequestError(myRequest.objectQueue[0], ERR_CREATE_REQ, "Instance of XMLHttpRequest cannot be created or is null!");
    else
        {
        this.xmlRequest[qCount].setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        this.xmlRequest[qCount].open("POST", myUrl, true);postData
        this.xmlRequest[qCount].onreadystatechange = xmlHTTPStateChange;
        this.xmlRequest[qCount].send(postData);
        //this.xmlRequest[qCount].send("id=" + escape(idTextField.value));
        }

    return;
    }





/******************************************************************************
* xmlHTTPStateChange - callback funciton
*******************************************************************************
*     this function is a callback used by the XMLHttpRequest object when there
*     is a change in the ready state.  If the ready state is 4, that means that
*     the content is loaded.  This function calls the onService routine always
*     with the number zero, because per a queue, the current element serviced 
*     is always the first in.  After servicing, the first element in is
*     deleted from the queue, and if there are other requests waiting, the
*     next one in line will be handled, else the request chain is done.
******************************************************************************/
var myRequest = new AsyncXMLGetRequest();
function xmlHTTPStateChange() 
    {
    //IF the request is uninitialized, before send() is called
    if(myRequest.xmlRequest[0].readyState == RS_UNINITIALIZED) 
        {
        }
    //send() has not been called
    else if(myRequest.xmlRequest[0].readyState == RS_LOADING) 
        {
        }
    //send() has been called, headers and status are available
    else if(myRequest.xmlRequest[0].readyState == RS_LOADED) 
        {
        }
    //data is being downloaded
    else if(myRequest.xmlRequest[0].readyState == RS_INTERACTIVE) 
        {
        }
    //the request has completed
    if(myRequest.xmlRequest[0].readyState == RS_COMPLETED) 
        {
        if(myRequest.xmlRequest[0].responseText == null)
            onRequestError(myRequest.objectQueue[0], ERR_RETURN_NULL, "Request returned null or no data!");
        else
            onService(myRequest.objectQueue[0], myRequest.requestQueue[0], myRequest.xmlRequest[0].responseText);
        
        myRequest.queueCount--;
        myRequest.requestQueue.splice(0, 1);
        myRequest.objectQueue.splice(0, 1);
        myRequest.xmlRequest.splice(0, 1);
        if(myRequest.queueCount == 0)
            {
            myRequest.inRequest = new Boolean(false);
            }
        else
            myRequest.sendGetRequest(myRequest.requestQueue[0], 0);
        }
    }







/******************************************************************************
* onRequest - callback processing function
*******************************************************************************
*     this is called whenever a request is queued in AsyncXMLGetRequest.  This
*     function is passed the reference variable that was passed into the
*     queue, and can be used to prepare the object for the data.  Usually, this
*     function will take the form of a "loading" or "please wait" prompt, to
*     let the user know that the request has been queued, and you are awaiting
*     data.  The originally requested URL is passed in case it is needed.
******************************************************************************/
function onRequest(requestObj, requestURL)
    {
    requestObj.innerHTML = "";
    }
/******************************************************************************
* onService - callback processing function
*******************************************************************************
*     this is called whenever a request is serviced (meaning the data requested
*     has been recieved).  It can be used to update the object that requested
*     the data.  The originally requested URL is passed in case it is needed.
*     The data requested is passed as requestItem.
******************************************************************************/
function onService(requestObj, requestURL, requestItem)
    {
    requestObj.innerHTML = requestItem;
    }
/******************************************************************************
* onRequestError - callback processing function
*******************************************************************************
*     this is called whenever there is an error with a request, either a file
*     not found, or trouble initializing the XMLHttpRequest
******************************************************************************/
function onRequestError(requestObj, errorCode, verboseError)
    {
    }


/*
To use this script, you must put this in the onclick for the image map.  For instance: 

<div id="starID">
<b>Rate It: </b><img name="rating_stars" align="absmiddle" src="user_rating_stars_0.gif" width="87" height="20" border="0" usemap="#rating_stars_map" alt="Rate This Title">
<map name="rating_stars_map">
<area shape="rect" coords="7,0,22,16" onClick="myRequest.queueGetRequest('whatever.cgi?ISBN=#ISBNNO&userid=###&rank=1', document.getElementById('starID'));" alt="1" onMouseOut="MM_swapImage('rating_stars','','user_rating_stars_5.gif',1);"  onMouseOver="MM_swapImage('rating_stars','','user_rating_stars_1.gif',1);"  >
<area shape="rect" coords="23,0,38,16" onClick="myRequest.queueGetRequest('whatever.cgi?ISBN=#ISBNNO&userid=###&rank=2', document.getElementById('starID'));" alt="2" onMouseOut="MM_swapImage('rating_stars','','user_rating_stars_5.gif',1);"  onMouseOver="MM_swapImage('rating_stars','','user_rating_stars_2.gif',1);"  >
<area shape="rect" coords="39,0,54,16" onClick="myRequest.queueGetRequest('whatever.cgi?ISBN=#ISBNNO&userid=###&rank=3', document.getElementById('starID'));" alt="3" onMouseOut="MM_swapImage('rating_stars','','user_rating_stars_5.gif',1);"  onMouseOver="MM_swapImage('rating_stars','','user_rating_stars_3.gif',1);"  >
<area shape="rect" coords="55,0,70,16" onClick="myRequest.queueGetRequest('whatever.cgi?ISBN=#ISBNNO&userid=###&rank=4', document.getElementById('starID'));" alt="4" onMouseOut="MM_swapImage('rating_stars','','user_rating_stars_5.gif',1);"  onMouseOver="MM_swapImage('rating_stars','','user_rating_stars_4.gif',1);"  >
<area shape="rect" coords="71,0,86,16" onClick="myRequest.queueGetRequest('whatever.cgi?ISBN=#ISBNNO&userid=###&rank=5', document.getElementById('starID'));" alt="5" onMouseOut="MM_swapImage('rating_stars','','user_rating_stars_5.gif',1);"  onMouseOver="MM_swapImage('rating_stars','','user_rating_stars_5.gif',1);"  >
</map>
</div>

Because there will be multiples of this on one page, you will have to enumerate the div's id, as well as the map name like so:


<div id="starID1">
<b>Rate It: </b><img name="rating_stars_1" align="absmiddle" src="user_rating_stars_0.gif" width="87" height="20" border="0" usemap="#rating_stars_map_1" alt="Rate This Title">
<map name="rating_stars_map_1">
<area shape="rect" coords="7,0,22,16" onClick="myRequest.queueGetRequest('whatever.cgi?ISBN=#ISBNNO&userid=###&rank=1', document.getElementById('starID1'));" alt="1" onMouseOut="MM_swapImage('rating_stars_1','','user_rating_stars_5.gif',1);"  onMouseOver="MM_swapImage('rating_stars_1','','user_rating_stars_1.gif',1);"  >
<area shape="rect" coords="23,0,38,16" onClick="myRequest.queueGetRequest('whatever.cgi?ISBN=#ISBNNO&userid=###&rank=2', document.getElementById('starID1'));" alt="2" onMouseOut="MM_swapImage('rating_stars_1','','user_rating_stars_5.gif',1);"  onMouseOver="MM_swapImage('rating_stars_1','','user_rating_stars_2.gif',1);"  >
<area shape="rect" coords="39,0,54,16" onClick="myRequest.queueGetRequest('whatever.cgi?ISBN=#ISBNNO&userid=###&rank=3', document.getElementById('starID1'));" alt="3" onMouseOut="MM_swapImage('rating_stars_1','','user_rating_stars_5.gif',1);"  onMouseOver="MM_swapImage('rating_stars_1','','user_rating_stars_3.gif',1);"  >
<area shape="rect" coords="55,0,70,16" onClick="myRequest.queueGetRequest('whatever.cgi?ISBN=#ISBNNO&userid=###&rank=4', document.getElementById('starID1'));" alt="4" onMouseOut="MM_swapImage('rating_stars_1','','user_rating_stars_5.gif',1);"  onMouseOver="MM_swapImage('rating_stars_1','','user_rating_stars_4.gif',1);"  >
<area shape="rect" coords="71,0,86,16" onClick="myRequest.queueGetRequest('whatever.cgi?ISBN=#ISBNNO&userid=###&rank=5', document.getElementById('starID1'));" alt="5" onMouseOut="MM_swapImage('rating_stars_1','','user_rating_stars_5.gif',1);"  onMouseOver="MM_swapImage('rating_stars_1','','user_rating_stars_5.gif',1);"  >
</map>
</div>

<div id="starID2">
<b>Rate It: </b><img name="rating_stars_2" align="absmiddle" src="user_rating_stars_0.gif" width="87" height="20" border="0" usemap="#rating_stars_map_2" alt="Rate This Title">
<map name="rating_stars_map_2">
<area shape="rect" coords="7,0,22,16" onClick="myRequest.queueGetRequest('whatever.cgi?ISBN=#ISBNNO&userid=###&rank=1', document.getElementById('starID2'));" alt="1" onMouseOut="MM_swapImage('rating_stars_2','','user_rating_stars_5.gif',1);"  onMouseOver="MM_swapImage('rating_stars_2','','user_rating_stars_1.gif',1);"  >
<area shape="rect" coords="23,0,38,16" onClick="myRequest.queueGetRequest('whatever.cgi?ISBN=#ISBNNO&userid=###&rank=2', document.getElementById('starID2'));" alt="2" onMouseOut="MM_swapImage('rating_stars_2','','user_rating_stars_5.gif',1);"  onMouseOver="MM_swapImage('rating_stars_2','','user_rating_stars_2.gif',1);"  >
<area shape="rect" coords="39,0,54,16" onClick="myRequest.queueGetRequest('whatever.cgi?ISBN=#ISBNNO&userid=###&rank=3', document.getElementById('starID2'));" alt="3" onMouseOut="MM_swapImage('rating_stars_2','','user_rating_stars_5.gif',1);"  onMouseOver="MM_swapImage('rating_stars_2','','user_rating_stars_3.gif',1);"  >
<area shape="rect" coords="55,0,70,16" onClick="myRequest.queueGetRequest('whatever.cgi?ISBN=#ISBNNO&userid=###&rank=4', document.getElementById('starID2'));" alt="4" onMouseOut="MM_swapImage('rating_stars_2','','user_rating_stars_5.gif',1);"  onMouseOver="MM_swapImage('rating_stars_2','','user_rating_stars_4.gif',1);"  >
<area shape="rect" coords="71,0,86,16" onClick="myRequest.queueGetRequest('whatever.cgi?ISBN=#ISBNNO&userid=###&rank=5', document.getElementById('starID2'));" alt="5" onMouseOut="MM_swapImage('rating_stars_2','','user_rating_stars_5.gif',1);"  onMouseOver="MM_swapImage('rating_stars_2','','user_rating_stars_5.gif',1);"  >
</map>
</div>

etc. etc.

The queueGetRequest passes the URL to send the GET request to (the first parameter), as well as the object to change when something happens (The second parameter, document.getElementById("divname")).

The functions onRequest and onService changes the HTML inside of the DIV, so that it is completely replaced by whatever the CGI/PHP script passes back as output.

The three functions directly above this comment section you can leave like that, as they will work fine.  If you want, you can change the text in "onRequest()" to something different than "Please Wait", but that's up to you.  If you need help, just give me a call, and I'll get back to you asap.



*/