/**
 * @filename library.js
 * @author EESG Staff
 * @created Wednesday September 26, 2007 - 10:31AM PST
 * 
 * @fileOverview This file contains generic javascript that is common
 *               to all pages within the application.  It is automatically
 *               included by index.cfm
 */

/**
 * the username of the current user
 */
 
 // global variables
var debugWindow;  // used do display error messages to the developers
var callsToHideSelect = 0; 
var DEBUG = false;
//var whichServer="";
//var rootURL = "http://206.116.62.243/internal/eesg/v2/";
//var securityRootURL = "http://206.116.62.243/internal/eesg/v2/zone";
//put the following va
//var rootURL = "http://www.electricedgesystems.com";
//var securityRootURL = "http://www.electricedgesystems.com/zone";

var g_hiddenLayers = new Array();
var username = "";

/**
 * the userID in the database of the current user
 */
var userID   = 0;

/**
 * the user type of the current user
 */
var userType = 0;

/**
 * a central way to maintain a list of the currently running ajax
 * calls so that they can be properly routed to the appropriate
 * callback function after they have been processed by the 
 * central ajax callback function (ajaxCallback).
 */
var callbackStack = new Array();


/**
 * Perform a remote call to method in a CFC through AJAX.  Can be called with or
 * without a form.  If no form is specified, a default form is used to transport
 * the data required for the call to execute on the server and return. 
 * 
 * @param {string} formName the name of the form to send.  May be blank.
 * @param {string} methodName the name of the method to call in the CFC component
 * @param {string} componentName the name of the component that the method exists in
 * @param {object} callbackFunction the name of the function to call when the
 *                 results of the ajax call return from the server.
 * 
 * @param {string} ajaxMessage a message to display to the user while the ajax
 *                 call is taking place.
 * @param {string} otherData a comma delimited list of name=value pairs indicating
 *                 additional arguments to be passed to the method being called on
 *                 the server.
 * @example ajaxCall("", "deleteTimesheetDetail", "projects", deleteTIDTCB, "Deleting Record","tidtID="+tidtID)
 * @return (void)
 */
function ajaxCall(formName, methodName, componentName, callbackFunction, ajaxMessage, otherData) {
  
  var form      = formName.length ? document.getElementById(formName) : document.getElementById("defaultAjaxForm");
  
  document.getElementById("errorDiv").innerHTML = "";

  displayMessage(ajaxMessage,400);
  callbackOne = callbackFunction;

  form.method.value = methodName;
  
  form.component.value = componentName;
  form.callback.value = callbackFunction.name;
  form.otherData.value = otherData;

  //alert("passing: "+form.method.value);

  callbackStack[callbackFunction.name] = callbackFunction;

  //alert('callbackStack: '+callbackStack[callbackFunction.name]);
  //To get the "/" style URL working, the masterHandler.cfm has to be specified using absolute folder.
  //The rootURL is specified in the index.cfm.
  masterURL = rootURL + "/masterHandler.cfm";
  ColdFusion.Ajax.submitForm(form,
                             masterURL,
                             ajaxCallback,
                             errorHandler);
  return;
}



/**
 * display text in a popup div on the web page.
 * 
 * @param (string) message the message to display in the popup div
 * @param (integer) width the desired width of the display message.  If unspecified,
 *                         a default width will be chosen. 
 * @param (integer) height the desired height of the display message.  If unspecified,
 *                         a default height will be chosen. 
 */
function displayMessage(message, width, height)
{
  var objStyle = document.getElementById("ajaxMessageDiv").style;
  var id = document.getElementById("ajaxMessageDiv");

  objStyle.width = width;
  
  // get the width and height
  var w = parseInt(objStyle.width);
  var h = parseInt(objStyle.height);

  // default to 0 if unspecified
  if (isNaN(w)) w = 0;
  if (isNaN(h)) h = 0;

  var pos = findViewPort();
  
  objStyle.left = (pos["Width"] - w)/2;
  objStyle.top = findScrollPos("Top") + (pos["Height"] - h)/2;

  // set the text of the message and make it visible   
  setContent(message, "ajaxMessageDiv");
  //callBackAlert(''+content+'','ok', 'hidemessage');
  // if (typeof(hideSelectBoxesPop) == "function") hideSelectBoxesPop(id); 

  return false;
}


/**
 * This function processes the result of ajax calls from the server.  At this
 * point, it 
 * <ul>
 *  <li>clears the ajax message (TODO)</li>
 *  <li>checks to see if an exception was caused during the execution of this
 *      ajax call to the server</li>
 *  <li>dispatch the result to the appropriate javascript function</li>
 * </ul>
 * 
 * @param {string} content the string returned from the ajax call. (TODO-use JSON instead of simple string?)
 * 
 * @return (void)
 */
