/**

 * @fileoverview XMLHttpRequest with visual textual activity indicator

 * @author (R---S)

 */



/**

 * This method provides XML HTTP Request functionality including callback.

 *

 * @param {String}  url                 The URL where to place the AJAX request

 * @param {String}  requestMethod       The way the AJAX request should be placed: one out of {POST | GET | PUT}

 * @param {String}  passedData          The data that should be passed to the AJAX request

 * @param {String}  responseType        The response type of the AJAX request: one out of {Text | XML}

 * @param {Object}  callbackFunction    The callback function which should be called upon AJAX request completion

 * @param {Object}  callbackParameters  The parameters which should be passed to the callback function

 */

function AjaxRequest(url, requestMethod, passedData, responseType, callbackFunction, callbackParameters) {

  // determines whether the activity indicator should contain debugging info or not

  var verbose = false;



  // create a random id for the activity indicator

  var randomId = getRandomId_();

//  indicateAjaxActivity_(randomId, url.substring(url.lastIndexOf("/") + 1, url.length - 4) + "...", verbose);



  // create a request object

  var ajaxRequest = getXmlHttpRequestObject_(requestMethod, url, true, passedData);



  // when done, call the callback function

  ajaxRequest.onreadystatechange = function() {

    if (ajaxRequest.readyState == 4) {

      if (ajaxRequest.status == 200) {

        indicateAjaxActivityFinished_(randomId);

        if (responseType.toLowerCase() == "text") {

          if (callbackParameters === null) {

            callbackFunction(ajaxRequest.responseText);

          } else {

            callbackFunction(ajaxRequest.responseText, callbackParameters);

          }

        } else if (responseType.toLowerCase() == "xml") {

          if (callbackParameters === null) {

            callbackFunction(ajaxRequest.responseXML);

          } else {

            callbackFunction(ajaxRequest.responseXML, callbackParameters);

          }

        }

      } else {

        indicateAjaxActivityFinished_(randomId);

       // alert('There was a problem with the XML HTTP Request.\nAjax Request Ready State: ' + ajaxRequest.readyState + '\nAjax Request Status: ' + ajaxRequest.status);

      }

    }

  };



  // place the request

  if (requestMethod.toLowerCase() == "post") {

    ajaxRequest.send(passedData);

  } else {

    ajaxRequest.send(null);

  }

};



/**

 * This method provides XML HTTP Request functionality including callback,

 * but this time the request is blocking.

 *

 * @param {String}  url            The URL where to place the AJAX request

 * @param {String}  requestMethod  The way the AJAX request should be placed: one out of {POST | GET | PUT}

 * @param {String}  passedData     The data that should be passed to the AJAX request

 * @param {String}  responseType   The response type of the AJAX request: one out of {Text | XML}

 */

function BlockingAjaxRequest(url, requestMethod, passedData, responseType) {

  // determines whether the activity indicator should contain debugging info or not

  var verbose = false;



  // create a random id for the activity indicator

  var randomId = getRandomId_();

  indicateAjaxActivity_(randomId, url.substring(url.lastIndexOf("/") + 1, url.length - 4) + "...", verbose);



  // create a request object

  var ajaxRequest = getXmlHttpRequestObject_(requestMethod, url, false, passedData);



  // place the request

  if (requestMethod.toLowerCase() == "post") {

    ajaxRequest.send(passedData);

  } else {

    ajaxRequest.send(null);

  }



  // when done, call the callback function

  if (ajaxRequest.status == 200) {

    indicateAjaxActivityFinished_(randomId);

    if (responseType.toLowerCase() == "text") {

      return ajaxRequest.responseText;

    } else if (responseType.toLowerCase() == "xml") {

      return ajaxRequest.responseXML;

    }

  } else {

    indicateAjaxActivityFinished_(randomId);

   // alert('There was a problem with the XML HTTP Request.\nAjax Request Ready State: ' + ajaxRequest.readyState + '\nAjax Request Status: ' + ajaxRequest.status);

  }

};



/**

 * This method creates an XML HTTP request object

 *

 */

