// this piece of code, only used in IE, will override the setInterval function so that it can be called with trailing extra parameters that will
// get passed to the callback function, just as Firefox behaves natively.
// i still have no idea how it works, but it does.  copied from the following page: 
// http://webreflection.blogspot.com/2007/06/simple-settimeout-setinterval-extra.html
if (isIE()){
  (function(f){
    window.setInterval = f(window.setInterval);
  })
    (function(f){
      return function(callback,timeInterval){
	var a = Array.prototype.slice.call(arguments,2);
	if (typeof callback != "function")
	  callback = new Function(callback);
	return f( function(){callback.apply(this, a)}, timeInterval);
      };
    });
} // end: if

// returns the size of the window, with some adjustments to compensate for what ??? (browser toolbars maybe?)
function getWindowSize()
{
  var w;
  var h;
  if (isIE()) {
    w = document.documentElement.clientWidth - 40;
    h = document.documentElement.clientHeight - 120;
  } else {
    w = window.innerWidth - 40;
    h = window.innerHeight - 120;
  } // end: if
    
  return {w: w, h: h};
} // end: getWindowSize;

// getStyle, setStyle, toCamelCase found here: http://www.ozzu.com/ftopic39999.html
function getStyle(el, style) 
{
  if(!document.getElementById) return;
  var value = el.style[toCamelCase(style)];
  if(!value)
    if(document.defaultView)
      value = document.defaultView.
	getComputedStyle(el, "").getPropertyValue(style);
    else if(el.currentStyle)
      value = el.currentStyle[toCamelCase(style)];
  
  return value;
}

function setStyle(objId, style, value) 
{
  document.getElementById(objId).style[style] = value;
}

function toCamelCase( sInput ) 
{
  var oStringList = sInput.split('-');

  if(oStringList.length == 1)   
    return oStringList[0];
  
  var ret = sInput.indexOf("-") == 0 ?
    oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) : oStringList[0];
  
  for(var i = 1, len = oStringList.length; i < len; i++){
    var s = oStringList[i];
    ret += s.charAt(0).toUpperCase() + s.substring(1);
  }
  
  return ret;
}


// returns the IE major version number if the browser is Internet Explorer, 0 otherwise.
function isIE()
{
  var ua = navigator.userAgent;
  var MSIEOffset = ua.indexOf("MSIE ");
    
  if (MSIEOffset == -1) {
    return 0;
  } else {
    return parseFloat(ua.substring(MSIEOffset + 5, ua.indexOf(";", MSIEOffset)));
  }

  //return ((navigator.appVersion.indexOf("MSIE")!= -1) && (!window.opera));
} // end: isIE

// return the browser name
function getBrowser()
{
  var ie = isIE();
  return (ie) ? 'MSIE' : '';
} // end: getBrowser

// get the key code from an onkeypress event.
function getKey(e)
{
  if (!e) { e = window.event; }
  return e.keyCode;
} // end: getKey 

// returns true if the pressed key is the Enter key, false otherwise
function isEnter(e)
{
  return getKey(e) == 13;
} // end: isEnter


function showElementById(divId, iState, x,y)
{
  var obj = document.getElementById(divId); //gecko(NN6) + IE 5+
  if (x && y){
    obj.style.left = x + "px";
    obj.style.top = y + "px";
  } // end: if
  obj.style.visibility = iState ? "visible" : "hidden";
} // end: showElementById

// retrieve event data (x,y, etc.) into a common object for all platforms
function getEventData(e)
{
  var x;
  var y;
  
  if (!e) e = window.event;
  if (e.pageX || e.pageY){
    x = e.pageX;
    y = e.pageY;
    //alert("pageX="+e.pageX+", pageY="+e.pageY);
  } else if (e.clientX || e.clientY){
    x = e.clientX + document.body.scrollLeft;
    y = e.clientY + document.body.scrollTop;
    //alert("clientX="+e.clientX+", scrollLeft="+document.body.scrollLeft);
  } // end: if
  
  return {x: x, y: y};
} // end: getEventData

