
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/, ''); };

var animationManager = new AnimationManager();

var throttles = {};
var throttleTimer = false;
var throttleCount = 0;

function removeThrottle(id)
{
  if (throttles[id] !== undefined)
  {
    delete throttles[id];
    throttleCount--;
  }
}

var myScrollTop = 0;

function onThrottleEvent(id, ajaxDuration, keyDuration, script)
{
  if (throttles[id] === undefined)
  {
    throttles[id] = new JumbuckThrottle(id, ajaxDuration, keyDuration, script);
    throttleCount++;
  }

  throttles[id].incrementEventId();

  if (!throttleTimer)
  {
    setTimeout("onThrottleTimer();", 500);
    throttleTimer = true;
  }
}

function resetThrottle(id, ignoreNextEvent)
{
  var throttle =  throttles[id];
  if (throttle !== null && throttle !== undefined)
  {
    throttle.lastEventId = throttle.lastEnabledEventId;
    throttle.lastAjaxTime = -1;
    throttle.lastEventTime = -1;
    throttle.ignoreNextEvent = ignoreNextEvent;
  }
}

var rotatingList = {};
var rotatingListCount = 0;

function getRotatingListPollingURLParams()
{
  var params = '';
  return params;
}

function JumbuckThrottle(id, ajaxDuration, keyDuration, script)
{
  this.id = id;
  this.lastEventTime = -1;
  this.lastAjaxTime = -1;

  this.lastEventId = -1;
  this.lastEnabledEventId = -1;
  this.ignoreNextEvent = false;

  this.keyDuration = keyDuration;
  this.ajaxDuration = ajaxDuration;

  this.script = script;

  this.incrementEventId = function()
  {
    if (this.ignoreNextEvent)
    {
      this.ignoreNextEvent = false;
    }
    else
    {
      this.lastEventId++;
      this.lastEventTime = new Date().getTime();
    }
  }

  this.housekeep = function(currentTime)
  {
    if (document.getElementById(this.id) === undefined)
    {
      return false;
    }
    if (this.lastEventId > this.lastEnabledEventId && currentTime > (this.lastEventTime + this.keyDuration) && currentTime > (this.lastAjaxTime + this.ajaxDuration))
    {
      this.lastEnabledEventId = this.lastEventId;
      if (!ajaxBlocked)
      {
        var currentTime = new Date().getTime();
        this.lastEventTime = currentTime;
        this.lastAjaxTime = currentTime;

        eval(this.script);
      }
    }
    return true;
  }
}

function onThrottleTimer()
{
  if (throttleTimer)
  {
    var currentTime = new Date().getTime();
    for (var id in throttles)
    {
      if (!throttles[id].housekeep(currentTime))
      {
        delete throttles[id];
        throttleCount--;
      }
    }
    if (throttleCount == 0)
    {
      throttleTimer = false;
    }
    else
    {
      throttleTimer = true;
      setTimeout("onThrottleTimer();", 100);
    }
  }
}

