/**
 * DHTML Dialogs
 * 
 * formerly
 *
 * jt_DialogBox.js - DHTML modal dialog box
 *
 * @version 9 Apr 2005
 * @author  Joseph Oster, wingo.com, Copyright (c) 2005-2006
 *
 * With modifications by geobirds.com
 *
 */
 
 /*********** Helper methods provided by Joseph at wingo.com ************/
  
 var isIE = (navigator.appName.indexOf("Microsoft") != -1);
 var isMoz = (navigator.appName.indexOf("Netscape") != -1);

 var alertDialog = null;
 var confirmDialog = null;
 var alertX = -1; // centers dialog in window!
 var alertY = -1;
 
 function MyAppAlertSetXY(x, y) {
   // call prior to 'MyAppAlert()'
   alertX = x;
   alertY = y;
   }
 
 function MyAppAlertXY(ev) {
   // call using 'onclick' prior to 'MyAppAlert()'
   var e = jt_fixE(ev);
   MyAppAlertSetXY(e.clientX, e.clientY + document.body.scrollTop);
   return true;
   }
 
 function MyAppAlertInit(title, icon, oktext) {
   var locTitle = '';
   if (title) locTitle += title;
   if (alertDialog == null) {
     alertDialog = new jt_AppAlert(icon ? icon : jt_AppAlert.Error, oktext);
     alertDialog.setTitle(locTitle);
     }
   else {
     if (title) alertDialog.setTitle(locTitle);
     if (icon) alertDialog.setIcon(icon);
     }
   
   alertDialog.base.veilOverlay.className = ""; // disable
   alertDialog.base.veilOverlay.className = "VeilStyle1c"; // CSS className

   }
   
  function MyAppConfirmInit(title,icon,okCallback,cancelCallback,okText,cancelText) {
  	var locTitle = '';
	if (title) locTitle += title;

	confirmDialog = new jt_AppConfirm(icon ? icon : jt_AppAlert.Error, 
			okCallback,cancelCallback,
			okText, cancelText);		
	confirmDialog.setTitle(locTitle);

	confirmDialog.base.veilOverlay.className = ""; // disable
	confirmDialog.base.veilOverlay.className = "VeilStyle1c"; // CSS className  
  }
 
 function MyAppAlert(msg, title, icon) {
   // 'title' and 'icon' are optional
   MyAppAlertInit(title, icon);
   alertDialog.setContent(msg);
   alertDialog.moveTo(alertX, alertY);
   alertDialog.show();
   if ((alertX == -1) || (alertY == -1)) alertDialog.moveTo(alertX, alertY);
   }

function GeoBirdsBasic2ChoiceDialog(msg,title) {
	return GeoBirdsBasicVeilDialog(msg,title,'jtDialogBoxVeil');
}

function GeoBirdsBasicVeilDialog(msg,title,veilClass) {
	var dialog = new jt_DialogBox(true);
	dialog.setTitle(title);

   	dialog.setContent(msg);
 
   	dialog.moveTo('0', '0');
   	dialog.show();
   	dialog.moveTo(-1,-1);
 
	jt_DialogBox.veilOverlay.className = ""; 
	jt_DialogBox.veilOverlay.className = veilClass;
 
   	return dialog;
}

function GeobirdsErrorAlert(msg,title,x,y,oktext,callback) {
	doShowGeobirdsAlert(msg,title,x,y,oktext,callback,jt_AppAlert.Error);
}

function GeobirdsWarningAlert(msg,title,x,y,oktext,callback) {
	doShowGeobirdsAlert(msg,title,x,y,oktext,callback,jt_AppAlert.Warning);
}

function GeobirdsInfoConfirm(msg,title,x,y,oktext,callback) {
	doShowGeobirdsAlert(msg,title,x,y,oktext,callback,jt_AppAlert.Confirm);
}

function Geobirds2ChoiceConfirm(msg,title,x,y, callOK, callCancel, okText, cancelText) {
	doShowGeobirds2Choice(msg,title,x,y, callOK, callCancel, okText, cancelText, jt_AppAlert.Confirm);
}

function Geobirds2ChoiceWarning(msg,title,x,y, callOK, callCancel, okText, cancelText) {
	doShowGeobirds2Choice(msg,title,x,y, callOK, callCancel, okText, cancelText, jt_AppAlert.Warning);
}

function doShowGeobirds2Choice(msg,title,x,y, callOK, callCancel, okText, cancelText,icon) {
	MyAppConfirmInit(title, icon, callOK, callCancel, okText, cancelText);  
   	confirmDialog.setContent(msg);
   	confirmDialog.moveTo('0', '0');
   	confirmDialog.show();
   	confirmDialog.moveTo(x,y);
}