// getGeom: get geometry properties (x,y,width,height) of object as json object
function getGeom(o)
{
  if (o){
    return {x : parseInt(getStyle(o,'left')),
	      y : parseInt(getStyle(o,'top')),
	      w : parseInt(getStyle(o,'width')),
	      h : parseInt(getStyle(o,'height'))};

    //    return {x : parseInt(o.style.left),
    //	      y : parseInt(o.style.top),
    //	      w : parseInt(o.style.width),
    //	      h : parseInt(o.style.height)};
  } else {
    return null;
  } // end: if
} // end: getGeom
	    
//	Written by Jonathan Snook, http://www.snook.ca/jonathan
//	Add-ons by Robert Nyman, http://www.robertnyman.com
function getElementsByClassName(oElm, strTagName, oClassNames)
{
  var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
  var arrReturnElements = new Array();
  var arrRegExpClassNames = new Array();
  if(typeof oClassNames == "object"){
    for(var i=0; i<oClassNames.length; i++){
      arrRegExpClassNames.push(new RegExp("(^|\\s)" + oClassNames[i].replace(/\-/g, "\\-") + "(\\s|$)"));
    }
  }
  else{
    arrRegExpClassNames.push(new RegExp("(^|\\s)" + oClassNames.replace(/\-/g, "\\-") + "(\\s|$)"));
  }
  var oElement;
  var bMatchesAll;
  for(var j=0; j<arrElements.length; j++){
    oElement = arrElements[j];
    bMatchesAll = true;
    for(var k=0; k<arrRegExpClassNames.length; k++){
      if(!arrRegExpClassNames[k].test(oElement.className)){
	bMatchesAll = false;
	break;
      }
    }
    if(bMatchesAll){
      arrReturnElements.push(oElement);
    }
  }
  return (arrReturnElements);
} // end: getElementsByClassName

function setClassStyle(className, styleName, styleValue, owner, tagName)
{
  var elements = getElementsByClassName(owner,tagName,className);
  for (var i in elements){
    elements[i].style[styleName] = styleValue;
  } // end: for
} // end: setClassStyle



function checkRadio(radio, checkValue)
{
  if (radio){
    if (radio.length){
      for (i = 0; i < radio.length; i++){
	if (radio[i].value == checkValue){
	  radio[i].checked = true;
	} // end: if
      } // end: for
    } // end: if
  } // end: if
} // end: checkRadio

function parseQueryString( name )
{
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var results = regex.exec( window.location.href );
  if( results == null )
    return "";
  else
    return results[1];
} // end: parseQueryString


function min (a,b)
{
  return (a < b) ? a : b;
} // end: min

function max (a,b)
{
  return (a > b) ? a : b;
} // end: max



// get the checked value for the given radio buttons object.
function getRadioValue(radioObject)
{
  for (var i=0; i < radioObject.length; i++){
    if (radioObject[i].checked){
      return radioObject[i].value;
    } // end: if
  } // end: for
} // end: getRadioValue


// moveMode: optional, can be 'x' or 'y' to specify movement only in the x or y directions.  if other, or not defined, then movement is in both directions
function mouseDown(event, object, moveMode)
{
  var e = getEventData(event);

  object.dragStartX = e.x;
  object.dragStartY = e.y;
  object.offsetX = parseInt(getStyle(object,'left')) || (object.offsetLeft - (parseInt(getStyle(object,'margin-left')) || 0));
  object.offsetY = parseInt(getStyle(object,'top')) || (object.offsetTop - (parseInt(getStyle(object,'margin-top')) || 0));
  //object.offsetX = parseInt(getStyle(object,'left'));
  //object.offsetY = parseInt(getStyle(object,'top'));
  /*
  object.offsetX = object.offsetLeft;
  object.offsetY = object.offsetTop;
  alert (parseInt(getStyle(object,'top')) + "," + object.offsetTop);
  */
  //alert (object.offsetX + "," + object.offsetY);
  //return;

  document.onmouseupTmp = document.onmouseup;
  document.onmouseup = mouseUp;
  document.onmousemoveTmp = document.onmousemove;
  document.onmousemove = mouseMove;

  document.onselectstart = function () { return false; };
  object.ondragstart = function () { return false; };
  document.dragObject = object;
  document.body.focus();

  document.moveMode = moveMode;

  if (object.mouseDownFunction){
      object.mouseDownFunction(e);
  } // end: if
  
  return false;
} // end: mouseDown