function AnimationManager()
{
  this.anims = {};
  this.animCount = 0;
  this.currentTime = 0;

  this.process = function()
  {
    this.currentTime = new Date().getTime();

    for (var i in this.anims)
    {
      if (this.anims[i].process(this.currentTime))
      {
        this.removeAnimation(i);
      }
    }

    setTimeout("animationManager.process();", 50);
  };

  this.verticalScroll = function(markupId, starty, endy, starttime, duration)
  {
    if (document.getElementById(markupId) !== null && document.getElementById(markupId) !== undefined)
    {
      this.anims[markupId] = new AnimationInstance(markupId, -1, -1, starty, endy, -1, -1, starttime, duration, false);
      this.animCount++;
    }
  };

  this.horizontalScroll = function(markupId, startx, endx, starttime, duration)
  {
    if (document.getElementById(markupId) !== null && document.getElementById(markupId) !== undefined)
    {
      this.anims[markupId] = new AnimationInstance(markupId, startx, endx, -1, -1, -1, -1, starttime, duration, false);
      this.animCount++;
    }
  };

  this.fade = function(markupId, pixelX, pixelY, startopacity, endopacity, starttime, duration, removeElement)
  {
    //alert("at start of fade fn - markupId = " + markupId + ", object = " + document.getElementById(markupId) );
    if (document.getElementById(markupId) !== null && document.getElementById(markupId) !== undefined)
    {
      //alert("about to start fade! markupId = " + markupId)
      this.anims[markupId] = new AnimationInstance(markupId, pixelX, pixelX, pixelY, pixelY, startopacity, endopacity, starttime, duration, removeElement);
      //alert("animation started!");
      this.animCount++;
    }
  };

  this.setupTransitionFade = function(markupId)
  {
    var thisDiv = document.getElementById(markupId);
    //alert("in setupTransitionFade. markupId = " + markupId + ", thisDiv = " + thisDiv);

    if (thisDiv !== null && thisDiv !== undefined)
    {
      //alert("inside divCheck!");
      this.assignCopyId(thisDiv);

      //alert("after assignCopy!");
      var elem = document.createElement("DIV");
      //alert("setting ID of " + markupId)
      elem.id = markupId;
      thisDiv.parentNode.appendChild(elem);
    }
  };

  this.getCopyIdFromId = function(markupId)
  {
    if (markupId !== null && markupId !== undefined)
    {
      return markupId + "jcopy";
    }
    return markupId;
  }

  this.doTransitionFade = function(markupId, duration)
  {
    var copyId = this.getCopyIdFromId(markupId);

    if (this.anims[copyId] !== null && this.anims[copyId] !== undefined)
    {
      this.removeAnimation(copyId);
    }
    //alert("starting first fade!");
    this.fade(markupId, -1, -1, 0, 100, -1, duration, false);
    //alert("starting second fade!");
    this.fade(copyId, -1, -1, 100, 0, -1, duration, true);
  };

  this.assignCopyId = function(element)
  {
    if (element !== null && element !== undefined && element.id !== undefined)
    {
      var children = element.childNodes;
      if (children !== null && children !== undefined)
      {
        for (var i=0; i < children.length; i++)
        {
          this.assignCopyId(children[i]);
        }
      }

      //alert("setting element event values.");
      element.onclick = "";
      element.onmouseover = "";
      element.onmouseout = "";
      //alert("getting element copy id");
      element.id = this.getCopyIdFromId(element.id);
      //alert("finished setting element event values");
    }
  }

  this.removeAnimation = function(markupId)
  {
    if (this.anims[markupId] !== undefined && this.anims[markupId] !== null)
    {
      if (this.anims[markupId].removeElement)
      {
        var thisNode = document.getElementById(markupId);
        if (thisNode != null && thisNode != undefined)
        {
          thisNode.parentNode.removeChild(thisNode);
        }
      }

      delete this.anims[markupId];
      this.animCount--;
    }
  };

  this.setOpacity = function(markupId, opacity)
  {
    var elem = document.getElementById(markupId);

    if (elem !== null && elem !== undefined)
    {
      elem.style.visibility = "visible";

        //this should cover all the different browser opacity settings.
      elem.style.opacity = (opacity / 100);
      elem.style.MozOpacity = (opacity / 100);
      elem.style.KhtmlOpacity = (opacity / 100);
      elem.style.filter = "alpha(Opacity=" + opacity + ")";
    }
  }

  this.process();
}