function ajaxCallback(content) {
  var myContent = content.replace(/^\s+|\s+$/g,"").split(":::");
 
 var callback = myContent[2];
  var data     = myContent[1];
  var type     = myContent[0];
  //setContent("<div id='ajaxMessageTitle'>  <span style='float: left;'><img src='images/win_client_access.gif' style='border:0px;' alt='Client Access'></span><a href='javascript: void 0' onClick='hideMessage();'><img src='images/cross.png' style='border:0px;' alt='[X]'></a></div><div id='ajaxMessageContent'>Invalid password/username combination. Please try again.</div>", "ajaxMessageDiv");

  //hideMessage disabled while the db is not connected
  hideMessage();
  //alert("got: "+content);
  //alert("callbackStack[] = "+callbackStack[callback]);
  
  if(type == 'exception') 
  {
  	if(whichServer == 'prod')
  	{
  		window.location.href = rootURL + "/causeError.cfm";
  	}
  	else
  	 {
      getObj("exception").innerHTML = content;
      displayElement("exception", 'show');
  	 }
  
  }
  else {
    callbackStack[callback].call(this,data,type); 
  }

}



// **********************************************************************************
// Function: getTags
//
// Purpose: Get an object by it's tag using either the web standard function
//           or older browser implementation functions
//
// Parameters: name     - the name of the desired html tag
//             parentId - id of parent element. If specified, will only return tags
//                        from within the parent
//
// Returns: a collection of html objects
// *********************************************************************************
function getTags(name, parentId)
{
  var objArray = null;
  
  // if modern browser
  if (document.getElementsByTagName)
  {
    // if parent was specified get the tags from it, otherwise return all
    if(DEBUG && parentId) debug("parentId: ["+parentId+"] name:["+name+"]");

    if (parentId)
    {
      var obj = getObj(parentId);
      if (obj)
        objArray = obj.getElementsByTagName(name);    
    }
    else
      objArray = document.getElementsByTagName(name);
  }
  // try older IE function
  else if (document.all)
  {
    //TODO How does an old IE handle getting tags array from a parent?
    // document.all.item(parentId).children.tags(name) - only direct children
    objArray = document.all.tags(name);
  }

  //If element fails to find any tags with the given name, create an empty array
  if (objArray == null)
    objArray = new Array();
  // If element does not return an array, create one containing the single object
  else if (objArray.length === undefined)
    objArray = new Array(objArray);
    
  return objArray;
}

// **********************************************************************************
// Function: getObj
//
// Purpose: Get an object by it's id using either the web standard function
//           or older browser implementation functions
//
// Parameters: id - the id of the desired html element
//
// Returns: an html object
// *********************************************************************************
function getObj(id)
{
  var obj;
  
  // if modern browser
  if (document.getElementById)
  {
    obj = document.getElementById(id);
  }
  // try older IE function
  else if (document.all)
  {
    obj = document.all.item(id);
  }
    
  return obj;
}

// **********************************************************************************
// Function: getOpenerObj
//
// Purpose: Get an object by it's id in opener window
//         using either the web standard function
//           or older browser implementation functions
//
// Parameters: id - the id of the desired html element
//
// Returns: an html object
// *********************************************************************************
function getOpenerObj(id)
{
  var obj;
  var openerDocument = window.opener.document;
  
  // if opener window exists and not closed
  if (window.opener && !window.opener.closed)
  {
      // if modern browser
      if (openerDocument.getElementById)
      {
        obj = openerDocument.getElementById(id);
      }
      // try older IE function
      else if (openerDocument.all)
      {
        obj = openerDocument.all.item(id);
      }
      
  }
    
  return obj;
}


// **********************************************************************************
// Function: getObjs
//
// Purpose: Get an array of objects by their common id using either the web standard
//           function or older browser implementation functions
//          Used for cases where form elements could have same id (radio buttons, etc.)
//
// Parameters: id - the common id of the desired html elements
//
// Returns: an array of objects
// *********************************************************************************
function getObjs(id)
{
  var objArray;

  if (document.getElementsByName)
  {
    objArray = document.getElementsByName(id);
  }
  else
  {
    var obj = getObj(id);
  
    var objArray = eval("obj.form."+id);
  
    // If element does not return an array, create one
    if (objArray.length === undefined)
      objArray = new Array(obj);
  }
  
  return objArray;
}



