//
// $Id: pageloader.js 2158 2005-10-20 18:17:51Z barrickw $
//
// Browser sniffing.
var mozilla = (document.getElementById && !document.all);
var nashville = (document.all && !document.getElementById);
var tasman = (document.all && document.getElementById);

// Functions.
function GetObject(u)
  {
  if(nashville) return eval('document.all["' + u+ '"]');
  else if(tasman || mozilla) return document.getElementById(u);
  else return null;
  }

function Append(x,s)
  {
  x = GetObject(x);
  s = unescape(s+'<br>');
  //alert(x + ' ' + s);
  if(document.layers)
    {
    document.open();document.write(s);document.close();
    }
  else
    {
    x.innerHTML = x.innerHTML+s;
    }
  }

function Replace(x,s)
  {
  x = GetObject(x);
  s = unescape(s+'<br>');
  //alert(x + ' ' + s);
  if (document.layers)
    {
    document.open(); document.write(s); document.close();
    }
  else
    {
    x.innerHTML = s;
    }
  }

function ShowElement(u)
  {
  var r; var y = "block"; var z = "none";
  if (nashville || tasman)
    {
    r = eval('document.all["' + u + '"]');
    if (r == null) return;
    if (r.style.display != z)
      r.style.display = z;
    else
      r.style.display = y;
    }
  else if (mozilla)
    {
    r = document.getElementById(u);
    if (r == null) return;
    if (r.isShowing)
      {
      r.style.display = z; r.isShowing = false;
      }
    else
      {
      r.style.display = y; r.isShowing = true;
      }
    }
  }

var timerId = 0;

// Global vars
var timerTickAmount = 100;
var timeoutInterval = 1000;
var timeoutTotal = 15000;
var timeoutAccum = 0;
var loadingPage = '';
var loadingThread = '';
var lastShowing = null;
var lastURL     = null;
var errorsAreAlerts = 0;

function SetInnerHTML(s,t)
  {
  var threadObj = GetObject(t);
  if(threadObj == null) return;
  threadObj.innerHTML = s;
  if(eval("window.frames[ 'pageLoader' ].document") == undefined)
    {
	alert("This functionality is not supported (more than once) in you browser software.");
	return;
    }
  x = eval("window.frames[ 'pageLoader' ].document.getElementById('complete')");
  if(x)
    {
    x.innerHTML = '0';
    }
  }

function RecoverFromError ()
  {
  window.onerror = '';
  if (timerId != 0) 
    clearTimeout(timerId);
  timerId = 0;
  if(errorsAreAlerts == 0)
    {
    SetInnerHTML('<font color=red>Cannot load the requested information.</font>', loadingThread);
    }
  else if(errorsAreAlerts == 1)
    {
    alert('Cannot load the requested information.');
    }
  
  //window.frames[ 'pageLoader' ].window.location.replace('about:');
  }

function ReloadFrame ()
  {
  window.frames[ 'pageLoader' ].window.location.replace(loadingPage);
  timeoutAccum = 0;
  if(timerId == 0)
    timerId = setTimeout('TimeoutFunction ()', timerTickAmount);
  }

function OpenInFrame(s, t)
  {
  loadingPage = s;
  loadingThread = t;
  //debugger;
  ReloadFrame();
  lastShowing = t;
  }

function TimeoutFunction ()
  {
  // Try to copy the span contents
  window.onerror = RecoverFromError;


  testComplete = eval("window.frames[ 'pageLoader' ].document.getElementById('complete')");
  // Close out the timerId
  timerId = 0;

  if (testComplete)
    {
    if (testComplete.innerHTML == '1')
      {
      //Completed successfully, display 'content' message in IFrame
      x = eval("window.frames[ 'pageLoader' ].document.getElementById('content')");
      if (x)
        {
        SetInnerHTML( x.innerHTML, loadingThread );
        return;
        }
      }
    else
      {
      //Completed, but not successfully.  display error message
      x = eval("window.frames[ 'pageLoader' ].document.getElementById('error')");
      if (x)
        {
        if(errorsAreAlerts == 0)
          {
	  SetInnerHTML( x.innerHTML, loadingThread );
          }
	else if(errorsAreAlerts == 1)
          {
	  alert(x.innerHTML);
	  }
        return;
        }
      }
    }

  window.onerror = '';
  timeoutAccum += timerTickAmount;

  if(timeoutTotal <= timeoutAccum)
    {
    alert("Reloading page");
    
    SetInnerHTML ('<b>Attempting to reload requested information.</b>' , loadingThread );
    ReloadFrame ();
    return;
    }

  if (timeoutAccum % timeoutInterval == 0)
    SetInnerHTML ('Loading requested information.  Please wait.', loadingThread);

  timerId = setTimeout ( 'TimeoutFunction ()', timerTickAmount );
  }



//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//AsyncResponse javascript
//
//  Used in conjunction with "comm/response/ASyncResponse" to provide a
//  framework for reliable asyncrounous browser-chameleon communication.
//  uses <iframe name="pageloader"> for asynchronous loading
//
var asyncRequests = new AsyncReplies();