function AnimationInstance(markupId, startx, endx, starty, endy, startopacity, endopacity, starttime, duration, removeElement)
{
  this.started = false;
  this.markupId = markupId;
  this.startx = startx;
  this.endx = endx;
  this.starty = starty;
  this.endy = endy;

  this.starttime = starttime;
  if (this.starttime == -1)
  {
    this.starttime = new Date().getTime();
  }

  this.duration = duration;
  this.startopacity = startopacity;
  this.endopacity = endopacity;
  this.removeElement = removeElement;

  this.currentopacity = -1;
  this.currentx = -1;
  this.currenty = -1;

  this.process = function(currentTime)
  {
    var thisElem = document.getElementById(this.markupId);
    if (thisElem === undefined || thisElem === null)
    {
      return false;
    }

    if (this.starttime <= currentTime)
    {
      if (!this.started)
      {
        this.start();
      }

      var timePercent = Math.round(Math.min(100, (currentTime - this.starttime) * 100 / this.duration));

      if (this.endx != -1)
      {
        var newx = Math.round(this.startx + ( (this.endx - this.startx) * timePercent / 100 ));
        if (newx != this.currentx)
        {
          this.currentx = newx;
          thisElem.style.left = this.currentx + "px";
        }
      }

      if (this.endy != -1)
      {
        var newy = Math.round(this.starty + ( (this.endy - this.starty) * timePercent / 100 ));
        if (newy != this.currenty)
        {
          this.currenty = newy;
          thisElem.style.top = this.currenty + "px";
        }
      }

      if (this.endopacity != -1)
      {
        var newopacity = Math.round(this.startopacity + ( (this.endopacity - this.startopacity) * timePercent / 100 ));

        if (newopacity != this.currentopacity)
        {
          this.currentopacity = newopacity;
          animationManager.setOpacity(this.markupId, this.currentopacity);
        }
      }

      return (timePercent == 100);
    }
  };

  this.start = function()
  {
    var thisElem = document.getElementById(this.markupId);
    if (thisElem === undefined || thisElem === null)
    {
      return;
    }

    if (this.endx != -1)
    {
      if (this.startx == -1)
      {
        this.startx = thisElem.offsetLeft;
      }
      else
      {
        thisElem.style.left = this.startx + "px";
      }
      this.currentx = this.startx;
    }
    if (this.endy != -1)
    {
      if (this.starty == -1)
      {
        this.starty = thisElem.offsetTop;
      }
      else
      {
        thisElem.style.top = this.starty + "px";
      }
      this.currenty = this.starty;
    }
    if (this.endopacity != -1)
    {
      if (this.startopacity == -1)
      {
        this.startopacity = thisElem.style.opacity;
      }
      else
      {
        animationManager.setOpacity(this.markupId, this.startopacity);
      }
      this.currentopacity = this.startopacity;
    }
    this.started = true;
  };
}


var jForms = {};
var jFormCount = 0;

var JumbuckForm = Class.create(
{
  initialize: function(id, warnOnChange)
  {
    this.id = id;
    this.elements = {};
    this.elementCount = 0;
    this.warnOnChange = warnOnChange;
    this.validateData = {};
    this.validateCount = 0;
  },

  addElement: function(id)
  {
    this.elements[id] = new JumbuckFormElement(id, this.id);
  },

  removeElement: function(id)
  {
    delete this.elements[id];
  },

  handleElementChanged: function(id)
  {
    this.elements[id].changed = true;
    this.validate(false, true, false);
  },

  resetChanges: function()
  {
    for (var jmb in this.elements)
    {
      this.elements[jmb].changed = false;
    }
  },

  hasChanged: function()
  {
    if (!this.warnOnChange) return false;

    for (var loopId in this.elements)
    {
      if (this.elements[loopId].changed)
      {
        return true;
      }
    }
    return false;
  },

  getCheck : function(id)
  {
    return this.validateData[id];
  },

  validate: function(showErrors, updateElementStyles, resetChanges)
  {
    var error = 'The following errors were found: \n\n';
    var errorCount = 0;
    var returnVal = 0; //validates

    for (var jmb in this.elements)
    {
      this.elements[jmb].jErrorCount = 0;
      if (tooltips[jmb] != undefined && tooltips[jmb] != null)
      {
        tooltips[jmb].reset();
      }
    }

    for (jmb in this.validateData)
    {
      if (!this.validateData[jmb].validate())
      {
        error += ('- ' + this.validateData[jmb].message + '\n');
        errorCount++;
      }
    }

    if (errorCount > 0 && showErrors)
    {
      alert(error + '\n ');
      returnVal = 1; //doesn't validate.. no request sent..
    }

    if (resetChanges)
    {
      this.resetChanges();
    }

    if (updateElementStyles)
    {
      for (jmb in this.elements)
      {
        this.elements[jmb].setErrorStyle();
      }
    }
    return returnVal;
  },

  setElementHasError: function(id, error)
  {
    this.elements[id].errorCount++;

    if (tooltips[id] != undefined && tooltips[id] != null)
    {
      if (this.elements[id].errorCount == 1)
      {
        tooltips[id].add('<br /><br />Current Errors:<br />');
      }
      tooltips[id].add('- ' + error + '<br />');
    }
  },

  addValuesIdenticalCheck: function(checkId, elementId1, elementId2, error)
  {
    this.validateData[checkId] = new CheckValuesIdentical(elementId1, elementId2, error, this);
    this.validateCount++;
  },

  addValueNotNullCheck: function(checkId, elementId, error)
  {
    this.validateData[checkId] = new CheckValueNotNull(elementId, error, this);
    this.validateCount++;
  },

  addCheckboxEqualToCheck: function(checkId, elementId, error, value)
  {
    this.validateData[checkId] = new CheckCheckBoxEqualTo(elementId, error, this, value);
    this.validateCount++;
  },

  addValueLengthValidCheck: function(checkId, elementId, error, min, max)
  {
    this.validateData[checkId] = new CheckValueLengthValid(elementId, error, this, min, max);
    this.validateCount++;
  },

  addDropDownValidCheck: function(checkId, elementId, error, defaultVal)
  {
    this.validateData[checkId] = new CheckDropDownValue(elementId, error, defaultVal, this);
    this.validateCount++;
  },

  addComponentValidServerCheck: function(checkId, elementId, error)
  {
    this.validateData[checkId] = new ServerCheckComponentValid(elementId, error, this);
    this.validateCount++;
  },

  addLoginServerCheck: function(checkId, usernameId, passwordId)
  {
    this.validateData[checkId] = new ServerCheckLogin(usernameId, passwordId, this);
    this.validateCount++;
  },

  removeCheck: function(checkId)
  {
    delete this.validateData[checkId];
    this.validateCount--;
  }
});