function doShowGeobirdsAlert(msg,title,x,y,oktext,callback,icon) {
	MyAppAlertInit(title, icon, oktext);  
   	alertDialog.setContent(msg);
   	if (callback) alertDialog.setCallOK(callback);
   	alertDialog.moveTo('0', '0');
   	alertDialog.show();
   	alertDialog.moveTo(x,y);
}




/************* jt_DialogBox class definition *******************************/
 

jt_DialogBox = function(isModal) {
  // CONSTRUCTOR for 'jt_DialogBox' object
  if (arguments.length==0) return;
  this.isModal = isModal;

  if (jt_DialogBox.veilOverlay == null) { // once per page
    jt_DialogBox.veilOverlay = document.createElement('div');
    jt_DialogBox.veilOverlay.className = "jtDialogBoxVeil"; // CSS className
    jt_DialogBox.veilOverlay.style.zIndex = jt_DialogBox.veilZ;
    jt_DialogBox.veilOverlay.innerHTML = "&nbsp;";
    jt_DialogBox.setVeilWidth();
    jt_DialogBox.addListener(window, "resize", jt_DialogBox.setVeilWidth);
    document.body.appendChild(jt_DialogBox.veilOverlay);

    jt_DialogBox.closeIcon = new Image();
    jt_DialogBox.closeIcon.src = jt_DialogBox.imagePath + "window_close.gif";
    }

  this.container = document.createElement('div');
  this.container.className = jt_DialogBox.className;
  this.container.id = new Date().getTime();
  this.container.dialogBox = this;

  var mainTable = document.createElement('table');
  mainTable.setAttribute('cellSpacing', '0');
  mainTable.setAttribute('cellPadding', '0');
  mainTable.setAttribute('border', '0');

  var tBodyM = document.createElement('tbody');
  var rowM = document.createElement('tr');
  var cellM = document.createElement('td');

  //*********** BEGIN Title TABLE ***********
  var titleTable = document.createElement('table');
  titleTable.setAttribute('cellSpacing', '0');
  titleTable.setAttribute('cellPadding', '0');
  titleTable.setAttribute('border', '0');
  titleTable.setAttribute('width', '100%');

  var tBodyT = document.createElement('tbody');
  var rowT = document.createElement('tr');
  var cellT = document.createElement('td');
  cellT.className = "tbLeft";
  rowT.appendChild(cellT);

  this.titleCell = document.createElement('td');
  this.titleCell.className = "Title";
  rowT.appendChild(this.titleCell);

  cellT = document.createElement('td');
  cellT.className = "tbRight";

  var closeIcon = document.createElement('img');
  closeIcon.src = jt_DialogBox.closeIcon.src;
  closeIcon.setAttribute('border','0');
  closeIcon.dialogBox = this;

  var aLink = document.createElement('A');
  aLink.setAttribute('href','#');
  aLink.appendChild(closeIcon);
  aLink.onclick = jt_DialogBox.closeBox;

  cellT.appendChild(aLink);
  rowT.appendChild(cellT);

  tBodyT.appendChild(rowT);
  titleTable.appendChild(tBodyT);
  //*********** END Title TABLE ***********

  cellM.appendChild(titleTable);
  rowM.appendChild(cellM);
  tBodyM.appendChild(rowM);

  rowM = document.createElement('tr');
  cellM = document.createElement('td');
  cellM.className = "MainPanel";

  this.contentArea = document.createElement('div');
  this.contentArea.className = "ContentArea";
  cellM.appendChild(this.contentArea);

  rowM.appendChild(cellM);
  tBodyM.appendChild(rowM);
  mainTable.appendChild(tBodyM);
  this.container.appendChild(mainTable);

  
  document.body.appendChild(this.container);

  Drag.init(this.titleCell, this.container, 0, null, 0);
  }


/************ BEGIN: Public Methods ************/
jt_DialogBox.imagePath = "/images/"; // set by application; directory path to 'window_close.gif' in titleBar

jt_DialogBox.prototype.show = function() {
  this.container.style.display = "block";
  this.topZ();
  jt_divOnScrn(this.container);
  if (this.isModal) jt_DialogBox.veilOverlay.style.display = "block";
  }