// **********************************************************************************
// Function: displayElement
//
// Purpose: Set the visibility & display properties of a given object id
//          Used for cases where form elements could have same id (radio buttons, etc.)
//
// Parameters: id    - the id of the desired html element
//             state - indicate which state to set, or swap state if unspecified
//                     valid values: unspecified, 'show', or 'hide'
//             prop  - indicate which property to set, or both if unspecified
//                     valid values: unspecified, 'display', or 'visibility'
//
// Returns: nothing
// *********************************************************************************
function displayElement(id,state,prop)
{
  var element = getObj(id);

  if (element)
  {
    // if state was not specified, simply switch the state to it's opposite
    if(state==undefined || state==null)
    {
      // if property was not specified as 'display', set the visibility property
      if(prop==undefined || prop==null || prop!='display')
        element.style.visibility = (element.style.visibility == 'hidden') ? 'visible' : 'hidden';
  
      // if property was not specified as 'visibility', set the display property
      if(prop==undefined || prop==null || prop!='visibility')
        element.style.display = (element.style.display == 'none') ? 'block' : 'none';
    }
    else
    {
      // if property was not specified as 'display', set the visibility property
      if(prop==undefined || prop==null || prop!='display')
        element.style.visibility = (state == 'show') ? 'visible' : 'hidden';
  
      // if property was not specified as 'visibility', set the display property
      if(prop==undefined || prop==null || prop!='visibility')
        element.style.display = (state == 'show') ? 'block' : 'none';
    }
  }
}


// **********************************************************************************
// Function: setStyle
//
// Purpose: Set the specified property or list of properites of a given object id
//
// Parameters: id    - the id of the desired html element
//             prop  - indicate which property to set (will also accept a comma
//                      delimited list)
//             val   - the value to set the propert(y|ies) to (will also accept a
//                      comma delmited list)
//
// Returns: nothing
// *********************************************************************************
function setStyle(id, prop, val)
{
  var obj = getObj(id).style;
  var props = prop.split(",");
  var vals = val.split(",");
  
  for (var i=0; i < props.length; i++)
  {
    if (props.length == vals.length)
      eval("obj."+props[i]+"='"+vals[i]+"'");
    else
      eval("obj."+props[i]+"='"+vals[0]+"'");
  }

  return;
}

// **********************************************************************************
// Function: roundTo
//
// Purpose: round a float to specified decimal places
//          created because toFixed/toPrecision have rounding errors on some browsers
//
// Parameters: num - the number to round
//             dec - number of decimal places to round to
//
// Returns: number rounded to the number of decimal places
// *********************************************************************************
function roundTo(num,dec)
{
/* demo of the rounding error
  var n = 6.295;
  var t = Math.round(n*Math.pow(10,2))/Math.pow(10,2);
  alert(t + " VS " + n.toPrecision(3) + " VS " + n.toFixed(2));
*/
  return Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
}

// **********************************************************************************
// Function: findPos
//
// Purpose: Find the offset(s) of a specified element
//
// Parameters: prop - Which property wanted ('Left' or 'Top')
//                    If not specified both positions will be returned in a string
//                     indexed array ('Left' and 'Top')
//
// Written by: Steve Walton for Electric Edge Systems Group
// Date: April 12 2006
// *********************************************************************************
function findPos(obj,prop)
{
  var retval;
  var curTop = 0;
  var curLeft = 0;

 	if (obj.offsetParent)
	{
		while (obj.offsetParent)
 		{
 			curTop += obj.offsetTop;
      curLeft += obj.offsetLeft;
 			obj = obj.offsetParent;
 		}
 	}
 	else if (obj.y && obj.x)
  {
 		curTop += obj.y;
  	curLeft += obj.x;
  }
 
  switch (prop)
  {
    case "Left":
      retval = curLeft;
      break;
      
    case "Top":
      retval = curTop;
      break;
    
    default:
      retval = new Array();
      retval["Top"] = curTop;
      retval["Left"] = curLeft;
      break;
  }
 
 	return retval;
}

/**
 * @param objectList a list of form objects or forms to clear 
 *                   the values out of 
 *
 * @return none
 *
 * @author Steve Walton (Electric Edge Systems) MAY 9 2006
 */
function clearObjects(objectList) {
  var objects = objectList.split(",");
  var obj;
  
  for(var count = 0; count < objects.length; count++) {
    obj = getObj(objects[count]);

    switch(obj.tagName.toUpperCase())
    {
      case "FORM":
        //recursive call to handle all form fields
        for (var i=0; i<obj.length; i++)
        {
          element = obj.elements[i];
          
          if (element.type == "text")
            element.value = "";
        } 
        break;
      case "SPAN":
      case "DIV":
        obj.innerHTML = "";
        break;
      case "INPUT":
        if (obj.type == "text")
          obj.className = 'inputText';
      default:
        obj.value = "";
        break;
    }
  }
  return;
}