function getXmlHttpRequestObject_(requestMethod, url, isAsynchronous, passedData) {

  var ajaxRequest = false;

  // create XMLHttpRequest Object for AJAX

  try {

    ajaxRequest = new XMLHttpRequest();

  } catch(e) {

    try {

      ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");

    } catch(e) {

      try {

        ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");

      } catch(e) {

        alert("Unable to Create the XMLHttpRequest Object.\nTry Updating to a Current Web Browser.");

        return false;

      }

    }

  }



  if (requestMethod.toLowerCase() == "post") {

    // open the connection

    ajaxRequest.open(requestMethod, url, isAsynchronous);

    // some header settings required for post

    ajaxRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

    ajaxRequest.setRequestHeader("Method", "POST " + url + " HTTP/1.1");

  } else {

    // open the connection, concat passed data as GET variables

    ajaxRequest.open(requestMethod, url+'?'+passedData, isAsynchronous);

    // some header settings required for get

    // this disables caching of GET operations

    ajaxRequest.setRequestHeader('If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT');

  }

  return ajaxRequest;

};



// global variable which holds the number of active indicators

var globalIndicatorCounter = 0;



// global array which holds the timeout ids of the ajax indicators

var globalIndicatorUpdateTimeout = new Array();



/**

 * This method provides visual textual feedback to signalize ajax activity.

 *

 * @param {String}   randomId  The random id of the activity indicator div object

 * @param {String}   url       The url where the ajax request is placed

 * @param {Boolean}  verbose   Whether the indicator should contain debugging info

 */

function indicateAjaxActivity_(randomId, url, verbose) {

  // if we do not already have an activity indicator then create one

  if (!document.getElementById(randomId)) {

    var indicator = document.createElement("div");

    indicator.style.padding = "0.2em";

    indicator.style.position = "fixed";

    indicator.style.top = 10 + globalIndicatorCounter * 4 + "px";

    indicator.style.right = 10 + globalIndicatorCounter * 4 + "px";

    indicator.style.zIndex = 1 + globalIndicatorCounter;

    indicator.style.backgroundColor = "rgb(" + createRgbComponent_() + ", " + createRgbComponent_() + ", " + createRgbComponent_() + ")";

    indicator.style.opacity = "1.0";

    // we have created one activity indicator

    globalIndicatorCounter++;

    indicator.id = randomId;

    var anchor = document.createElement("a");

    anchor.onclick = function () {

      indicateAjaxActivityFinished_(randomId);

      return false;

    };

    anchor.style.textDecoration = "none";

    anchor.style.color = "white";

    anchor.style.fontWeight = "bold";

    anchor.style.fontSize = "0.8em";

    if (verbose) {

      anchor.appendChild(document.createTextNode("Loading..."));

      anchor.appendChild(document.createElement("br"));

      anchor.appendChild(document.createTextNode("Ajax Request ID: " + randomId));

      anchor.appendChild(document.createElement("br"));

      anchor.appendChild(document.createTextNode("Currently Active Ajax Requests: " + globalIndicatorCounter));

      anchor.appendChild(document.createElement("br"));

      anchor.appendChild(document.createTextNode("Accessing: " + url));

      anchor.appendChild(document.createElement("br"));

    } else {

      anchor.appendChild(document.createTextNode("Loading " + url));

    }

    indicator.appendChild(anchor);

    document.body.insertBefore(indicator, document.getElementsByTagName("body")[0].firstChild);

  } else {

    // else if we already have an activity indicator then re-use it

    var indicator = document.getElementById(randomId);

    indicator.style.backgroundColor = "rgb(" + createRgbComponent_() + ", " + createRgbComponent_() + ", " + createRgbComponent_() + ")";

    window.clearTimeout(globalIndicatorUpdateTimeout[randomId]);

  }

  globalIndicatorUpdateTimeout[randomId] = window.setTimeout(function() { indicateAjaxActivity_(randomId, url, verbose); return false; }, 500);

};



/**

 * This method destroys the graphical feedback div

 *

 * @param {String}  randomId  The random id of the activity indicator div object

 */

function indicateAjaxActivityFinished_(randomId) {

  // we have destroyed one activity indicator

  globalIndicatorCounter--;

  window.clearTimeout(globalIndicatorUpdateTimeout[randomId]);

  try {

    document.body.removeChild(document.getElementById(randomId));

   } catch (e) {

     return false;

   }

};



/**

 * This method returns a random value between 0 and 255

 * as needed for an RGB color value

 *

 */

function createRgbComponent_() {

  return Math.round((Math.random() * 255) % 255);

};



/**

 * This method returns a random id between 0 and 10.000

 *

 */

function getRandomId_() {

  return Math.round(Math.random() * 10000);

};