jt_DialogBox.prototype.hide = function(ok) {
  this.container.style.display = "none";
  if (this.isModal) jt_DialogBox.veilOverlay.style.display = "none";
  var posInList = this.listPos();
  if (posInList != -1) {
    jt_DialogBox.openList[posInList] = jt_DialogBox.openList[jt_DialogBox.openList.length-1];
    jt_DialogBox.openList.pop();
    }
  if (ok) {
    if (this.callOK)
      if (this.returnData) this.callOK(this.returnData);
      else this.callOK();
    }
  else if (this.callCancel) this.callCancel();
  }

jt_DialogBox.prototype.moveTo = function(x, y) {
	if (isIE) {
		  if (x == -1) x = Math.round(( document.documentElement.clientWidth - this.container.offsetWidth) / 2)  +  document.body.scrollLeft
		  if (y == -1) y = Math.round(( document.documentElement.clientHeight - this.container.offsetHeight) / 2) + document.body.scrollTop;	
	} else {
		  if (x == -1) x = Math.round((window.innerWidth - this.container.offsetWidth) / 2)  + window.pageXOffset;
		  if (y == -1) y = Math.round((window.innerHeight - this.container.offsetHeight) / 2) + window.pageYOffset;
	}
  	this.container.style.left = x + "px";
  	this.container.style.top = y + "px";
  }

jt_DialogBox.prototype.setTitle = function(title) {
  this.titleCell.innerHTML = title;
  }

jt_DialogBox.prototype.setContent = function(htmlContent) {
  this.contentArea.innerHTML = htmlContent;
  }

jt_DialogBox.prototype.setWidth = function(width) {
  this.contentArea.style.width = width + "px";
  }

jt_DialogBox.prototype.setCallOK = function(callOK) {
  // set by application as needed
  this.callOK = callOK;
  }

jt_DialogBox.prototype.setCallCancel = function(callCancel) {
  // set by application as needed
  this.callCancel = callCancel;
  }
/************ END: Public Methods ************/


/************ BEGIN: Private Methods ************/
jt_DialogBox.className = "jtDialogBox"; // CSS className
jt_DialogBox.closeIcon = null;
jt_DialogBox.veilOverlay = null;
jt_DialogBox.veilZ = 10000;
jt_DialogBox.openList = new Array();
jt_DialogBox.maxDepth = 5; // optimize search of parent nodes

jt_DialogBox.closeBox = function(e) {
  if (!e) e = window.event;
  var node = e.target ? e.target : e.srcElement;
  var count = 0;
  while ((node != null) && (count < jt_DialogBox.maxDepth)) {
    if (node.dialogBox) {
      node.dialogBox.hide();
      return false;
      }
    node = node.parentNode;
    count++;
    }
  return false;
  }

jt_DialogBox.prototype.listPos = function() {
  var posInList = -1;
  for (var i=0; i<jt_DialogBox.openList.length; i++)
    if (jt_DialogBox.openList[i] == this) {
      posInList = i;
      break;
      }
  return posInList;
  }

jt_DialogBox.prototype.topZ = function() {
  var posInList = this.listPos();
  if (posInList == -1) jt_DialogBox.openList[jt_DialogBox.openList.length] = this; // add to list
  else if (posInList < jt_DialogBox.openList.length-1) {
    for (var i=posInList; i<jt_DialogBox.openList.length-1; i++) jt_DialogBox.openList[i] = jt_DialogBox.openList[i+1];
    jt_DialogBox.openList[jt_DialogBox.openList.length-1] = this; // move to end
    var newZ = jt_DialogBox.veilZ;
    for (var i=jt_DialogBox.openList.length-1; i>0; i--) {
      newZ--;
      jt_DialogBox.openList[i].style.zIndex = newZ;
      }
    }
  this.container.style.zIndex = jt_DialogBox.veilZ+1;
  }

jt_DialogBox.setVeilWidth = function() {
	if (window.innerHeight) {
	  jt_DialogBox.veilOverlay.style.width = window.innerWidth + 'px';
	  jt_DialogBox.veilOverlay.style.height = window.innerHeight + 'px';	
	} else if (document.documentElement.clientHeight) {
	  jt_DialogBox.veilOverlay.style.width = document.documentElement.clientWidth + 'px';
	  jt_DialogBox.veilOverlay.style.height = document.documentElement.clientHeight + 'px'; 	
	} else {
	  jt_DialogBox.veilOverlay.style.width = document.body.scrollWidth + 'px';
	  jt_DialogBox.veilOverlay.style.height = document.body.scrollHeight + 'px';
 	}
 }