function addJumbuckForm(id, warnOnChange)
{
  //alert("adding jumbuck form!");
  //alert('add jumbuck form - ' + id);
  if (jForms[id] == undefined)
  {
    jForms[id] = new JumbuckForm(id, warnOnChange);
    jFormCount++;
  }
  //alert("finished - adding jumbuck form!");
}

function removeJumbuckForm(id)
{
  //alert('remove jumbuck form - ' + id);
  var form = jForms[id];
  if (form != undefined && form != null)
  {
    delete jForms[id];
    jFormCount--;
  }
}

function getJumbuckFormPanel(id)
{
  return jForms[id];
}

var JumbuckFormElement = Class.create(
{
  initialize: function(id, formId)
  {
    this.id = id;
    this.formId = formId;
    this.errorCount = 0;
    this.changed = false;
  },

  setErrorStyle: function()
  {
    var elem = document.getElementById(this.id);
    if (elem === null || elem === undefined) return;

    if (this.errorCount > 0)
    {
      elem.style.backgroundColor = "#ffffff"; //MRR.  Made it a nicer shade of red.
    }
    else if (this.changed)
    {
      elem.style.backgroundColor = "#ffffff";
    }
    else
    {
      elem.style.backgroundColor = "#ffffff";
    }
  }
});

function getFormElementValue(id)
{
  var elem = document.getElementById(id);
  if (elem !== null)
  {
    return elem.value;
  }
  return "";
}

function getCheckboxValue(id)
{
  var elem = document.getElementById(id);
  if (elem !== null)
  {
    return elem.checked;
  }
  return "";
}


function getDropDownValue(id)
{
  var elem = document.getElementById(id);
  if (elem !== null)
  {
    return elem.options[elem.selectedIndex].value;
  }
  return "";
}

function getDropDownText(id)
{
  var elem = document.getElementById(id);
  if (elem !== null)
  {
    return elem.options[elem.selectedIndex].text;
  }
  return "";
}


var ajaxBlocked = false;

String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); }

var ServerCheckComponentValid = Class.create(
{
  initialize: function(id, message, myform)
  {
    this.id = id;
    this.message = message;
    this.lastIllegalValue = null;
    this.myform = myform;
  },

  validate: function()
  {
    if (this.lastIllegalValue === document.getElementById(this.id).value.trim())
    {
      this.myform.setElementHasError(this.id, this.message);
      return false;
    }
    else
    {
      return true;
    }
  },

  setLastIllegalValue: function(value)
  {
    this.lastIllegalValue = value;
  }
});