/**
 * Creates an alert box effect with a popup div.
 *
 * @param msg                message to display
 * 
 * @return true 
 *
 * @author Allen Souliere (Electric Edge Systems) June 19 2006
 */
function callbackAlert(msg, buttonName, callbackFunction, buttonName2, callbackFunction2, buttonName3, callbackFunction3) {
  returnValue = true;

  lastLine = "<br><br> ";

  if(buttonName && buttonName.length) {
    if (callbackFunction.indexOf('(') == -1)
      callbackFunction += "()";
      
    lastLine += "<span style='margin-right:10px'><a href='javascript:void "+callbackFunction+";' onclick='hideMessage();' class='linkButton'>"+buttonName+"</a></span>";
  }
  else {
    lastLine += "<span  style='margin-right:10px'><a href='javascript:void 0;' onclick='hideMessage();' class='linkButton'>OK</a></span>";
  }

  if(buttonName2 && buttonName2.length) {
    if(callbackFunction2 && callbackFunction2.length) {
      lastLine += "<span  style='margin-right:10px'><a href='javascript:void "+callbackFunction2+"();' onclick='hideMessage();' class='linkButton'>"+buttonName2+"</a></span>";
    }
    else {
      lastLine += "<span  style='margin-right:10px'><a href='javascript:void 0;' onclick='hideMessage();' class='linkButton'>"+buttonName2+"</a></span>";
    }
  }

  if(buttonName3 && buttonName3.length) {
    if(callbackFunction3 && callbackFunction3.length) {
      lastLine += "<span  style='margin-right:10px'><a href='javascript:void "+callbackFunction3+"();' onclick='hideMessage();' class='linkButton'>"+buttonName3+"</a></span>";
    }
    else {
      lastLine += "<span  style='margin-right:10px'><a href='javascript:void 0;' onclick='hideMessage();' class='linkButton'>"+buttonName3+"</a></span>";
    }
  }

  lastLine += "<br>";
   
  msg += lastLine;
 
  displayMessage(msg,450,350);
   
  return returnValue;
   
}




// *************************************************************************************
// ******************************************************************************************
// hideSelectBoxes
//
// Written by: Keith Anderson
//
// Date April 24, 2006
//
// Purpose: When a popup div appears over a select box
//          the select box still shows!!
//          This function will hide the select boxes in a given from
//          that overlap with a given popup div
//
// Arguments: formName - name/id of the form which may have the offending select boxes
//            divToHide - id of the popup div
// ******************************************************************************************
function hideSelectBoxes(formName,divToHideFrom)
{
  var formArray, sel = new Array();

  // get an array of form names based on the formName
  if (arguments.length && formName.length)
    formArray = formName.split(",");
  else
  {
    // create an array of all form names
    var tags = getTags("FORM");
    formArray = new Array();

    for (var t=0; t < tags.length; t++)
      formArray.push(tags[t].id);
  }

  if(arguments.length > 1 && divToHideFrom.length)
  {
    // get an array of form names to exclude from hiding
    var ignoreForms = getTags("FORM", divToHideFrom); 
    var formList = formArray.toString();
  
    // check for excluded form names in form list
    for (var f=0; f < ignoreForms.length; f++)
    {
      // if found remove form list to hide
      if (formList.indexOf(ignoreForms[f].id) != -1)
      {
        // find array index to be removed, and remove it
        for (var r=0; r < formArray.length; r++)
          if (formArray[r] == ignoreForms[f].id)
            formArray.splice(r,1);
      }
    }
  }
  
  if (DEBUG) debug("formArray: '"+formArray.toString()+"' ["+formArray.length+"]");

  // iterate through array of forms to hide, and get all the select boxes
  for (var i=0; i < formArray.length; i++)
  {
    // get select boxes for current form
    tags = getTags("SELECT", formArray[i]);

    // add to array of select boxes to hide 
    for (var t=0; t < tags.length; t++)
      sel.push(tags[t]);
  }

  // update counter indicating something will be hidden    
  callsToHideSelect++;
  
  if (DEBUG) debug("hide: "+callsToHideSelect);     
  
  // get the absolute position of the div thats popping up
  var myObj = getObj(divToHideFrom);
  var myPos = findPos(myObj);  

  x = myPos["Left"];
  y = myPos["Top"];

  y2 = y + myObj.offsetHeight;
  x2 = x + myObj.offsetWidth;      

  // go thru each select box and find the appropriate ones to hide      
  for(i=0; i < sel.length; i++)
  {     
     // get the absolute position of this select box
     myPos = findPos(sel[i]);
     selx = myPos["Left"];
     sely = myPos["Top"];
     sely2 = sely + sel[i].offsetHeight;
     selx2 = selx + sel[i].offsetWidth;              

     // ok now we have the all absolute positions so lets see if any select boxes
     // overlap with popup div, if they overlap hide the select box
     if ((selx2 >=  x) && (selx <= x2) && (sely2 >= y) && (sely <= y2))
     {       
//alert("hiding the element '" + sel[i].id + "'");
       displayElement(sel[i].id,'hide','visibility');
     }         
  }  
  
  return false;
}