jt_DialogBox.addListener = function(obj, evType, fn) {
  if (obj.addEventListener) {
    obj.addEventListener(evType, fn, false);
    return true;
    }
  else if (obj.attachEvent) return obj.attachEvent('on' + evType, fn);
  else return false;
  }
  
/********* Dialog box alert extensions **********************************************/

/**
 * jt_AppDialogs.js - extends jt_DialogBox.js with 3 specific types of dialog boxes,
 * based on JavaScript equivalents: 'jt_AppAlert', 'jt_AppConfirm' and 'jt_AppPrompt'
 *
 * @version 9 Apr 2005
 * @author  Joseph Oster, wingo.com, Copyright (c) 2005-2006
 */

jt_AppAlert = function(icon, oktext) {
  // CONSTRUCTOR for 'jt_AppAlert' object - EXTENDS 'jt_DialogBox'
  if (arguments.length==0) return;
  this.base = jt_DialogBox;
  this.base(true);

  var dialogTable = document.createElement('table');
  dialogTable.setAttribute('cellSpacing', '0');
  dialogTable.setAttribute('cellPadding', '0');
  dialogTable.setAttribute('border', '0');

  var tBody = document.createElement('tbody');
  var row = document.createElement('tr');
  var cell = document.createElement('td');
  cell.setAttribute("vAlign", "top");

  this.iconImage = document.createElement('img');
  this.iconImage.style.margin = "0px 10px 0px 0px";
  this.setIcon(icon);
  cell.appendChild(this.iconImage);
  row.appendChild(cell);

  this.contentCell = document.createElement('td');
  this.contentCell.className = "ContentArea";
  row.appendChild(this.contentCell);
  tBody.appendChild(row);
  dialogTable.appendChild(tBody);
  this.contentArea.appendChild(dialogTable);

  this.buttonDIV = document.createElement('div');
  this.buttonDIV.setAttribute("align", "center");
  this.buttonDIV.style.margin = "10px 0px 0px 0px";
  this.contentArea.appendChild(this.buttonDIV);
	if (oktext) {
		  jt_AppAlert.addButton(this, oktext, 1);
	} else {
  		jt_AppAlert.addButton(this, jt_AppAlert.lblOK, 1);
  	}
  }

jt_AppAlert.prototype = new jt_DialogBox();


/************ BEGIN: 'jt_AppAlert' Public Methods ************/
jt_AppAlert.Warning = "warning.gif"; 		// 'icon' param to 'jt_AppAlert' constructor
jt_AppAlert.Error = "error.gif";     		// 'icon' param to 'jt_AppAlert' constructor
jt_AppAlert.Info = "info.gif";       		// 'icon' param to 'jt_AppAlert' constructor
jt_AppAlert.Confirm = "checkmark.gif";       	// 'icon' param to 'jt_AppAlert' constructor

jt_AppAlert.lblOK = "OK"; // label for "OK" button (for i18N)
jt_AppAlert.lblCancel = "Cancel"; // label for "Cancel" button (for i18N)

jt_AppAlert.prototype.setContent = function(htmlContent) {
  this.contentCell.innerHTML = htmlContent;
  }

jt_AppAlert.prototype.setIcon = function(icon) {
  this.iconImage.src = jt_DialogBox.imagePath + icon;
  }
/************ END: 'jt_AppAlert' Public Methods ************/



jt_AppConfirm = function(icon, callOK, callCancel, okText, cancelText) {
  // CONSTRUCTOR for 'jt_AppConfirm' object - EXTENDS 'jt_AppAlert'
  if (arguments.length==0) return;
  this.base = jt_AppAlert;
  this.base(icon, okText);
  this.callOK = callOK;
  this.callCancel = callCancel;
  jt_AppAlert.addButton(this, cancelText, 2);
  }

jt_AppConfirm.prototype = new jt_AppAlert();


/************ BEGIN: 'jt_AppConfirm' Public Methods ************/
jt_AppConfirm.prototype.askUser = function(htmlContent) {
  this.setContent(htmlContent);
  this.show();
  }
/************ END: 'jt_AppConfirm' Public Methods ************/



jt_AppPrompt = function(icon, callOK, callCancel, cssClass) {
  // CONSTRUCTOR for 'jt_AppPrompt' object - EXTENDS 'jt_AppConfirm'
  if (arguments.length==0) return;
  this.base = jt_AppConfirm;
  this.base(icon, callOK, callCancel);
  this.returnData = new Object();
  this.fInput = document.createElement('input');
  this.fInput.type = "text";
  if (cssClass) this.fInput.className = cssClass;
  this.fInput.appDialog = this;
  this.fInput.onkeypress = jt_AppPrompt.keyPress;
  }