var ServerCheckLogin = Class.create(
{
  initialize: function(idUsername, idPassword, myform)
  {
    this.idUsername = idUsername;
    this.idPassword = idPassword;
    this.message = 'Could not log in!';
    this.myform = myform;
    this.lastIllegalUsername = null;
    this.lastIllegalPassword = null;
  },

  validate: function()
  {
    if (this.lastIllegalUsername === document.getElementById(this.idUsername).value &&
        this.lastIllegalPassword === document.getElementById(this.idPassword).value)
    {
      this.myform.setElementHasError(this.idUsername, this.message);
      this.myform.setElementHasError(this.idPassword, this.message);
      return false;
    }
    else
    {
      return true;
    }
  },

  setLastIllegalValue: function(usernameValue, passwordValue, message)
  {
    this.lastIllegalUsername = usernameValue;
    this.lastIllegalPassword = passwordValue;
    this.message = message;
  }
});

var CheckValuesIdentical = Class.create(
{
  initialize: function(id1, id2, message, myform)
  {
    this.id1 = id1;
    this.id2 = id2;
    this.message = message;
    this.myform = myform;
  },

  validate: function()
  {
    var val1 = getFormElementValue(this.id1);
    var val2 = getFormElementValue(this.id2);
    if (val1 != val2)
    {
      this.myform.setElementHasError(this.id1, this.message);
      this.myform.setElementHasError(this.id2, this.message);
      return false;
    }
    else
    {
      return true;
    }
  },

  containsElement: function(id)
  {
    return this.id1 == id || this.id2 == id;
  }
});

var CheckValueNotNull = Class.create(
{
  initialize: function(id, message, form)
  {
    this.id = id;
    this.message = message;
    this.form = form;
  },

  validate: function()
  {
    var val = getFormElementValue(this.id);
    if (val !== null && val.trim().length > 0)
    {
      return true;
    }
    else
    {
      this.form.setElementHasError(this.id, this.message);
      return false;
    }
  },

  containsElement: function(id)
  {
    return this.id == id;

  }
});

var CheckCheckBoxEqualTo = Class.create(
{
  initialize: function(id, message, form, value)
  {
    this.id = id;
    this.message = message;
    this.form = form;
    this.value = value;
  },

  validate: function()
  {
    var val = getCheckboxValue(this.id);
    if (val !== null && val == this.value)
    {
      return true;
    }
    else
    {
      this.form.setElementHasError(this.id, this.message);
      return false;
    }
  },

  containsElement: function(id)
  {
    return this.id == id;

  }
});

var CheckValueLengthValid = Class.create(
{
  initialize: function(id, message, form, min, max)
  {
    this.id = id;
    this.message = message;
    this.form = form;
    this.min = min;
    this.max = max;
  },

  validate: function()
  {
    var val = getFormElementValue(this.id);

    if (val !== null && val.length >= this.min && val.length <= this.max)
    {
      return true;
    }
    else
    {
      this.form.setElementHasError(this.id, this.message);
      return false;
    }
  },

  containsElement: function(id)
  {
    return this.id == id;
  }
});

var CheckDropDownValue = Class.create(
{
  initialize: function(id, message, defaultVal, form)
  {
    this.id = id;
    this.message = message;
    this.form = form;
    this.defaultVal = defaultVal;
  },

  validate: function()
  {
    var txt = getDropDownText(this.id);
    if (txt !== null && txt.length > 0 && txt != this.defaultVal)
    {
      return true;
    }
    else
    {
      this.form.setElementHasError(this.id, this.message);
      return false;
    }
  },

  containsElement: function(id)
  {
    return this.id == id;
  }
});

function setupFormSubmit(callbackURL, formId)
{
  if (!ajaxBlocked)
  {
    var currentForm = getJumbuckFormPanel(formId);
    if (currentForm != undefined && currentForm != null)
    {
      var result = currentForm.validate(true, true, false);
      if (result == 0)
      {
        return callbackURL
      }
    }
  }
  return null;
}

var isPolling = false;