//API
//-------------------------------------------------
//
//starts the load process, returns the reply ID to use with the other methods:
//  string asyncRequests.Load(url)
//determines if reply recieved yet:
//  bool asyncRequests.IsComplete(id)
//determines if reply was "success", returns false if no reply recieved yet
//  bool asyncRequests.Success(id)
//retrieve the content of the success message:
//  string asyncRequests.Content(id)
//retrieve the error message of the reply:
//  string asyncRequests.ErrorMessage(id)
//frees resources / reloading of the specified id:
//  void asyncRequests.Free(id)
function AsyncReplies ()
  {
  this.loadedUrls = new Array();
  //Statuses:
  //  -1 ==> No reply yet
  //   0 ==> Error
  //   1 ==> Success
  this.replyStatuses = new Array();
  this.replyContents = new Array();
  //Used codes:
  //  0 ==> in-active, available to use
  //  1 ==> currently active
  //  2 ==> currently used, but no reply recieved yet.  Kepp until reply then
  //        free it
  this.isUsed = new Array();
  this.timerIds = new Array();
  this.timerAcc = new Array();

  this.Load = function (url)
    {
    var id = this.GetNextId();
    if(id > 0)
      {
      var loadUrl = url;
      if(!loadUrl.match('\&$'))
        {
        loadUrl += "&";
        }
      loadUrl += "asyncid=" + id + "&";

      //populate data
      this.isUsed[id] = 1;
      this.loadedUrls[id] = loadUrl;
      this.replyContents[id] = "";
      this.replyStatuses[id] = -1;
      this.timerIds[id] = 0;
      this.timerAcc[id] = 0;

      this.TimerLoad(id, loadUrl);
      }
    return id;
    };

  this.IsComplete = function (id)
    {
    if(this.isUsed[id] == 1 && this.replyStatuses[id] > 0)
      {
      return true;
      }
    else
      {
      return false;
      }
    };

  this.Success = function (id)
    {
    if(this.isUsed[id] == 1 && this.replyStatuses[id] == 1)
      {
      return true;
      }
    else
      {
      return false;
      }
    };

  this.Content = function (id)
    {
    if(this.isUsed[id] == 1 && this.replyStatuses[id] == 1)
      {
      return this.replyContents[id];
      }
    else
      {
      return "";
      }
    };

  this.ErrorMessage = function (id)
    {
    if(this.isUsed[id] == 1 && this.replyStatuses[id] == 0)
      {
      return this.replyContents[id];
      }
    else
      {
      return "";
      }
    };

  this.Free = function (id)
    {
    if(this.replyStatuses[id] > 0)
      {
      //have recieved reply, set for re-use
      this.isUsed[id] = 0;
      }
    else
      {
      //set for wait to get response before clearing
      this.isUsed[id] = 2;
      }
    };

  this.GetUrl = function (id)
    {
    if(this.isUsed[id] == 1)
      {
      return this.loadedUrls[id];
      }
    return "";
    };

  //private methods
  this.GetNextId = function ()
    {
    //check if there is currently an available slot (i.e. isUsed[n] = 0)
    var i=1;
    var found = false;
      
    while(i < this.isUsed.length && !found)
      {
      if(this.isUsed[i] == 0)
        {
        found = true;
        }
      else
        {
        i++;
        }
      }
    if(!found)
      {
      //set the slot in each array in-case read attempt before set
      //  otherwise
      this.loadedUrls[i] = "";
      this.replyStatuses[i] = -1;
      this.replyContents[i] = "";
      this.isUsed[i] = 1;
      }
    return i;
    };

  this.Complete = function(id, status, content)
    {
    if(this.isUsed[id] > 0)
      {
      //clear the timer
      if(this.timerIds[id] != 0)
        {
        clearTimeout(this.timerIds[id]);
        }
      this.timerIds[id] = 0;
	
      //active
      if(this.replyStatuses[id] == -1)
        {
        //waiting for response
        //set content first in-case rare timing occurs and content asked
        //for between assignments!
        this.replyContents[id] = content;
        this.replyStatuses[id] = status;
        }

      //check if we are waiting for response to free it
      if(this.isUsed[id] == 2)
        {
        //set as un-used, since reply recieved
        this.isUsed[id] = 0;
        }
      }
    };

  this.TimerLoad = function (id, url)
    {
    window.frames[ 'pageLoader' ].window.location.replace(url);
    //reset waiting period
    this.timerAcc[id] = 0;
    if(this.timerIds[id] == 0)
      {
      this.timerIds[id] = setTimeout('asyncRequests.Timeout('+id+')',
        timerTickAmount);
      }
    };

  this.Timeout = function (id)
    {
    if(this.isUsed[id] == 1 && this.replyStatuses[id] == -1)
      {
      this.timerAcc[id] += timerTickAmount;

      if(this.timerAcc[id] <= timeoutTotal)
        {
        //Still has time before giving up, try again
        this.replyContents[id] = 'Attempting to reload requested information.';
        SetInnerHTML ('<b>Attempting to reload requested information.</b>',
          'async' );
        this.timerIds[id] = setTimeout('asyncRequests.Timeout('+id+')',
          timerTickAmount);
        }
      else
        {
        //Timedout, don't wait any more.
        //  Automatic ERROR "Timed out.  Unknown reason."
        this.timerIds[id] = 0;
        this.Complete(id, 0, 'Timed out.  Unknown reason.');
        }
      }
    //else
    //  Timeout for in-active or already replied to request.  Ignore, since
    //  most likely a successfull completion before timeout reached
    };

  return this;
  }


//Called by Asyncronous responses from chameleon
function AsyncComplete(id, success, content)
  {
  asyncRequests.Complete(id, success, content);
  }