jt_AppPrompt.prototype = new jt_AppConfirm();
jt_AppPrompt.superClass = jt_AppConfirm.prototype;


/************ BEGIN: 'jt_AppPrompt' Public Methods ************/
jt_AppPrompt.prototype.askUser = function(htmlContent, stDefault) {
  this.setContent(htmlContent);
  this.fInput.value = stDefault;
  this.contentCell.appendChild(this.fInput);
  this.show();
  this.fInput.focus();
  }

jt_AppPrompt.prototype.focus = function() {
  this.fInput.focus();
  }

jt_AppPrompt.prototype.hide = function(ok) {
  if (ok) this.returnData.value = this.fInput.value;
  jt_AppPrompt.superClass.hide.call(this, ok);
  }
/************ END: 'jt_AppPrompt' Public Methods ************/



/************ BEGIN: 'jt_AppAlert' Private Methods ************/
jt_AppAlert.addButton = function(parent, buttonText, buttonNum) {
  var button = document.createElement("button");
  button.style.fontSize = "10pt";
 // button.style.width = "80px";
  button.style.margin = "0px 5px";
  button.innerHTML = buttonText;
  button.linkNum = buttonNum;
  button.appDialog = parent;
  button.onclick = jt_AppAlert.clickLink;
  parent.buttonDIV.appendChild(button);
  }

jt_AppAlert.clickLink = function(e) {
  if (!e) e = window.event;
  var node = e.target ? e.target : e.srcElement;
  var linkNum = node.linkNum;
  var count = 0;
  while ((node != null) && (count < jt_DialogBox.maxDepth)) {
    if (node.appDialog) {
      switch (linkNum) {
        case 1: {
          node.appDialog.hide(true);
          break;
          }
        case 2: {
          node.appDialog.hide();
          break;
          }
        }
      return false;
      }
    node = node.parentNode;
    count++;
    }
  return false;
  }

jt_AppPrompt.keyPress = function(e) {
  if (!e) e = window.event;
  var node = e.target ? e.target : e.srcElement;
  var key = e.keyCode ? e.keyCode : e.which;
  if (key == 13) node.appDialog.hide(true);
  if (key == 27) node.appDialog.hide();
  }

jt_AppAlert.prototype.trace = function() {
  alert(objToString(this.contentArea));
  }

/**
 * jt_utils.js - Misc. JavaScript utility functions
 *
 * @version 16 Nov 2005
 * @author  Joseph Oster, wingo.com, Copyright (c) 2005-2006
 */

/* GENERIC FUNCTIONS */
String.prototype.trim = function () {
  return this.replace(/^\s+/g, '').replace(/\s+$/g, '');
  }

function jt_ShowHideElm(elm, showIt) {
  if (elm) elm.style.visibility = (showIt) ? "visible" : "hidden";
  }

function jt_ShowNoneElm(elm, showIt, showStyle) {
  if (!showStyle) showStyle = "";
  if (elm) elm.style.display = (showIt) ? showStyle : "none";
  }

function jt_ShowHide(divName, showIt) {
  jt_ShowHideElm(document.getElementById(divName), showIt);
  }

function jt_ShowNone(divName, showIt, showStyle) {
  jt_ShowNoneElm(document.getElementById(divName), showIt, showStyle);
  }


/********** BEGIN: Event handling **********/
function jt_AddListener(obj, evType, fn) {
  if (obj.addEventListener) {
    obj.addEventListener(evType, fn, false);
    return true;
    }
  else if (obj.attachEvent) return obj.attachEvent('on' + evType, fn);
  else return false;
  }

function jt_fixE(ev) {
  var e = ev ? ev : window.event;
  return e;
  }
/********** END: Event handling **********/


/********** BEGIN: screen handling **********/
function jt_Point(x, y) {
  // returns a "Point" object with '.x' and '.y' properties
  this.x = x;
  this.y = y;
  }

function jt_getOffsetXY(obj) {
  // returns a "jt_Point" object with both '.x' and '.y' coordinates of 'obj'; usage: "var point = jt_getOffsetXY(obj); var left=point.x; var top=point.y;"
  var xPos = obj.offsetLeft;
  var yPos = obj.offsetTop;
  var parent = obj.offsetParent;
  while (parent != null) {
    xPos += parent.offsetLeft;
    yPos += parent.offsetTop;
    parent = parent.offsetParent;
    }
  return new jt_Point(xPos, yPos);
  }