function setupPollingURLParams(callbackURL)
{
  callbackURL += getRotatingListPollingURLParams();
  isPolling = true;
  return callbackURL;
}

function setLinkFocus(id)
{
  setLocalCursor(document.getElementById(id), 'pointer');
}

function setLinkBlur(id)
{
  setLocalCursor(document.getElementById(id), 'default');
}

var panels = {};
var panelCount = 0;

var root = null;

var tooltips = {};
var tooltipCount = 0;

var mouseListeners = {};

function addTooltip(id, tip, elementId)
{
  tooltips[id] = new Tooltip(tip, elementId, null, null);
}

function addDynamicImageTooltip(id, elementId, imgId, imgPath)
{
  tooltips[id] = new Tooltip('', elementId, imgId, imgPath);
  addMouseMoveListener(id);
}


function removeTooltip(id)
{
  if (tooltips[id] !== undefined && tooltips[id] !== null)
  {
    if (tooltips[id].useMouseMove)
    {
      removeMouseMoveListener(id);
    }
    delete tooltips[id];
  }
}

function getTooltip(id)
{
  return tooltips[id];
}

function getTooltipContent(id)
{
  if (tooltips[id] !== undefined && tooltips[id] != null)
  {
    if (tooltips[id].elementId == null)
    {
      return tooltips[id].modifiedText;
    }
    else
    {
      return tooltips[id].elementId;
    }
  }
  return null;
}

var Tooltip = Class.create(
{
  initialize: function(text, elementId, imgId, imgPath)
  {
    this.elementId = elementId;
    this.text = text;
    this.modifiedText = this.text;
    this.state = 'inactive';
    this.imgId = imgId;
    this.imgPath = imgPath;

    if (this.imgPath != null)
    {
      this.useMouseMove = true;
    }
    else
    {
      this.useMouseMove = false;
    }
  },

  add: function(newText)
  {
    this.modifiedText += newText;
  },

  reset: function()
  {
    this.modifiedText = this.text;
  }
});

function addMouseMoveListener(elementId)
{
  mouseListeners[elementId] = false;
  //$(elementId).observe("mouseover", onElementMouseOver);
  //$(elementId).observe("mouseout", onElementMouseOut);
  //$(elementId).observe("mousemove", onElementMouseMove);
}

function removeMouseMoveListener(elementId)
{
  delete mouseListeners[elementId];
  //$(elementId).stopObserving("mouseover", onElementMouseOver);
  //$(elementId).stopObserving("mouseout", onElementMouseOut);
}

function adjustImage(imgId, divId)
{
  var myImg = document.getElementById(imgId);
  var myDiv = document.getElementById(divId);

  var imgWidth = myImg.clientWidth;
  var imgHeight = myImg.clientHeight;

  var stretchWidth = myDiv.clientWidth;
  var stretchHeight = myDiv.clientHeight;
  //alert(stretchWidth);

  myDiv.style.textAlign = "left";

  var widthPercent = imgWidth / stretchWidth;
  var heightPercent = imgHeight / stretchHeight;

  if (widthPercent > heightPercent)
  {
    myImg.style.width = stretchWidth + "px";
    var newHeight = imgHeight * (stretchWidth / imgWidth);
    myImg.style.height = newHeight + "px";

    //alert(stretchHeight + ", " + newHeight);
    myImg.style.top = (((stretchHeight - newHeight) / 2) + 1) + "px";
  }
  else
  {
    myImg.style.height = stretchHeight + "px";
    var newWidth = imgWidth * (stretchHeight / imgHeight);
    myImg.style.width = newWidth + "px";

    myImg.style.left = (((stretchWidth - newWidth) / 2) + 1) + "px";
  }

  myDiv.style.visibility = "visible";
}

var ajaxPreHandler = null;
var ajaxPostHandler = null;

function registerJumbuckAjaxPreHandler(preHandler)
{
  ajaxPreHandler = preHandler;
}

function registerJumbuckAjaxPostHandler(postHandler)
{
  ajaxPostHandler = postHandler;
}

function doJumbuckAjaxPreHandler()
{
  if (ajaxPreHandler !== null)
  {
    ajaxPreHandler();
  }
}