function mouseUp(event)
{
  var e = getEventData(event);
  if (document.dragObject){
    var object = document.dragObject;
    if (object.mouseUpFunction){
      object.mouseUpFunction(e);
    } // end: if
  } // end: if

  /*  
      // the problem with trying to set these to their original states (preserved int the *Tmp variables) is that if something goes wrong 
      // and the mouseUp function does not get triggered to release the event, the next click on the same object to try and release the event,
      // doesn't work because it stores the same mousemove function in the Tmp variables.   
  document.onmousemove = document.onmousemoveTmp;
  document.onmouseup = document.onmouseupTmp;
  */
  document.onmousemove = null;
  document.onmouseup = null;
  document.onselectstart = null;
  document.moveMode = null;
  
} // end: objectUp

function mouseMove(event)
{
  if (document.dragObject){
    var e = getEventData(event);
    var object = document.dragObject;

    // check the boundaries, if the object has a checLimits function, to see if we can move the object.
    if (!object.checkLimitsFunction || object.checkLimitsFunction(event)){
      
      if (!document.moveMode || (document.moveMode != 'y')){
	object.style.left = (object.offsetX + e.x - object.dragStartX) + 'px';
      } // end: if
      if (!document.moveMode || (document.moveMode != 'x')){
	object.style.top = (object.offsetY + e.y - object.dragStartY) + "px";
      } // end: if


      // if the object moveFunction is defined then call that function
      if (object.mouseMoveFunction){
	object.mouseMoveFunction(event);
      } // end: if
    } // end: if

      
      
  } // end: if
} // end: mouseMove


    
// Event handler for mouse wheel event.
function wheel(event, handleFunc)
{
  //document.form1.query.value = "x="+event.pageX+",y="+event.pageY;
  //alert('here');
  var delta = 0;
  if (!event) /* For IE. */
    event = window.event;
  if (event.wheelDelta) { /* IE/Opera. */
    delta = event.wheelDelta/120;
    /** In Opera 9, delta differs in sign as compared to IE.
     */
    if (window.opera)
      delta = -delta;
  } else if (event.detail) { /** Mozilla case. */
    /** In Mozilla, sign of delta is different than in IE.
     * Also, delta is multiple of 3.
     */
    delta = -event.detail/3;
  }
  /** If delta is nonzero, handle it.
   * Basically, delta is now positive if wheel was scrolled up,
   * and negative, if wheel was scrolled down.
   */
  if (delta)
    handleFunc(delta, event);
  /** Prevent default actions caused by mouse wheel.
   * That might be ugly, but we handle scrolls somehow
   * anyway, so don't bother here..
   */
  if (event.preventDefault)
    event.preventDefault();
  event.returnValue = false;
} // end: wheel

function d2h(d) 
{
  var hD="0123456789ABCDEF";
  var h = hD.substr(d&15,1);
  while(d>15) {
    d >>= 4;
    h = hD.substr(d&15,1)+h;
  } // end: while
  return h;
} // end: d2h

function toColor(r,g,b)
{
  var c = r*256*256 + g*256 + b;
  var hexPadded = "000000"+d2h(c);
  //alert(hexPadded);
  return("#"+hexPadded.substr(hexPadded.length-6,6));
} // end: toColor

function getColorGradient(start,end,current,max)
{
  if (max != 0){
    return start - parseInt( current*(start-end)/max);
  } else {
    return 0;
  } // end: if
} // end: getColorGradient