function jt_moveTo(obj, x, y) {
  // moves 'obj' to x/y coordinates
  obj.style.left = x + "px";
  obj.style.top = y + "px";
  }

function jt_getOffsetX(obj) {
  // returns 'x' coordinate of 'obj'
  var xPos = obj.offsetLeft;
  var parent = obj.offsetParent;
  while (parent != null) {
    xPos += parent.offsetLeft;
    parent = parent.offsetParent;
    }
  return xPos;
  }

function jt_getOffsetY(obj) {
  // returns 'y' coordinate of 'obj'
  var yPos = obj.offsetTop;
  var parent = obj.offsetParent;
  while (parent != null) {
    yPos += parent.offsetTop;
    parent = parent.offsetParent;
    }
  return yPos;
  }

function jt_windowOffsetX() {
  // returns X-offset of window (for positioning popups)
  if (window.screenX) return window.screenX + (window.outerWidth-window.innerWidth) - window.pageXOffset;
  else return document.body.scrollLeft + window.screenLeft;
  }

function jt_windowOffsetY() {
  // returns Y-offset of window (for positioning popups)
  if (window.screenY) return window.screenY + (window.outerHeight-24-window.innerHeight) - window.pageYOffset;
  else return document.body.scrollTop + window.screenTop;
  }

function jt_getChromeY() {
  // return height of browser "chrome" ('screenTop' offset)
  return window.screenTop ? window.screenTop : (window.outerHeight - window.innerHeight - 24);
  }

/********** END: screen handling **********/
// also see: http://www.mattkruse.com/javascript/anchorposition/source.html


/********** BEGIN: FORM handling **********/
function jt_setRadio(radioFld, val) {
  // set 'radioFld' button with value == val and return 'true' (if not disabled!)
  for (var i=0; i<radioFld.length; i++)
    if (radioFld[i].value == val)
      if (!radioFld[i].disabled) {
        radioFld[i].checked = true;
        return true;
        }
  return false;
  }

function jt_getRadio(radioFld) {
  // return value of selected 'radioFld' button
  var st = "";
  for (var i=0; i<radioFld.length; i++)
    if (radioFld[i].checked) {
      st = radioFld[i].value;
      break;
      }
  return st;
  }

function foSelected(pulldown) {
  // return value of selected item
  var st = "";
  for (var i=0; i<pulldown.options.length; i++)
  if (pulldown.options[i].selected) {
    if (pulldown.options[i].value) st = pulldown.options[i].value
    else st = pulldown.options[i].text;
    break;
    }
  return st;
  }

function foPosInList(pulldown, val) {
  // return position of 'val' in pulldown menu, -1 if not found
  if (val != "")
    for (var i=0; i<pulldown.options.length; i++) {
      var opVal = pulldown.options[i].value;
      if (opVal == "") opVal = pulldown.options[i].text;
      if (opVal == val) {
        return i;
        break;
        }
      }
  return -1;
  }

function foSetSelectVal(pulldown, val) {
  // set "SELECTED" for item in pulldown menu with 'value==val'
  var p = foPosInList(pulldown,val);
  if (p != -1) pulldown.options.selectedIndex = p;
  }
/********** END: FORM handling **********/


function jt_parseQuery(queryString) {
  // converts name/value pairs in 'queryString' to JS object
  var qObj = new Object();
  var stQuery = (queryString) ? queryString : location.search; // use 'location.search' if 'queryString' is null
  if (stQuery.indexOf("?") == 0) stQuery = stQuery.substring(1);
  if (stQuery) {
    var nvPairs = stQuery.split("&");
    for (var i=0; i < nvPairs.length; i++) {
      var posEq = nvPairs[i].indexOf("=");
      if (posEq != -1) eval( "qObj." + nvPairs[i].substring(0,posEq) + "='" + nvPairs[i].substring(posEq+1) + "'");
      }
    }
  return qObj;
  }