// ************************************************************************************
// isIdInForm
//
// written by: Keith Anderson for Electric Edge Systems
//
// Date: April 25, 2006
//
// needed by hide select boxes
//
// determines if a given id is part of a given form
// returns true or false
//
// **************************************************************************************
function isIdInForm(formName,theId)
{
   retVal = false;   
      
   elems = document.forms[formName].elements;   
    
   for (j=0;j<elems.length;j++)
   {
       if (elems[j].id == theId)
       {
           retVal = true;
           j = elems.length;
       }
   }      
   
   return retVal;
}

// ******************************************************************************************
// showSelectBoxes
//
// Written by: Keith Anderson for Electric Edge Systems
//
// Date April 24, 2006
//
// shows all hidden select boxes
// ******************************************************************************************
function showSelectBoxes()
{

// TODO: account for additional forms that are included on the page which may contain offending
//        select boxes that need to be hidden when messages pop up.
//    
  // get all the select boxes  
  var sel = getTags("SELECT");

  //don't try to adjust the counter if it is already at 0 
  if(callsToHideSelect)
    callsToHideSelect--;

  if (DEBUG) debug("show: "+callsToHideSelect);     

  // show all select boxes
  if (callsToHideSelect < 1)
  {
    for(i=0; i < sel.length; i++)
    {
//alert("showing the element '" + sel[i].id + "'");
       displayElement(sel[i].id,'show','visibility');
    }
  }
    
  return false;
}

/**
 * Hide select boxes on all but a given layer (fix for IE select box issue)
 *
 * @member Library
 *
 * @param divName name of div to exclude from hiding
 *
 * @return nothing
 * 
 * @author Steve Walton (Electric Edge Systems) Sept 21 2006
 */
function hideSelectBoxesPop(divName)
{
  var hideId = "";
  
  // get an array of all select boxes
  var hideArray = getTags("SELECT");
  
  // get an array of select boxes to exclude from hiding
  var ignoreArray = getTags("SELECT", divName); 
  var ignoreList = ignoreArray.toString();
  
  // iterate through array of select boxes
  for(var h=0; h < hideArray.length; h++)
  {
    hideId = (hideArray[h].id)? hideArray[h].id : hideArray[h].name;
    
    // if current id is NOT in list of exclusions, hide it
    if (ignoreList.indexOf(hideId) == -1)
      displayElement(hideId,'hide','visibility');
  }

  if(DEBUG) debug("pushing "+divName);
  
  // push layer name onto g_hiddenLayers stack for use by showSelectBoxesPop
  g_hiddenLayers.push(divName);
    
  return;
}

/**
 * Show all select boxes on a particular layer
 *
 * @member Library
 *
 * @param condition only show select boxes when on top of the stack (optional)
 *
 * @return nothing
 * 
 * @author Steve Walton (Electric Edge Systems) Sept 21 2006
 */
function showSelectBoxesPop(condition)
{
  var showId = "";
  var parentVisible = true;

//alert("show condition:"+condition);
  
  // when a condition is specifed, only show if condition is on top of the stack
  if ( !arguments.length || !g_hiddenLayers.length ||
       ( condition.length && 
         condition == g_hiddenLayers[g_hiddenLayers.length - 1] ) )
  {
    // get name of layer to not show selects on from g_hiddenLayers stack
    var divName = g_hiddenLayers.pop();

    if (DEBUG) debug("popping "+divName)

    var showLayer = (g_hiddenLayers.length)? g_hiddenLayers[g_hiddenLayers.length-1] : "content";
//alert("show:"+showLayer+" ignore:"+divName);
    // get an array of the next layers' select boxes
    var showArray = getTags("SELECT", showLayer);
  
    // get an array of select boxes to exclude from showing
    var ignoreArray = getTags("SELECT", divName); 
    var ignoreList = ignoreArray.toString();
  
    // iterate through array of select boxes
    for(var s=0; s < showArray.length; s++)
    {
      showId = (showArray[s].id)? showArray[s].id : showArray[s].name;
      parentVisible = (showArray[s].form.style.visibility == 'hidden')? false: true;
    
      // if current id is NOT in list of exclusions and parent is showing, show select
      if (ignoreList.indexOf(showId) == -1 && parentVisible)
        displayElement(showId,'show','visibility');
    }
  }

  return;
}