function objectPan (destX, destY, object,  postFunc)
{
  //var curX = parseInt(object.style.left);
  //var curY = parseInt(object.style.top);
  var curX = parseInt(getStyle(object,'left'));
  var curY = parseInt(getStyle(object,'top'));
  var dX = destX - curX;
  var dY = destY - curY;
  
  var timer = new Date();
  object.panStartTime = (object.panStartTime) ? object.panStartTime : timer.getTime();
  var timeout = (object.panTimeout < (timer.getTime() - object.panStartTime));
  //debug("objectPan: dX="+dX+",dY="+dY+",startTime="+object.panStartTime +",timer = "+timer.getTime() + ",timeout="+timeout );

  if (dX || dY){
    var stepX = parseInt(Math.abs(dX)/10) + scrollSpeed;
    var stepY = parseInt(Math.abs(dY)/10) + scrollSpeed;
    var signX = (destX >= curX) ? 1 : -1;
    var signY = (destY >= curY) ? 1 : -1;
    var newX = (object.animate && !timeout && stepX < Math.abs(dX)) ? curX + signX*stepX : newX = destX;
    var newY = (object.animate && !timeout && stepY < Math.abs(dY)) ? curY + signY*stepY : newY = destY;
    //debug("objectPan: newX="+newX+",newY="+newY);
    
    object.style.left = newX + "px";
    object.style.top = newY + "px";
  } else {
    object.panStartTime = 0;
    clearInterval(object.intervalId);
    if (postFunc && (typeof(postFunc) == 'function')){
      postFunc(object);
    } // end: if
  } // end: if

} // end: objectPan

// create and return a DOM element having type, id, and class
function createElement(parent, type, id, className)
{
  var el = document.createElement(type);
  if (id)
    el.id = id;
  if (className)
    el.className = className;
  if (parent)
    parent.appendChild(el);

  return el;
} // end: createElement


function createDropShadow(el, width)
{
  if (el){
    for (var i = 0; i < width; i++){
      var borderRight = createElement(el, 'div', '', '');
      borderRight.style.position = 'absolute';
      borderRight.style.right = -(i+1) + "px";
      borderRight.style.bottom = -(i+1) + "px";
      borderRight.style.width = (i+1) + "px";
      borderRight.style.height = "100%";
      borderRight.style.background = "#000";
      borderRight.style.opacity =  '0.12';
      borderRight.style.filter = 'alpha (opacity = 12)';
      borderRight.style.zIndex = 0;

      var borderBottom = createElement(el, 'div', '', '');
      borderBottom.style.position = 'absolute';
      borderBottom.style.right = "0px";
      borderBottom.style.bottom = -(i+1) + "px";
      borderBottom.style.height = (i+1) + "px";
      borderBottom.style.background = "#000";
      borderBottom.style.opacity =  '0.12';
      borderBottom.style.filter = 'alpha (opacity = 12)';  
      borderBottom.style.zIndex = 0;
      if (isIE() == '6'){
	borderBottom.style.font = "1px verdana"; // seems we need this to avoid IE6 fattening the height of the div to accomodate a larger default font size. 
	borderBottom.style.width = "100%";
      } else {
	borderBottom.style.left = (i+1) + "px";
      } // end: if


    } // end: for 
  } // end: if
} // end: createDropShadow


function createDropShadow2(el, width, r,g,b)
{
  if (el){
    for (var i = 1; i <= width; i++){
      var border = createElement(el, 'div', '', '');
      border.style.position = 'absolute';
      border.style.left = -i + "px";
      border.style.right = -i + "px";
      border.style.top = -i + "px";
      border.style.bottom = -i + "px";
      var opacity = (width - (i-1)) * 16;
      border.style.border = '1px solid ' + toColor(r - opacity, g - opacity, b - opacity);
      /*
      border.style.borderLeft = '1px solid ' + toColor(r - opacity, g - opacity, b - opacity);
      border.style.borderRight = '1px solid ' + toColor(r - opacity, g - opacity, b - opacity);
      border.style.borderBottom = '1px solid ' + toColor(r - opacity, g - opacity, b - opacity);
      */
      border.style.zIndex = -1;

    } // end: for 
  } // end: if
} // end: createDropShadow2