function doJumbuckAjaxPostHandler()
{
  if (ajaxPostHandler !== null)
  {
    ajaxPostHandler();
  }
}

var globalCursor = null;
var localCursor;
var localCursorElement;

function setGlobalCursor(myCursorValue)
{
  globalCursor = myCursorValue;

  if (globalCursor !== null)
  {
    document.body.style.cursor = globalCursor;
    if (localCursorElement != null)
    {
      localCursorElement.style.cursor = globalCursor
    }
  }
  else
  {
    document.body.style.cursor = 'default';
    if (localCursorElement != null)
    {
      localCursorElement.style.cursor = localCursor;
    }
  }
}

function setLocalCursor(elem, myCursorValue)
{
  localCursor = myCursorValue;
  localCursorElement = elem;

  if (globalCursor === null)
  {
    if (localCursorElement !== null)
      localCursorElement.style.cursor = localCursor;
  }
}

function jumbuckEventKey(e)
{
  if (typeof(e.keyCode)== 'undefined')
  {
    return e.which;
  }
  else
  {
    return e.keyCode;
  }
}

var googleMapsLoaded = false;

function loadGoogleMaps(initScript)
{
  if (!googleMapsLoaded)
  {
    google.load("maps", "2.x", { callback : initScript } );
    googleMapsLoaded = true;

    return true;
  }
  return false;
}

function setCaretToEnd(markupId)
{
  var ctrl = document.getElementById(markupId);
  setCaretPosition(ctrl, ctrl.value.length);
}

function setCaretPosition(ctrl, pos)
{
  if(ctrl.setSelectionRange)
	{
		ctrl.focus();
		ctrl.setSelectionRange(pos,pos);
	}
	else if (ctrl.createTextRange)
  {
		var range = ctrl.createTextRange();
		range.collapse(true);
		range.moveEnd('character', pos);
		range.moveStart('character', pos);
		range.select();
	}
}

//special tooltips stuff...

var specialTipStartTime = 0;
var specialTipElementId = null;

document.observe('mousemove', OnMouseMove);
document.observe('click', OnMouseClick);
document.observe('mousedown', OnMouseDown);
document.observe('mouseover', onElementMouseOver);

var dragDiffX = null;
var dragDiffY = null;
var dragStarted = false;
var mouseX = -1;
var mouseY = -1;

function OnMouseMove(event)
{
  mouseX = event.pointerX();
  mouseY = event.pointerY();
  /*
  var overActive=false;

  if (dragDiffX !== null && dragDiffY !== null)
  {
    event.preventDefault();
    dragStarted = true;
    var tooltipDiv = $('tooltip');
    tooltipDiv.setOpacity(0.75);

    var bodyContainer = $('main');
    var bodyWidth = bodyContainer.cumulativeOffset().left * 2 + bodyContainer.getWidth();

    var newPosX = Math.max(2, Math.min(posX-dragDiffX, bodyWidth - tooltipDiv.getWidth()-5));
    var newPosY = Math.max(2, Math.min(posY-dragDiffY, bodyContainer.getHeight()-tooltipDiv.getHeight()-5));

    tooltipDiv.style.left = newPosX + "px";
    tooltipDiv.style.top = newPosY + "px";
    return;
  }

  for (var id in mouseListeners)
  {
    var tooltip = getTooltip(id);
    if (tooltip !== undefined && tooltip !== null)
    {
      if (tooltip.state == 'active')
      {
        var tooltipPanel = $('tooltip');
        if (tooltipPanel !== null && tooltipPanel !== undefined)
        {
          if (!Position.within(tooltipPanel, posX, posY))
          {
            OnMouseExit(event, id);
          }
          else
          {
            overActive = true;
          }
        }
      }
    }
  }

  if (!overActive)
  {
    for (var id in mouseListeners)
    {
      var tooltip = getTooltip(id);
      if (tooltip !== undefined && tooltip !== null)
      {
        if (tooltip.state == 'inactive')
        {
          var tooltipSourcePanel = $(id);
          if (tooltipSourcePanel !== null && tooltipSourcePanel !== undefined)
          {
            if (Position.within(tooltipSourcePanel, posX, posY))
            {
              OnMouseEnter(event, id);
            }
          }
        }
        else if (tooltip.state == 'pending')
        {
          var tooltipSourcePanel = $(id);
          if (tooltipSourcePanel !== null && tooltipSourcePanel !== undefined)
          {
            if (!Position.within(tooltipSourcePanel, posX, posY))
            {
              OnMouseExit(event, id);
            }
          }
        }
      }
    }
  } */
}