// ************************************************************************************
// 
// ***********************************************************************************
function getPopUpPosition(fromTopOffset,divWidth, divHeight)
{
  // calculate needed offset from top of the screen  
  var screenTop = findScrollPos("Top");
  var offset = 0;

  if (offset < fromTopOffset)
    offset = fromTopOffset;
  
  // set values based on offset
  retTop = screenTop + offset;
  retLeft = (document.body.offsetWidth - divWidth)/2
  
  // create return array and add values
  retArray = new Array();
  retArray["Left"] = retLeft;
  retArray["Top"] = retTop;
   
  return retArray;
}



/**
 * Places a message into the specified div, '_errMsg' div, or debug window.
 *
 * @member Library
 *
 * @param content    message to display or empty string if the element is to be cleared
 * @param target     div to fill with content.  Defaults to '_errMsg' div.
 * @param defaultMsg optional message to display if content is empty string
 * 
 * @author Steve Walton (Electric Edge Systems) June 19 2006
 */
function setContent(content, target, defaultMsg)
{
  // Check if there is any content to display
  if(content)
  {
    // dump the string into the div
    getObj(target).innerHTML = content;
  
    // make sure the div is visible
    displayElement(target, 'show'); 
  }
  else
  {
    //is there a default message to be displayed?
    if (defaultMsg)
    {
      // dump the string into the div
      getObj(target).innerHTML = defaultMsg;
    
      // make sure the div is visible
      displayElement(target, 'show'); 
    }
    else
    {
      //no content means no need for display element 
      displayElement(target, 'hide');
    } 
  }
}


/**
 * hide the ajax loading message.
 * 
 * @return void
 */
function hideMessage()
{
  displayElement("ajaxMessageDiv",'hide');   
  return false;
}

// **********************************************************************************
// Function: resetMessage
//
// Purpose: Reset contents of message text area
//
// Parameters: none
//
// Written by: Steve Walton for Electric Edge Systems Group
// Date: May 11 2006
// *********************************************************************************
function resetFields(fieldList)
{
  var field, fields = fieldList.split(",");
  
  for(var count = 0; count < fields.length; count++)
  {
    field = getObj(fields[count]);
    field.value = field.defaultValue;
  }
  
  return;
}

/**
 * Controls redirection by processing a list of objects and creating a new uri
 *  from the contents of the objects and any additional parameters
 * 
 * @member Library
 *  
 * @param objName a comma delimited list of objects to process
 * @param addParams any additional parameters to add to the new uri
 *  
 * @return nothing
 *
 * @author Steve Walton (Electric Edge Systems) June 28 2006
 */
function gotoURI(objName, addParams)
{
  var val = "./index.cfm?pg=";
  var baseLen = val.length;
  var objNameArray = objName.split(",");

  // process list of objects 
  for(var i=0; i < objNameArray.length; i++)
  { 
    var obj = getObj(objNameArray[i]);
  
    if (obj)
    {
      // process tags differently based on the type
      switch(obj.tagName.toUpperCase())
      {
        case "SPAN":
        case "DIV":
          var uri = new String(obj.innerHTML);
          // fix any ampersand conversions due to innerHTML
          val += uri.replace(/&amp;/gi, "&");
          break;
        default: // handle form fields
          val += obj.value;
          break;
      }
    }
  }
  
  // if additional paramenters were specified add them to the redirection string
  if(addParams)
    val += addParams.replace(/&amp;/gi, "&");

  if(DEBUG) debug("redirect to: " + val);

  // if actually have a new location to load then load page
  if (val.length > baseLen)
    document.location.href = val;
    
  return;
}

/**
 * Display a debugging message.  This is used for development purposes
 * only.
 * 
 * <p>TODO make this debugging function display append these strings (one
 *       line at a time in a separate debug window or div perhaps</p>
 *
 * @param debugStr the string to display to the programmer.
 *
 * @author Allen Souliere (Electric Edge Systems Group) MAR 01 2006
 * @member ReallSumEditJS
 */
function debug(debugStr) {
  alert("DEBUG-"+debugStr);
}

/**
 * Toggles between 'select all' or 'deselect all' for the checkboxes
 * on the form.
 * 
 * @member Library
 *
 * @param cbName name of the check box array.
 * @param cbAll  id of the select all checkbox (defaults to cbName + "All")
 * 
 * @return nothing
 *
 * @author Steve Walton (Electric Edge Systems) Sept 20 2006
 */
function selectAll(cbName, cbAll)
{
  var rowItems = getObjs(cbName);
  
  if (arguments.length < 2 || cbAll.length == 0)
    cbAll = cbName + "All";

  // for each selectbox set its value to the value of the select all box
  for(var i = 0; i < rowItems.length; i++)
    rowItems[i].checked = getObj(cbAll).checked;
  
  return;
}