function jt_safeHTML(st) {
  // encode - same as 'u:htmlencode' tag
  if (st.length == 0) return "";
  st = st.replace(/</gi,"&lt;");
  st = st.replace(/>/gi,"&gt;");
  st = st.replace(/\"/gi,'&quot;');
  st = st.replace(/\'/gi,"&#39;");
  st = st.replace(/\\/gi,"&#92;");
  return st;
  }

function jt_unsafeHTML(st) {
  // decode - opposite of 'u:htmlencode' tag
  if (st.length == 0) return "";
  st = st.replace(/&lt;/gi,"<");
  st = st.replace(/&gt;/gi,">");
  st = st.replace(/&quot;/gi,'"');
  st = st.replace(/&#39;/gi,"'");
  st = st.replace(/&#92;/gi,"\\");
  return st;
  }

function jt_plural(qty, lbl) {
  // returns plural suffix or optional extended format if 'lbl' is present; example: qty=12, lbl="server", return value="12 servers"
  var stPlural = (qty == 1) ? "" : "s";
  if (lbl) stPlural = qty + " " + lbl + stPlural;
  return stPlural;
  }

function objToString(anObj, sep) {
  // convert any JS object to string of name:value pairs separated by optional 'sep'
  // NOTE: pass '<br />' for 'sep' to display as HTML
  if (!sep) sep = ' ][ '; // good for 'alert()' msgs
  var st = "";
  for(var prop in anObj) {
    if ((prop.charAt(0) == '$') || ((typeof anObj[prop]) == 'function')) continue;
    if (st != "") st += sep;
    st += prop + ':' + anObj[prop];
    }
  return st;
  }

function jt_alignCorner(elmToMove, elmAnchor, TlTrBlBr, xOffset, yOffset) {
  // aligns 'elmToMove' with 'elmAnchor' based on 2-character 'TlTrBlBr' indicating corner: 'TL' | 'TR' | 'BL' | 'BR'
  xOffset = xOffset ? xOffset : 0; // optional param
  yOffset = yOffset ? yOffset : 0; // optional param
  var anchorXY = jt_getOffsetXY(elmAnchor);
  var xxOffset = (TlTrBlBr.indexOf('R') != -1) ? elmToMove.offsetWidth - elmAnchor.offsetWidth : 0;
  var yyOffset = (TlTrBlBr.indexOf('B') != -1) ? elmToMove.offsetHeight : 0;
  jt_moveTo(elmToMove, anchorXY.x - xxOffset + xOffset, anchorXY.y - yyOffset + yOffset);
  }

function jt_boxOverlap(objectA, objectB, mode) {
  // box collision detector; returns area of overlap (if any) in pixels between DOM elements 'objectA' and 'objectB'
  // adapted from http://www.gamedev.net/reference/articles/article754.asp
  // 'mode' is optional - two special modes are offered:
  //   mode='X' - test for overlap of X-coordinates only; ignore Y
  //   mode='Y' - test for overlap of Y-coordinates only; ignore X

  var xyA = jt_getOffsetXY(objectA);
  var xyB = jt_getOffsetXY(objectB);

  var objAxTL = xyA.x; // AX1 - xTopLeft
  var objAyTL = xyA.y; // AY1 - yTopLeft
  var objAxBR = xyA.x + objectA.offsetWidth; // AX2 - xBottomRight
  var objAyBR = xyA.y + objectA.offsetHeight; // AY2 - yBottomRight

  var objBxTL = xyB.x; // BX1
  var objByTL = xyB.y; // BY1
  var objBxBR = xyB.x + objectB.offsetWidth; // BX2
  var objByBR = xyB.y + objectB.offsetHeight; // BY2

/*
alert("objAxTL=" + objAxTL + " - objAyTL=" + objAyTL + " - objAxBR=" + objAxBR + " - objAyBR=" + objAyBR + "\n" +
      "objBxTL=" + objBxTL + " - objByTL=" + objByTL + " - objBxBR=" + objBxBR + " - objByBR=" + objByBR);
*/


/*
reject the following conditions:
AX2<BX1
AY2<BY1
BX2<AX1
BY2<AY1
*/
  if (mode != 'Y') {
    if (objAxBR < objBxTL) return -1;
    if (objBxBR < objAxTL) return -1;
    }
  if (mode != 'X') {
    if (objAyBR < objByTL) return -1;
    if (objByBR < objAyTL) return -1;
    }


  var objCxTL;
  var objCyTL;
  var objCxBR;
  var objCyBR;

/*
If AX1<BX1 then CX1=BX1 and CX2=AX2, otherwise, CX1=AX1 and CX2=BX2
If AY1<BY1 then CY1=BY1 and CY2=AY2, otherwise, CY1=AY1 and CY2=BY2
*/

  if (objAxTL < objBxTL) {
    objCxTL = objBxTL;
    objCxBR = objAxBR;
    }
  else {
    objCxTL = objAxTL;
    objCxBR = objBxBR;
    }

  if (objAyTL < objByTL) {
    objCyTL = objByTL;
    objCyBR = objAyBR;
    }
  else {
    objCyTL = objAyTL;
    objCyBR = objByBR;
    }

  var olX = objCxBR - objCxTL;
  var olY = objCyBR - objCyTL;
  if (mode == 'X') return olX;
  else if (mode == 'Y') return olY;
  else return olX * olY;
  }


function jt_currStyle(divToRead) {
  // return current (derived) CSS style object
  var cs = divToRead.style;
  if (window.getComputedStyle) cs = window.getComputedStyle(divToRead,null);
  else if (divToRead.currentStyle) cs = divToRead.currentStyle;
  return cs;
  }

function jt_divOnScrn(divOnScrn) {
  var divPos = jt_getOffsetXY(divOnScrn);
  var newX = divPos.x;
  var newY = divPos.y;
  if (divPos.x + divOnScrn.offsetWidth - document.body.scrollLeft > document.body.clientWidth) newX = document.body.scrollLeft + document.body.clientWidth - divOnScrn.offsetWidth;
  if (divPos.x < document.body.scrollLeft) newX = document.body.scrollLeft;
  if (divPos.y + divOnScrn.offsetHeight - document.body.scrollTop > document.body.clientHeight) newY = document.body.scrollTop + document.body.clientHeight - divOnScrn.offsetHeight;
  if (divPos.y < document.body.scrollTop) newY = document.body.scrollTop;
  if ((newX != divPos.x) || (newY != divPos.y)) jt_moveTo(divOnScrn, newX, newY);
  }

/**************************************************
 * dom-drag.js
 * 09.25.2001
 * www.youngpup.net
 **************************************************
 * 10.28.2001 - fixed minor bug where events
 * sometimes fired off the handle, not the root.
 **************************************************/

var Drag = {

	obj : null,

	init : function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper)
	{
		o.onmousedown	= Drag.start;

		o.hmode			= bSwapHorzRef ? false : true ;
		o.vmode			= bSwapVertRef ? false : true ;

		o.root = oRoot && oRoot != null ? oRoot : o ;

		if (o.hmode  && isNaN(parseInt(o.root.style.left  ))) o.root.style.left   = "0px";
		if (o.vmode  && isNaN(parseInt(o.root.style.top   ))) o.root.style.top    = "0px";
		if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right  = "0px";
		if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";

		o.minX	= typeof minX != 'undefined' ? minX : null;
		o.minY	= typeof minY != 'undefined' ? minY : null;
		o.maxX	= typeof maxX != 'undefined' ? maxX : null;
		o.maxY	= typeof maxY != 'undefined' ? maxY : null;

		o.xMapper = fXMapper ? fXMapper : null;
		o.yMapper = fYMapper ? fYMapper : null;

		o.root.onDragStart	= new Function();
		o.root.onDragEnd	= new Function();
		o.root.onDrag		= new Function();
	},

	start : function(e)
	{
		var o = Drag.obj = this;
		e = Drag.fixE(e);
		var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
		var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
		o.root.onDragStart(x, y);

		o.lastMouseX	= e.clientX;
		o.lastMouseY	= e.clientY;

		if (o.hmode) {
			if (o.minX != null)	o.minMouseX	= e.clientX - x + o.minX;
			if (o.maxX != null)	o.maxMouseX	= o.minMouseX + o.maxX - o.minX;
		} else {
			if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
			if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
		}

		if (o.vmode) {
			if (o.minY != null)	o.minMouseY	= e.clientY - y + o.minY;
			if (o.maxY != null)	o.maxMouseY	= o.minMouseY + o.maxY - o.minY;
		} else {
			if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
			if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
		}

		document.onmousemove	= Drag.drag;
		document.onmouseup		= Drag.end;

		return false;
	},

	drag : function(e)
	{
		e = Drag.fixE(e);
		var o = Drag.obj;

		var ey	= e.clientY;
		var ex	= e.clientX;
		var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
		var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
		var nx, ny;

		if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
		if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
		if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
		if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);

		nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
		ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));

		if (o.xMapper)		nx = o.xMapper(y)
		else if (o.yMapper)	ny = o.yMapper(x)

		Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
		Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
		Drag.obj.lastMouseX	= ex;
		Drag.obj.lastMouseY	= ey;

		Drag.obj.root.onDrag(nx, ny);
		return false;
	},

	end : function()
	{
		document.onmousemove = null;
		document.onmouseup   = null;
		Drag.obj.root.onDragEnd(	parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]), 
									parseInt(Drag.obj.root.style[Drag.obj.vmode ? "top" : "bottom"]));
		Drag.obj = null;
	},

	fixE : function(e)
	{
		if (typeof e == 'undefined') e = window.event;
		if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
		if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
		return e;
	}
};