function OnMouseEnter(id)
{
  getTooltip(id).state = "pending";
  setTimeout("setupJTooltip('" + id + "')", 350);
}

function setupJTooltip(id)
{
  var tooltip = getTooltip(id);
  if (tooltip !== undefined && tooltip !== null && tooltip.state == 'pending')
  {
    var tooltipDiv = $('tooltip');
    var tooltipContainer = $('tooltipPanel');

    tooltipDiv.setStyle({cursor:"move"});

    var tooltip = getTooltip(id);
    tooltip.state = 'active';

    var elementId = tooltip.elementId;
    if (elementId !== undefined && elementId !== null)
    {
      //tooltipContainer.setStyle({zIndex: '100', width: document.body.getWidth()+'px', height: document.body.getHeight()+'px'});

      var copyElem = $(elementId);
      tooltipDiv.hide();
      tooltipDiv.innerHTML = copyElem.innerHTML;

      var dimensions = tooltipDiv.getDimensions();
      var width = dimensions.width;
      var height = dimensions.height;

      //tooltipDiv.setStyle({borderStyle:"solid", borderWidth:"1px", borderColor:"#000000"});
      tooltipDiv.style.left = (mouseX - width/2) + "px";
      tooltipDiv.style.top = (mouseY - height/2) + "px";
      tooltipDiv.show();

      $(tooltip.imgId).src = tooltip.imgPath;
    }
  }
}

function OnMouseExit(id)
{
  var tooltip = getTooltip(id);
  if (tooltip.state == 'active')
  {
    var tooltipDiv = $('tooltip');
    tooltipDiv.innerHTML = '';
    tooltipDiv.hide();
  }
  tooltip.state = 'inactive';
}

function OnMouseClick(event, id)
{
  var tooltipPanel = $('tooltip');

  dragDiffX = null;
  dragDiffY = null;

  if (dragStarted)
  {
    tooltipPanel.setOpacity(1.0);
    dragStarted = false;
    return;
  }

  var posX = event.pointerX();
  var posY = event.pointerY();

  for (var id in mouseListeners)
  {
    var tooltip = getTooltip(id);
    if (tooltip !== undefined && tooltip !== null)
    {
      if (tooltip.state == 'active')
      {
        if (tooltipPanel !== null && tooltipPanel !== undefined)
        {
          if (Position.within(tooltipPanel, posX, posY))
          {
            OnMouseExit(id);
          }
        }
      }
    }
  }
}

function OnMouseDown(event, id)
{
  var posX = event.pointerX();
  var posY = event.pointerY();

  var tooltipDiv = $('tooltip');
  if (tooltipDiv !== null && tooltipDiv !== undefined && dragDiffX === null && dragDiffY === null)
  {
    if (Position.within(tooltipDiv, posX, posY))
    {
      dragDiffX = posX - tooltipDiv.cumulativeOffset().left;
      dragDiffY = posY - tooltipDiv.cumulativeOffset().top;
      event.preventDefault();
    }
  }
}

function onElementMouseOver(event)
{
  var elem = event.element();

  for (var floatingId in mouseListeners)
  {
    var tooltip = getTooltip(floatingId);
    if (tooltip.state == 'inactive')
    {
      //check for entry..
      if (elem.id == floatingId || elem.up("#"+floatingId) !== undefined)
      {
        OnMouseEnter(floatingId);
      }
    }
    else if (tooltip.state == 'pending')
    {
      //check we're still over the pad..
      if (elem.id != floatingId && elem.up("#"+floatingId) === undefined)
      {
        OnMouseExit(floatingId);
      }
    }
    else if (tooltip.state == 'active')
    {
      //check for exit...
      if (elem.id != 'tooltip' && elem.up("#tooltip") === undefined)
      {
        OnMouseExit(floatingId);
      }
    }
  }

}