/**
 * Each time a check box is selected, lets determine whether or not
 * we will have to update the select all checkbox to reflect the 
 * checked status of all the checkboxes.
 * 
 * @member Library
 *
 * @param cbName name of the check box array.
 * @param cbAll  id of the select all checkbox (defaults to cbName + "All")
 *
 * @return nothing
 *
 * @author Steve Walton (Electric Edge Systems) Sept 20 2006
 */
function selectOne(cbName, cbAll) {
  var rowItems = getObjs(cbName);
  var allChecked = true;
  
  if (arguments.length < 2 || cbAll.length == 0)
    cbAll = cbName + "All";

  // find out if any checkbox is not checked
  for(var i = 0; i < rowItems.length; i++)
  {
    if(rowItems[i].checked == false)
    {
      allChecked = false;
      break;
    }
  } 

  // update the state of the 'select all' checkbox
  getObj(cbAll).checked = allChecked;

  return;
}


/**
 * The dimensions of the window available to the document.
 * 
 * @param (string) prop Which property is wanted ('Width' or 'Height'),
 *              If not specified both positions will be returned in a string
 *              indexed array ('Width' and 'Height')
 *
 * @return nothing
 *
 * @author Steve Walton (Electric Edge Systems) Oct 16 2006
 */
function findViewPort(prop)
{
  var x,y;

  if (!arguments.length)
    prop = "";

  // all except Explorer
  if (self.innerHeight)
  {
    x = self.innerWidth;
    y = self.innerHeight;
  }
  // Explorer 6 Strict Mode
  else if (document.documentElement && document.documentElement.clientHeight)
  {
    x = document.documentElement.clientWidth;
    y = document.documentElement.clientHeight;
  }
  // other Explorers
  else if (document.body)
  {
    x = document.body.clientWidth;
    y = document.body.clientHeight;
  }

  // only return property asked for
  switch (prop.toLowerCase())
  {
    case "width":
      retval = x;
      break;
      
    case "height":
      retval = y;
      break;
    
    default:
      retval = new Array();
      retval["Width"] = x;
      retval["Height"] = y;
      break;
  }
 
  return retval;
}


/**
 * How much the page has scrolled in a particular direction.
 * 
 * @param (string) prop Which property is wanted ('Left' or 'Top'). 
 *              If not specified both positions will be returned in a string
 *              indexed array ('Left' and 'Top')
 *
 * @return integer or array of integers
 *
 * @author Steve Walton (Electric Edge Systems) Oct 16 2006
 */
function findScrollPos(prop)
{
  var x,y;
  // all except Explorer
  if (self.pageYOffset)
  {
    x = self.pageXOffset;
    y = self.pageYOffset;
  }
  // Explorer 6 Strict
  else if (document.documentElement && document.documentElement.scrollTop)
  {
    x = document.documentElement.scrollLeft;
    y = document.documentElement.scrollTop;
  }
  // all other Explorers
  else if (document.body)
  {
    x = document.body.scrollLeft;
    y = document.body.scrollTop;
  }

  // only return property asked for
  switch (prop.toLowerCase())
  {
    case "top":
      retval = y;
      break;
      
    case "left":
      retval = x;
      break;
    
    default:
      retval = new Array();
      retval["Top"] = y;
      retval["Left"] = x;
      break;
  }
 
  return retval;
}


/**
 * Format a numeric string into a comma delimited string
 * 
 * @member Library
 *
 * @param nStr numeric string to be formatted
 *
 * @return comma delimited numeric string
 *
 * @author Steve Walton (Electric Edge Systems) Jan 4, 2007
*/
function addCommas(nStr)
{
  var strNum = new String(nStr);
  //seperate integer from possible floating point number
  var arrNum = strNum.split('.');
  //set regular expression for formatting
	var rgx = /(\d+)(\d{3})/;

  //use regex to update string
	while (rgx.test(arrNum[0]))
		arrNum[0] = arrNum[0].replace(rgx, '$1' + ',' + '$2');

  //combine the array for possible floating point number
  return arrNum.join('.');
}

function removeCommas(nStr)
{
  var strNum = new String(nStr);
  //seperate integer from possible floating point number
  var arrNum = strNum.split('.');
  //seperate on commas
  var arrComma = arrNum[0].split(',');

  //rejoin with no commas
  arrNum[0] = arrComma.join('');

  //combine the array for possible floating point number
  return arrNum.join('.');
}

  function ltrim(str) 
  { 
	for(var k = 0; k < str.length && isWhitespace(str.charAt(k)); k++);
	return str.substring(k, str.length);
 }
function rtrim(str) {
	for(var j=str.length-1; j>=0 && isWhitespace(str.charAt(j)) ; j--) ;
	return str.substring(0,j+1);
}
function trim(str) {
	return ltrim(rtrim(str));
}
function isWhitespace(charToCheck) {
	var whitespaceChars = " \t\n\r\f";
	return (whitespaceChars.indexOf(charToCheck) != -1);
}

function errorHandler(code, msg) {
  alert("Error!!! " + code + ": " + msg);
  getObj("errorDiv").innerHTML = msg;
}

/* display error message */
function displayError(err_msg)
{
  getObj("err_msg").innerHTML=err_msg;
}

function ismaxlength(obj)
{
	var mlength=obj.getAttribute? parseInt(obj.getAttribute("maxlength")) : "";
	if (obj.getAttribute && obj.value.length>mlength)
	obj.value=obj.value.substring(0,mlength);
}

  


function userLogin()
{
	//Below line needs the cfc's to login
	var imageURL = "<div id='ajaxMessageContent'><img src='"+ imagePath +"/login.gif'> Verifying information</div>";
	ajaxCall('login', 'validateUser', 'security', userLoginCB, imageURL, '');
}

function userLoginCB(content, type)
{
	setContent(''+content+'', 'ajaxMessageDiv','');
	if (!content)
	{
    window.location = securityRootURL;
	};
}

/**
 * Checks to see if the enter key was pressed
 * 
 * @member Library
 *
 * @param 
 *
 * @return nothing
 *
 * @author Bryn Tassell (Electric Edge Systems) Feb 06, 2008
*/
function checkEnter(e)
    {
			var characterCode = 13;
			
			if(e && e.which)
			{
  			e = e;
  			characterCode = e.which; 
			}
			else
			{
  			e = event;
  			characterCode = e.keyCode; 
			}
			if(characterCode == 13)
			{ 
  			userLogin();
  			return false;
			}
			else
			{
			  return true;
			}
		}
function cf_DeleteAttachmentCall() {
  var form      		= document.getElementById('delAttachForm');
  form.method.value 	= 'deleteAttachment';
  form.component.value 	= 'issues';
  masterURL 			= "../../cf_masterHandler.cfm";
  document.getElementById("errorDiv").innerHTML = "";
  ColdFusion.Ajax.submitForm(form,
                             masterURL,
                             null,
                             null);
  return;
}
function cf_ajaxCall(formName, methodName, componentName, callbackFunction, ajaxMessage, otherDataArray) {
  var form      = formName.length ? document.getElementById(formName) : document.getElementById("defaultAjaxForm");
  
  document.getElementById("errorDiv").innerHTML = "";

  displayMessage(ajaxMessage,400);
  callbackOne = callbackFunction;

  form.method.value = methodName;
  
  form.component.value = componentName;
  form.callback.value = callbackFunction.name;
  form.otherData.value = ColdFusion.JSON.encode(otherDataArray);

  callbackStack[callbackFunction.name] = callbackFunction;

  //alert('callbackStack: '+callbackStack[callbackFunction.name]);
  //To get the "/" style URL working, the masterHandler.cfm has to be specified using absolute folder.
  //The rootURL is specified in the index.cfm.
  masterURL = rootURL + "/cf_masterHandler.cfm";

  ColdFusion.Ajax.submitForm(form,
                             masterURL,
                             cf_ajaxCallback,
                             errorHandler);
  return;
}


/**
 * This function processes the result of ajax calls from the server.  At this
 * point, it 
 * <ul>
 *  <li>clears the ajax message (TODO)</li>
 *  <li>checks to see if an exception was caused during the execution of this
 *      ajax call to the server</li>
 *  <li>dispatch the result to the appropriate javascript function</li>
 * </ul>
 * 
 * @param {string} content the string returned from the ajax call. (TODO-use JSON instead of simple string?)
 * 
 * @return (void)
 */
function cf_ajaxCallback(response) {
  
  var res = ColdFusion.JSON.decode(response);
  var success = res.SUCCESS;
  //convert to string before decoding
  res.DATA = res.DATA.toString();
  var returnData = ColdFusion.JSON.decode(res.DATA);
  
  var callBackFunc = res.CALLBACK;
  
  hideMessage();
  
  if(success)
  {
    callbackStack[callBackFunc].call(this,returnData); 
  } 
  else
  {
    if(whichServer == 'prod')
    {
      window.location.href = rootURL + "/causeError.cfm";
    }
    else
     {
      getObj("exception").innerHTML = returnData;
      displayElement("exception", 'show');
     }
  }  
  return;
}

