//////////////////////////////////////////////////////////////////////
// (c) 2005 Evolving Web
// Unauthorized use is prohibited.
//////////////////////////////////////////////////////////////////////

var DEBUG = false;

// Global variables
var isIE  = (document.all) ? true : false;
var isNS  = (document.layers) ? true : false;
var isDOM = (document.getElementById) ? true : false;

// Variables for each page.
var PageProps = new Object ();

// Mouse.
PageProps.mouseX         = 0;
PageProps.mouseY         = 0;
PageProps.mouseWindowX   = 0;
PageProps.mouseWindowY   = 0;
PageProps.mouseDownX     = 0;
PageProps.mouseDownY     = 0;
PageProps.mouseIncX      = 0;
PageProps.mouseIncY      = 0;
PageProps.isMouseDown    = false;

// Keys.
PageProps.keyUp          = 0;
PageProps.keyDown        = 0;
//PageProps.keyPress       = 0;

// Browser size.  Initialized to defaults.
PageProps.windowWidth  = 800;
PageProps.windowHeight = 600;

// Track the divs that programmatically get shown.
PageProps.visibleDivs = new Array ();

// Track the page hierarchy.
PageProps.pageLevel  = new Array ();

// If popup, says whether parent should reload when closed
PageProps.reload = false;

// Post-back properties.
PageProps.postBackQueue = null;
PageProps.downloadUrlCallbackFunction = null;
PageProps.downloadUrlComplete = true;

//////////////////////////////////////////////////////////////
// Functionality verification functions.
//////////////////////////////////////////////////////////////

// See if post backs can be done in the background.
PageProps.canDoBgPostBack = function () {
  return (PageProps.postBackIFrame != null);
}

// End: functionality verification functions. ////////////////


//////////////////////////////////////////////////////////////
// Global mouse functions.
//////////////////////////////////////////////////////////////

// Allow multiple mouse movement event functions.
var GlobalMouseMoves      = new Array ();
var GlobalMouseUps        = new Array ();
var GlobalWaitingMouseUps = new Array ();				// Functions to run during each mouse move until the next mouse up event.
var GlobalMouseDowns      = new Array ();
var GlobalSetValueOnMouseUp = new Array ();     // Properties to set on the next mouse up event.
var GlobalSetValueOnceOnMouseMove = new Array ();   // Set a value on the next mouse-move.

function RegisterMouseMove (f) {
	GlobalMouseMoves.push (f);
}

// Calls all the mouse movement functions.
function OnMouseMove (e) {
	if (!e) e = event;
	
/*	// Set a value one time.
	while (GlobalSetValueOnceOnMouseMove.length) {
	  SetPropertyValue (GlobalSetValueOnceOnMouseMove.shift ());
	}
*/

	// Call all the registered mouse move functions.
	for (var i=0; i<GlobalMouseMoves.length; i++) {
		GlobalMouseMoves[i] (e);
	}

	// Temporary mouse move events (until next mouse up).
	for (var i=0; i<GlobalWaitingMouseUps.length; i++) {
		GlobalWaitingMouseUps[i] (e);
	}

	if (DEBUG) {
	  var target = (e.target) ? ((e.target.id) ? e.target.id : "nullID") : e.srcElement;
//	  var exOrT  = (e.explicitOriginalTarget) ? ((e.explicitOriginalTarget.id) ? e.explicitOriginalTarget.id : "nullID") : "null";
	  var toEl   = (e.toElement) ? ((e.toElement.id) ? e.toElement.id : "nullID") : "null";
	  var curTar = (e.currentTarget) ? ((e.currentTarget.id) ? e.currentTarget.id : "nullID") : "null";
	  var relTar = (e.relatedTarget) ? ((e.relatedTarget.id) ? e.relatedTarget.id : "nullID") : "null";
	
		top.status  = "("+e.clientX+","+e.clientY+")("+PageProps.mouseX+","+PageProps.mouseY+") ";
		top.status += "target["+target+"] ";
//		top.status += "toEl["+toEl+"] curTar["+curTar + "] relTar["+relTar+"] ";
		top.status += "Moves("+GlobalMouseMoves.length+") FWaitingUps("+GlobalWaitingMouseUps.length+") ";
		top.status += "OWaitingUps("+GlobalWaitingMouseUps.length+") MoveObjects ("+GlobalMoveObjects.length+") ";
		top.status += "MouseDowns ("+GlobalMouseDowns.length+") ";
	}
	
	return true;
}

// Allow multiple mouse-up event functions.
function RegisterMouseUp (f) {
	GlobalMouseUps.push (f);
}

// Call a function with every mouse movement until the next mouse-up.
function RegisterUntilMouseUp (f) {
	GlobalWaitingMouseUps.push (f);
}

// Calls all the mouse up functions.
function OnMouseUp (e) {
	if (!e) e = event;
	
/*	// Assign a value to a property one time only.
	while (GlobalSetValueOnMouseUp.length) {
	  SetPropertyValue (GlobalSetValueOnMouseUp.shift ());
	}
*/
	
	// Call all the registered mouse up functions.
	for (var i=0; i<GlobalMouseUps.length; i++) {
		GlobalMouseUps[i] (e);
	}
	
	// Call the object functions that are run only once.
	while (GlobalObjectMouseUpOnce.length) {
		GlobalObjectMouseUpOnce.shift().mouseUpOnce (e);
	}
	
	// Remove all the functions waiting for a mouse up.
	while (GlobalWaitingMouseUps.length) {
		GlobalWaitingMouseUps.shift ();
	}
	
	PageProps.isMouseDown = false;            // Allow mouse down calls back on the page.
	document.onselectstart = null;            // Allow selecting of the page again.

	return true;
}

// Allow multiple mouse movement event functions.
function RegisterMouseDown (f) {
	GlobalMouseDowns.push (f);
}

// Calls all the mouse down functions.
function OnMouseDown (e) {
	if (!e) e = event;
  PageProps.isMouseDown = true;

	for (var i=0; i<GlobalMouseDowns.length; i++) {
		GlobalMouseDowns[i] (e);
	}
	
 if (!isIE && GlobalMoveObjects.length) 
   e.preventDefault ();
}

/*document.onmousemove = OnMouseMove;
document.onmouseup   = OnMouseUp;
document.onmousedown = OnMouseDown;*/
if (isIE) {
  document.attachEvent('onmousemove', OnMouseMove);
  document.attachEvent('onmouseup', OnMouseUp);
  document.attachEvent('onmousedown', OnMouseDown);
}
else {
  document.addEventListener('mousemove', OnMouseMove, false);
  document.addEventListener('mouseup', OnMouseUp, false);
  document.addEventListener('mousedown', OnMouseDown, false);
}
if (document.captureEvents)
	document.captureEvents(Event.MOUSEMOVE);

// Track the mouse movements.
function MouseMovements (e) {
	var x, y;
	
	if (isIE) {
		x = e.clientX + document.body.scrollLeft;
		y = e.clientY + document.body.scrollTop;
	}
	else {
		x = e.pageX;
		y = e.pageY;
	}
	
	PageProps.mouseX       = x;
	PageProps.mouseY       = y;
	PageProps.mouseWindowX = e.clientX;
	PageProps.mouseWindowY = e.clientY;
	PageProps.mouseIncX    = x - PageProps.mouseDownX;
	PageProps.mouseIncY    = y - PageProps.mouseDownY;
}
RegisterMouseMove (MouseMovements);

// Track mouse down locations.
function PageMouseDown (e) {
	var x, y;
	
	if (isIE) {
		x = e.clientX + document.body.scrollLeft;
		y = e.clientY + document.body.scrollTop;
	}
	else {
		x = e.pageX;
		y = e.pageY;
	}
	
	PageProps.mouseDownX = x;
	PageProps.mouseDownY = y;
}
RegisterMouseDown (PageMouseDown);
	
// Move object(s) with the mouse.
var GlobalMoveObjects = new Array ();
function MoveWithMouse (e) {
	// Validate the arguments.
	if (!GlobalMoveObjects.length)
		return false;
		
	// Prevent selecting of body objects when dragging objects in IE.
	if (!document.onselectstart) {
    document.onselectstart = function () { return false; };
  }
		
	for (var i=0; i<GlobalMoveObjects.length; i++) {
		var objStyle = GlobalMoveObjects[i];
		// Make sure the original information was set.
		if (null == objStyle.origTop || 
		    null == objStyle.origLeft)
			return false;
			
		// On the first mouse move, initialize the object.
		if (objStyle.isFirstMouseMove) {
	    // If the object is a 'static' control, temporarily make it 'relative'.
	    if (false == objStyle.isFixedPosition)
	      objStyle.position = 'relative';
	    else
	      objStyle.position = 'absolute';
      
      objStyle.isFirstMouseMove = false;
    }
		
		// Set the new location of the object.
		objStyle.top  = objStyle.origTop  + PageProps.mouseIncY;
		objStyle.left = objStyle.origLeft + PageProps.mouseIncX;
	}
	
	return true;
}
RegisterMouseMove (MoveWithMouse);

// Add an object to the movement list.
function RegisterMoveObject (obj) {
//alert('you');
	if (!obj) return false;
	obj = getObject (obj);
	
	// Set the original position coords and register the object for movement recognition.
	var objStyle = SetMouseDown (obj);
	if (objStyle) {
	  // If the object's position is not 'static' then firefox-based browsers will not send mousemove
	  // commands to the main window.
	  if (!isIE && false == objStyle.isFixedPosition)
	    objStyle.position = 'static';
	  
	  // Link to parent.
	  objStyle.parent = obj;
	  
	  GlobalMoveObjects.push (objStyle);
	}
}

// Remove the objects move objects waiting for a mouse up.
function UnregisterMoveObjects (e) {
	while (GlobalMoveObjects.length) {
		var objStyle = GlobalMoveObjects.shift ();
		ClearMouseDown (objStyle);
	}
}
RegisterMouseUp (UnregisterMoveObjects);

// Set the location of a mouse click on an object.
// Returns the object style.
function SetMouseDown (obj) {
	// Validate the arguments.
	if (!obj)
		return false;
	
	// Store the original object and cursor location.
	var objStyle = getObjectStyle (obj);
	var top  = parseInt (objStyle.top);
	var left = parseInt (objStyle.left);
	objStyle.origTop  = (isNaN (top))  ? 20 : ((false == objStyle.isFixedPosition) ? top + PageProps.moveObjects.objectBarHeight + 5 : top);
	objStyle.origLeft = (isNaN (left)) ?  0 : left;
	
	return objStyle;
}

// Clear the object mouse movement info.
function ClearMouseDown (objStyle) {
	// Validate the arguments.
	if (!objStyle)
		return false;
	
	// Reset the original object and cursor location.
	objStyle.origTop    = null;
	objStyle.origLeft   = null;
	objStyle.mouseDownX = null;
	objStyle.mouseDownY = null;
	
	return true;
}

// Reset the position of the object.
function ResetMoveObjects () {
  for (var i=0; i<GlobalMoveObjects.length; i++) {
    var objStyle = GlobalMoveObjects[i];
    
    // Explicitly check for 'false' as objects without the attribute set will return null
    // which also tests as false.
    if (false == objStyle.isFixedPosition) {
      objStyle.top  = 0;
      objStyle.left = 0;
      objStyle.position = 'static';

      // Hide the object bar.
      setTimeout('ayudaHideObjectBar("'+ objStyle.parent.id +'")', 400)
    }
    else {
      objStyle.top  = objStyle.origTop;
      objStyle.left = objStyle.origLeft;
    }
    
    // Flag that the move has been cancelled.
    objStyle.isMoveObjectCancelled = true;
  }
  
  UnregisterMoveObjects (null);
}

/*
// Assign the given property a value on mouse up.
function RegisterSetValueOnMouseUp (obj, property, value) {
  var item = new SetPropertyItem ();
  item.object   = obj;
  item.property = property;
  item.value    = value;
  GlobalSetValueOnMouseUp.push (item);
}

// Assign the given property a value on the next mouse move.
function RegisterSetValueOnceOnMouseMove (obj, property, value) {
  var item = new SetPropertyItem ();
  item.object   = obj;
  item.property = property;
  item.value    = value;
  GlobalSetValueOnceOnMouseMove.push (item);
}

// Set a property for an object.  This may only work for object styles.
function SetPropertyValue (item) {
  item.object[item.property] = item.value;
}

function SetPropertyItem (obj, property, value) {
  this.object   = obj;
  this.property = property;
  this.value    = value;
}
*/

/////////////////////////////////////////
// Object mouse functions.
/////////////////////////////////////////

var GlobalObjectMouseUpOnce = new Array ();

// Run all the functions awaiting a single mouse up event.
function ObjectMouseUpOnce (e) {
	if (!this.mouseUpOnceList) return false;

	// Run each registered function.
	while (this.mouseUpOnceList.length) {
		(this.mouseUpOnceList.shift()) (e, this);
	}
}

// Notify the object to run a function only once on a mouse up event.
function ObjectRegisterMouseUpOnce (f) {
  var obj = this;
  if (ObjectRegisterMouseUpOnce.arguments > 1) {
    obj = ObjectRegisterMouseUpOnce.arguments[1];
    ObjectInitializeMouse (obj);
  }

	// Make sure the list exists.
	if (!obj.mouseUpOnceList)
		obj.mouseUpOnceList = new Array ();

	// When a function is added for the first time, add the object to the list.
	if (!obj.mouseUpOnceList.length)
		GlobalObjectMouseUpOnce.push (obj);
		
	obj.mouseUpOnceList.push (f);
}

// Assign the mouse functions to the object.
function ObjectInitializeMouse (obj) {
	// See if the functions have already been registered.
	if (obj.registerMouseUpOnce ||
	    obj.mouseUpOnce)
		return false;
		
	// They have not.
	obj.registerMouseUpOnce = ObjectRegisterMouseUpOnce;
	obj.mouseUpOnce         = ObjectMouseUpOnce;
}

// End object mouse functions. //////////

// End mouse functions. /////////////////

///////////////////////////////////////////////////////////
// Key manipulation functions.
///////////////////////////////////////////////////////////

// Allow multiple key up event functions.
var GlobalKeyUps = new Array ();
function RegisterKeyUp (f) {
	GlobalKeyUps.push (f);
}

// Calls all the key up functions.
function OnKeyUp (e) {
	if (!e) e = event;

	for (var i=0; i<GlobalKeyUps.length; i++) {
		GlobalKeyUps[i] (e);
	}
	
	PageProps.keyUp = e.keyCode;
}

if (isIE) {
  document.attachEvent ('onkeyup', OnKeyUp);
}
else {
  document.addEventListener ('keyup', OnKeyUp, false);
}

// Allow multiple key down event functions.
var GlobalKeyDowns = new Array ();
function RegisterKeyDown (f) {
	GlobalKeyDowns.push (f);
}

// Calls all the key down functions.
function OnKeyDown (e) {
	if (!e) e = event;

	for (var i=0; i<GlobalKeyDowns.length; i++) {
		GlobalKeyDowns[i] (e);
	}
	
	PageProps.keyDown = e.keyCode;
}

if (isIE) {
  document.attachEvent ('onkeydown', OnKeyDown);
}
else {
  document.addEventListener ('keydown', OnKeyDown, false);
}

// Key manipulation functions. ////////////////////////////

///////////////////////////////////////////////////////////
// Event utility functions.
///////////////////////////////////////////////////////////

function ayudaAttachEvent (name, f) {
  if (!name || ! f) return false;
  
  if (isIE)
    return document.attachEvent ('on'+name, f);
  else
    return document.addEventListener (name, f, false);
}

// End: event utility functions. //////////////////////////

///////////////////////////////////////////////////////////
// Object manipulation functions.
///////////////////////////////////////////////////////////

// Hides an object after a successful callback.
function HideObjOnCallBack (reply) {
  if (!reply.success ())
    return;
  
  // Hide the given object.
  var id = null;
  if (id = reply.getValue ('ID'))
    HideObj (id);
}

function ShowObj (obj, x, y) {
	return SetObjVisibility (obj, true, x, y);
}

function HideObj (obj) {
	return SetObjVisibility (obj, false);
}

// Show or hide a DIV.
function SetObjVisibility (obj, vis, x, y) {
  var obj      = getObject (obj);
	var objStyle = getObjectStyle (obj);
	if (!objStyle) return false;

	// Show or hide the div.
	if (vis) {
	  objStyle.visibility = 'visible';
	  objStyle.display    = 'block';
	  
	  // Set the x,y coords.
	  if (x) objStyle.left = x;
	  if (y) objStyle.top  = y;
	  
	  // Keep track of the DIV's visibility for hiding Select boxes in IE.
	  PageProps.visibleDivs[obj.id] = true;
	}
	else {
	  objStyle.visibility = 'hidden';
	  objStyle.display    = 'none';
	  PageProps.visibleDivs[obj.id] = false;
	}

  // Need to hide the select boxes in IE so they don't appear over the DIVs.
  if (isIE && obj.tagName && 'div' == obj.tagName.toLowerCase ()) {	
	  // Hide the select boxes that might be in the way.
	  var hideSelect = false;
	  var hiddenCtr  = 0;
	  for (var v in PageProps.visibleDivs) {
	    if (PageProps.visibleDivs[v]) {
	      hideSelect = true;
	      hiddenCtr++;
	    }
	  }
	  if (hideSelect && 1 == hiddenCtr)
	    hideSelects (obj.id);
	  else if (!hideSelect)
	    showSelects (obj.id);
	}

	return true;
}

// Check the visibility of a DIV.
function IsDivVisible (div) {
  var objStyle = getObjectStyle (div);
  if (!objStyle) return false;
  if ("visible" == objStyle.visibility.toLowerCase())
    return true;
  else
    return false;
}

// Show the DIV slightly offset from the mouse cursor location.
function ShowDivAtMouse (div) {
  if (!(div = getObject (div))) return false;

  // Set default height and width.
  var width, height;
  var objStyle = getObjectStyle (div);
      
  // Find the default height and width.
  if (!(height = ShowDivAtMouse.arguments[1]))
    if (!(height = parseInt (objStyle.height)))
      height = 0;

  if (!(width = ShowDivAtMouse.arguments[2]))
    if (!(width = parseInt (objStyle.width)))
      width = 0;
      
  // Make one last effort to search the style sheets for a height and width.
  var style = null;
  if ((0 == height || 0 == width) && 
      (style = getStyleSheetStyle (div.className))) {
    height = parseInt (style.height);
    width  = parseInt (style.width);
  }

  var padding = 20;

  // The user may have resized the window.
  GetWindowSize ();

	// Do not let the PropertyDiv appear off the window.
	var x = PageProps.mouseX;
	var visibleX = PageProps.windowWidth - PageProps.mouseWindowX;
	if (width + padding > visibleX) {
		x -= width - visibleX + padding;
		
		if (x < 0) x = 0;
	}
	var y = PageProps.mouseY;
	var visibleY = PageProps.windowHeight - PageProps.mouseWindowY;
	if (height + padding > visibleY) {
	  y -= height - visibleY + padding;
	  
	  if (y < 0) y = 0;
	}

	SetDivPos  (div, x, y);
	ShowObj (div);
}

// Set the DIV position on the page.
function SetDivPos (div, x, y) {
	var objStyle = getObjectStyle (div);
	if (!objStyle)
		return false;
		
	objStyle.top  = y;
	objStyle.left = x;
}

// Set the height and width of a DIV.
function SetDivSize (div, height, width) {
	var objStyle = getObjectStyle (div);
	if (!objStyle)
		return false;
		
	objStyle.height = height;
	objStyle.width  = width;
}

// Change the css class of an object using an attribute stored in the object tag.
function ayudaSwitchClassNameFromAttribute (ID, attributeName) {
  var obj = getObject (ID);
  if (obj && obj.getAttribute) {                                // Handle objects without an object bar.
    var attrib = null;
    if (attrib = obj.getAttribute (attributeName))
      obj.className = attrib;
  }
}

// Change the css class of an object.
function ayudaSwitchClassName (ID, className) {
  var obj = getObject (ID);
  if (obj && obj.className) {                                // Handle objects without an object bar.
      obj.className = className;
  }
}

// End: Object manipulation functions. ////////////////////////

///////////////////////////////////////////////////////////
// Object finding functions.
///////////////////////////////////////////////////////////

function getObject (obj) {
  var newObj = null;
  if (typeof obj == 'string') {
    if (document.getElementById) {
      newObj = document.getElementById (obj);
      if (newObj)
        return newObj;
    }

		if (isIE) {   // IE won't find DIVs with a name attribute.
			newObj = findIEObject (obj);
			if (newObj)
				return newObj;
		}
		else {
			if (document.getElementsByName) {
				newObj = document.getElementsByName (obj);
				if (newObj.length > 0)
					return newObj.item(0);
			}
		}

    if (document.all)
      newObj = document.all (obj);

    return newObj;
  } 
  else {
    // pass through object reference
    return obj;
  }
}

// Find the object by name.  IE doesn't allow named DIVs.
function findIEObject (name) {
	var elements = document.getElementsByTagName ('div');
	for (var i=0; i<elements.length; i++) {
		var elName = elements[i].getAttribute ('name');
		if (elName == name)
			return elements[i];
	}
	
	return null;
}

// Return the style object for the current browser.
function getObjectStyle (obj) {
  obj = getObject (obj);
  if (!obj)
    return null;

  if (isIE || isDOM)
    return obj.style;
  else if (isNS)
    return obj;
  else
    return null;
}

// Gets a style object from a style sheet.
function getStyleSheetStyle (className) {
  // Search all the style sheets.  The last named rule trumps, so search from the end.
  for (var i=document.styleSheets.length-1; i>=0; i--) {
    var sheet = document.styleSheets[i];
    
    // IE uses rules, Mozilla uses cssRules.
    var rules = null;
    if (isIE)
      rules = sheet.rules;
    else
      rules = sheet.cssRules;
    
    // Search all the rules in the style sheet for a matching name.
    for (var j=rules.length-1; j>=0; j--) {
      var rule = rules[j];
      
      if (rule.selectorText == '.'+className)
        return rule.style;
    }
  }
  
  return null;
}

/////////////////////////


/////////////////////////////////////////////////////////////
// Initialization code run by every page.
/////////////////////////////////////////////////////////////

// Grab a handle to the parent window.
if (ayudaGetParentWindow ()) {
  // Set up the child.
  var parentWin = PageProps.pageLevel[0];
  if (parentWin.PageProps && parentWin.PageProps.childWindows) {
    // Determine the ID of the property being modified.
    var ID = null;
    
    // If this is a child window, it's possible the parent has the ID.
    if (top.PageProps.parentPageID)
      ID = top.PageProps.parentPageID;
    
    // This may be a top-level frame, so keep looking up the chain for the ID.
    if (!ID) {
      for (var win in parentWin.PageProps.childWindows) {
        if (top == parentWin.PageProps.childWindows[win]) {
          ID = win;
          break;
        }
      }
    }
    
    // This must be a property window.
    if (ID) {
      PageProps.parentPageID = ID;
      
      // Set the child window to notify the parent if it is closed.
      if (opener) {
        if (isIE)
          top.attachEvent ('onunload', ayudaTellRelativesDone);
        else 
          top.addEventListener ('unload', ayudaTellRelativesDone, false);
      }

      // Make sure this window has a title.
      if ('' == document.title)
        document.title = 'ID: ' + ID;
    }
  }
}

// End: initialization code. ////////////////////////////////

/////////////////////////////////////////////////////////////
// Functions called by child windows.
/////////////////////////////////////////////////////////////

// Find the nearest parent window.
function ayudaGetParentWindow () {
  var parent = null;
  // See if the window is a separate window.
  if (!(parent = opener) || opener.closed)
    // Is it an iframe?
    if ((parent = window.parent) == this)
      return false;
  
  var findParentLevel = parent;
  if (findParentLevel) {
    try {
      do {
        // Don't record iframe container windows with no interactive functionality.
        if (findParentLevel.PageProps &&
            findParentLevel.PageProps.pageLevel &&
            ((findParentLevel.PageProps.childWindows &&                    // Find the page that opened this window.
              findParentLevel.PageProps.childWindows.numChildren > 0) ||
             !top.opener))                                                 // This window may just be an IFrame in the top window.
          PageProps.pageLevel.push (findParentLevel);
      } while (findParentLevel.PageProps && (findParentLevel = findParentLevel.PageProps.pageLevel[0]));
    }
    catch (ex) {
      // Access denied to the parent: probably a different domain.
      PageProps.pageLevel.pop ();
    }
  }
  
  if (PageProps.pageLevel.length)
    return true;
  else
    return false;
}

// Inform the parent that this window is closing.
function ayudaTellRelativesDone () {
  // First close all the child windows.
  if (PageProps.childWindows && PageProps.childWindows.numChildren > 0) {
    // Make sure the other windows weren't closed prematurely.
    var childWindowFound = false;
    for (var win in PageProps.childWindows) {
      if (PageProps.childWindows[win] && !PageProps.childWindows[win].closed && PageProps.childWindows[win].document) {
        childWindowFound = true;
        break;
      }
    }
  
    // If a child window is still open, notify the user.
    if (childWindowFound && confirm ("This window has opened other windows.  Would you like to close them as well?")) {
      for (var win in PageProps.childWindows) {
        // Make sure the element is a window and not a property.
        if (!PageProps.childWindows[win].closed && PageProps.childWindows[win].document)
          PageProps.childWindows[win].close ();
      }
    }
    else {        // TODO: MJR - Cancel the window closing.  This doesn't seem to work - the window closes anyway.
      // Clean up the parent so it doesn't also try to close the children.
      if (this != top && top.PageProps.childWindows && top.PageProps.childWindows.numChildren > 0) {
        // This will prevent a "child window open" message and the memory will be cleaned up when the parent closes.
        top.PageProps.childWindows.numChildren = 0;
      }
      //return false;
    }
  }

  // Notify the parent of changes.
  if (PageProps && PageProps.pageLevel && PageProps.pageLevel[0] && !PageProps.pageLevel[0].closed && PageProps.pageLevel[0].ayudaCloseChildWindow) {
    PageProps.pageLevel[0].ayudaCloseChildWindow (PageProps.parentPageID);
  
    if (PageProps.reload)   // Refresh the parent window.  No need to clean up the child window resources as they are destroyed on the refresh anyway.
      PageProps.pageLevel[0].ayudaRefreshWindow ();
  }
  
  top.close ();

  return true;
}

// Show the bread crumb path to the parent windows.
function ayudaShowParentBreadCrumbs () {
  var obj = null;
  if (!(obj = getObject ('BreadCrumbMenu')) || !PageProps || !PageProps.pageLevel)
    return false;
    
  var text = '';
  
  // Create the menu structure.
  for (var i=PageProps.pageLevel.length-1; i>=0; i--) {
    var parent = PageProps.pageLevel[i];
    
    // Don't include empty frames (ie. container frames for other objects).
    if (!parent.PageProps.childWindows || parent.PageProps.childWindows.numChildren == 0)
      continue;
    
    // Get the parent title.
    var title = parent.document.title;
    if ('' == title)
      title = parent.document.location;
    
    // Create a link to the parent window.
    text += '<a href="javascript:void(0);" onClick="PageProps.pageLevel[\''+i+'\'].focus ();return false;">' + title + '</a> &gt; ';
  }
  
  // Finally, complete the menu by adding a reference to this window.
  text += document.title;
  
  // Display the text.
  obj.innerHTML = text;
  
  return true;
}

function ayudaPostBackIFrameLoaded() {
  // Alert that the post-back has completed the round trip.
  PageProps.downloadUrlComplete = true;
  
  var html;
  if (isIE)
    PageProps.postBackIFrame.body = document.frames("ayudaPostBackIFrame").document.body;
  else // Assuming Mozilla - need to make this work with all browsers!!
    PageProps.postBackIFrame.body = PageProps.postBackIFrame.contentDocument.body;
    
  html = PageProps.postBackIFrame.body.innerHTML;
  if (html) {
    html = html.replace(/&amp;/g, '&'); // Need to find an html decoder method
    var pckage = new Package(html);
    var userMessage = pckage.userMessage();
    if (userMessage)
      alert(userMessage);
    if (PageProps.downloadUrlCallbackFunction)
      PageProps.downloadUrlCallbackFunction(pckage, html); // the html in case they want to read it raw
    else
    {
      if (pckage.success () && pckage.reload ())
        ayudaRefreshWindow ();
    }
  }
  
  // Call the next command.
  ayudaCallNextPostBack ();
}

function ayudaShowPopupDiv (src, html) {
  var ayudaPopupDiv = getObject('ayudaPopupDiv');
  var ayudaPopupIframe = getObject('ayudaPopupIframe');
  var ayudaPopupLastSrc = getObject('ayudaPopupLastSrc');
  if (ayudaPopupDiv && ayudaPopupIframe && ayudaPopupLastSrc) {
    ayudaPopupDiv.style.display = 'inline';
    ayudaPopupDiv.style.top = PageProps.mouseDownY;
    ayudaPopupDiv.style.left = PageProps.mouseDownX;
    //ayudaPopupDiv.setActive();
    if (src != ayudaPopupLastSrc.value)
      ayudaPopupLastSrc.value = ayudaPopupIframe.src = src;
  }
}

function ayudaHidePopupDiv () {
  var ayudaPopupDiv = getObject('ayudaPopupDiv');
  if (ayudaPopupDiv)
    ayudaPopupDiv.style.display = 'none';
}


// Checks to see if there is another post-back command queued and, if so, runs it.
function ayudaCallNextPostBack () {
  if (PageProps.postBackQueue != null) {
    ayudaRunCommand (PageProps.postBackQueue.command, PageProps.postBackQueue.commandParameters, 
                     PageProps.postBackQueue.reload,  PageProps.postBackQueue.callbackFunction);
  }
  
  // Hide the wait message.
  ayudaDisplaySystemBusy (false);
}

function ayudaDownloadUrl(url, callbackFunction) {
  PageProps.downloadUrlCallbackFunction = callbackFunction;
  PageProps.postBackIFrame.src = url;
  //alert('test'); /// !!! For some bizzare reason, Mozilla doesn't work unless I have an alert here
}

function ayudaSetImageSize(image, maxHeight, maxWidth) {
  if (image && maxWidth && maxHeight) {
    if (image.height > image.width && image.height > maxHeight)
    {
      image.width = Math.round(image.width * maxHeight/image.height);
      image.height = maxHeight;
    }
    else if (image.width > maxWidth)
    {
      image.height = Math.round(image.height * maxWidth/image.width);
      image.width = maxWidth;
    }
    else if (image.width == 0 || image.height == 0)  // just in case, happens very rarely, but need to keep the images from being full size
    {
      image.height = maxHeight;
      image.width = maxWidth;
    }
  }
}

// Refresh the current window.
function ayudaRefreshWindow () {
//  PageProps.postBackIFrame.body.innerHTML = "";
//  alert (document.location.href);
  document.location = document.location.href;
}

function ayudaCloseOnSuccess(reply) {
  if (!reply.success())
    return;

  // If the child window needs to be refreshed, refresh the parent.
  if (reply.reload())
    PageProps.reload = true;

  ayudaTellRelativesDone ();
}

function ayudaOpenWindow (url, height, width) {
  // Get the screen size.  Who knows, the user may have changed it since we last checked.
  GetScreenSize ();
  
  // Position the window in the middle of the screen.
  var top = PageProps.screenHeight/2 - height/2;
  if (top < 0) top = 0;
  
  var left = PageProps.screenWidth/2 - width/2;
  if (left < 0) left = 0;

  return window.open (url, '_blank', 'scrollbars=yes,directories=no,location=no,menubar=no,status=no,toolbar=no,resizable=yes,height='+height+',width='+width+',top='+top+',left='+left);
}

function ayudaCloseWindow (reload) {
  if (reload)
    PageProps.reload = true;
  ayudaTellRelativesDone ();
}

// End: functions called by child windows. //////////////////

function AddElements(elementHash, elementList)
{
  if (!elementHash || !elementList)
    return;
  
  var elementName;
  for(var i=0; i<elementList.length; i++)
    if (elementList[i].name && elementList[i].name.substr(0,2) != '__')
    {
      elementName = elementList[i].name;
      elementHash[elementName.substring(elementName.lastIndexOf(':')+1)] = elementList[i];
    }
}

function SetPropertyValues(propertyValues)
{
  if (!propertyValues)
    return;
 
  var pckage = new Package(propertyValues, '');
  var elementsHash = new Object();
  AddElements(elementsHash, document.getElementsByTagName('input'));
  AddElements(elementsHash, document.getElementsByTagName('select'));
  AddElements(elementsHash, document.getElementsByTagName('textarea'));

  var count = pckage.getCount();
  for(var i=0; i<count; i++)
  {
    var propertyName = pckage.getName(i);
    var propertyValue = pckage.getValue(propertyName);
    if (!propertyValue)
      propertyValue = '';
    var element = elementsHash[propertyName];   // do we want to be case sensitive here???
    if (element)
    {
      if (element.setValue)
        element.setValue(propertyValue);
      else if (element.type == 'select-one')
      {
        // there's got to be a faster way to do this that works in all browsers
        var inList = false;
        var k = 0;
        while (k < element.options.length && !inList)
        {
          if (element.options[k].value == propertyValue);
            inList = true;
          k++;
        }
        if (!inList)
          element.options.add(new Option(propertyValue, propertyValue), 0);
        element.value = propertyValue;
      }
      else if (element.type == 'select-multiple')
        SetSelectedValues(element, propertyValue)
      else if (element.type == 'checkbox')
        element.setAttribute('checked', propertyValue.toLowerCase() == 'true');
      else
        element.value = propertyValue;
    }
  }
}

///////////////////////////////////////// BEGIN ENCODING SECTION /////////////////////////////////
//I (Brian) programmed these, so there are no license problems
function utf8Encrypt(s) {
  ret = Array();
  retIndex = 0;
  for(i=0; i<s.length; i++) {
    code = s.charCodeAt(i);
    if(code < 0x80) {
      ret[retIndex++] = code;
    }
    else if(code >= 0x80 && code < 0x800) {
      ret[retIndex++] = ((code >> 6) | 0xc0);
      ret[retIndex++] = ((code & 0x00003f) | 0x80);
    }
    else if(code >= 0x800 && code < 0x10000) {
      ret[retIndex++] = ((code >> 12) | 0xe0);
      ret[retIndex++] = (((code >> 6) & 0x00003f) | 0x80);
      ret[retIndex++] = ((code & 0x00003f) | 0x80);
    }
    else {
      if(code > 0x10FFFF)
        return "Error";
      ret[retIndex++] = ((code >> 18) | 0xf0);
      ret[retIndex++] = (((code >> 12) & 0x00003f) | 0x80);
      ret[retIndex++] = (((code >> 6) & 0x00003f) | 0x80);
      ret[retIndex++] = ((code & 0x00003f) | 0x80);  
    }    
  }
  return ret;
}

var b64Characters = new Array('A','B','C','D','E','F','G','H','I','J','K','L',
  'M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
  'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
  '0','1','2','3','4','5','6','7','8','9','+','/');
function b64EncryptBytes(bData) {
  var i=0;
  var b1,b2,b3;
  result = new Array();
  resultIndex = 0;
  blength = bData.length;
  while(i+3 <= blength) {
    b1 = bData[i++];
    b2 = bData[i++];
    b3 = bData[i++];
    result[resultIndex++] = b64Characters[b1 >> 2];
    result[resultIndex++] = b64Characters[ ((b1 << 4) & 0x30) | (b2 >> 4) ];
    result[resultIndex++] = b64Characters[ ((b2 << 2) & 0x3c) | (b3 >> 6) ];
    result[resultIndex++] = b64Characters[ b3 & 0x3f ];
  }
  if(i+1 == bData.length) {
    b1 = bData[i++];
    b2 = 0x00;
    result[resultIndex++] = b64Characters[b1 >> 2];
    result[resultIndex++] = b64Characters[ ((b1 << 4) & 0x30) | (b2 >> 4) ];
    result[resultIndex++] = "=";
    result[resultIndex++] = "=";
  } else if(i+2 == bData.length) {
    b1 = bData[i++];
    b2 = bData[i++];
    b3 = 0x00;
    result[resultIndex++] = b64Characters[b1 >> 2];
    result[resultIndex++] = b64Characters[ ((b1 << 4) & 0x30) | (b2 >> 4) ];
    result[resultIndex++] = b64Characters[ ((b2 << 2) & 0x3c) | (b3 >> 6) ];
    result[resultIndex++] = "=";
  }
  return result.join("");
}
///////////////////////////////////////// END ENCODING SECTION /////////////////////////////////
// End object finding functions. //////////////////////////

///////////////////////////////////////////////////////////
// Browser screen functions.
///////////////////////////////////////////////////////////

function GetWindowSize () {
  // Take into account the scroll bars.
  var offset = 25;
  
  if (isIE) {
    PageProps.windowWidth  = document.body.offsetWidth  - offset;
    PageProps.windowHeight = document.body.offsetHeight - offset;
  }
  else {
    PageProps.windowWidth  = window.innerWidth  - offset;
    PageProps.windowHeight = window.innerHeight - offset;
  }
}

function GetScreenSize () {
  PageProps.screenHeight = window.screen.availHeight;
  PageProps.screenWidth  = window.screen.availWidth;
}

// End browser screen functions. //////////////////////////

function GetCookie(sName)
{
  // cookies are separated by semicolons
  var aCookie = document.cookie.split("; ");
  for (var i=0; i < aCookie.length; i++)
  {
    if (0 == aCookie[i].indexOf(sName+"="))
      return (aCookie[i].substr(sName.length+1));
  }    
  // a cookie with the requested name does not exist
  return null;
}

function SetCookie (cookieName, cookieValue, nDays) {
 var today = new Date ();
 var expire = new Date ();
 if (nDays==null || nDays==0) nDays=1;
 
 expire.setTime(today.getTime() + 3600000*24*nDays);
 document.cookie = cookieName + "=" + escape (cookieValue) + ";expires=" + expire.toGMTString ();
}

function ayudaCanSetCookie () {
  // Attempt to set a cookie.
  SetCookie ('ayudaTestCookie', 'test', 1);
  if (GetCookie ('ayudaTestCookie') == null) {
    alert ('Cookies are not enabled.  Cookies are required to log in.');
    return false;
  }
  
  // Remove the cookie.
  SetCookie ('ayudaTestCookie', '', -1);

  return true;
}

function ayudaImportUrl(url, urlPrompt, namePrompt)
{
  url = prompt(urlPrompt, url);
  if (url) {
    var name = prompt(namePrompt, "name");
    if (name) {
        var params = new Package();
        params.addValue("url", url);
        params.addValue("name", name);
        ayudaRunCommand("ImportUrl", params);
    }
  }
}

// Sends a command in the background to the server.
// command:           Command(s) to send to the server.
// commandParameters: Package class containing all the name-value pairs.
// reload:            true to reload the window when the command returns.
// callbackFunction:  Function to call when the server returns from background processing.
function ayudaRunCommand(command, commandParameters, reload, callbackFunction)
{
 // Allow the reload and callbackFunction to be interchanged.
  if (typeof reload == "function") {
    var tempF = callbackFunction;
    callbackFunction = reload;
    reload = tempF;
  }
  
  // Don't run the command if a command is currently being processed.
  if (!PageProps.downloadUrlComplete) {
    // Alert the user that the system is busy.
    ayudaDisplaySystemBusy (true);
    
    // Queue the command.
    PageProps.postBackQueue = new Object ();
    PageProps.postBackQueue.command = command;
    PageProps.postBackQueue.commandParameters = commandParameters;
    PageProps.postBackQueue.reload = reload;
    PageProps.postBackQueue.callbackFunction = callbackFunction;
    return;
  }
  else {
    PageProps.downloadUrlComplete = false;
    PageProps.postBackQueue = null;
  }
  
  // Force reload to be a bool.
  reload = (reload == true);
  
  // Request a page reload.
  if (reload) {
    if (!commandParameters)
      commandParameters = new Package ();
    commandParameters.addValue ("reload", "true");
  }

  var form = getObject('ayudaForm');
  var url = form.CallbackUrl.value+'&Command='+command;
  var reloadPostBack = true;
  if (commandParameters) {  // Could check length before deciding to drop it to a cookie
    var params = commandParameters.pack(true);
    var length = params.length;
    if (length < 1000) { // just pass it on the query string is small enough (I think circa 2000 is limit)
      url += "&CommandParameters=" + encodeURIComponent(params);
    }
    else {
      // Create a form through which large amounts of data may be posted.
      var postBackDoc = null;
      if (isIE)
        postBackDoc = document.frames('ayudaPostBackIFrame').document;
      else
        postBackDoc = PageProps.postBackIFrame.contentDocument;
      
      // In order to post back there must be an actual page.
      var postBackPage = url;
      var pageIndex = -1;
      if ((pageIndex = postBackPage.indexOf ("/?")) >= 0) {
        postBackPage  = url.substring (0, pageIndex+1);
        postBackPage += "Default.aspx";
        postBackPage += url.substring (pageIndex+1);
      }
      
      // Create the form.
      var form = postBackDoc.createElement ('form');
      form.method = 'POST';
      form.action = postBackPage;
      
      // Create the CommandParameters input.
      var formCommandParameters = postBackDoc.createElement ('input');
      formCommandParameters.type = 'hidden';
      formCommandParameters.name = 'CommandParameters';
      formCommandParameters.value = params;
      
      // Assign the CallBackFunction.
      PageProps.downloadUrlCallbackFunction = callbackFunction;
      
      // Add the form and elements.
      form.appendChild (formCommandParameters);
      postBackDoc.body.appendChild (form);
      form.submit ();

      // Don't change the postBack source.  It was changed with the form.submit.
      reloadPostBack = false;
    }
  }
  
  if (reloadPostBack)
    ayudaDownloadUrl(url, callbackFunction);
}

// Inform the user that the system is busy.
function ayudaDisplaySystemBusy (display) {
  var obj = null;

  // Locate the system busy DIV.
  if (null == PageProps.divDisplaySystemBusy)
    obj = PageProps.divDisplaySystemBusy = getObject ('ayudaDisplaySystemBusy');
  else {
    obj = PageProps.divDisplaySystemBusy;
  }
  
  // Scroll the box with the window.
  var top = 0;
  var left = 0;
  if (isIE) {
    top = document.body.scrollTop;
    left = document.body.scrollLeft;
  }
  else {
    top = window.pageYOffset;
    left = window.pageXOffset;
  }
  
  // Show/Hide and position the DIV.
  SetObjVisibility (obj, display, left, top);
  
  // The animating image needs to be reloaded after the div has been hidden.
  if (display) {
    var imgObj = getObject ('ayudaDisplaySystemBusyImg').src;
    imgObj.src = imgObj.src;
  }
}

// Sends a command to the server by posting back the current page.
// command:           Command(s) to send to the server.
// commandParameters: Package class containing all the name-value pairs.
function ayudaPostCommand(command, commandParameters)
{
  var form = getObject('ayudaForm');
  form.Command.value = command + ',ViewPage';
  if (commandParameters)
    form.CommandParameters.value = commandParameters.pack(true);
  form.submit();
}

// Centralize the command to submit a form.
function ayudaSubmitPageForm () {
  var form = getObject ('ayudaForm');
  form.submit ();
}

function ayudaGetInputParameters()
{
  var pckage = new Package();
  var elementHash = new Object();
  AddElements(elementHash, document.getElementsByTagName('input'));
  AddElements(elementHash, document.getElementsByTagName('select'));
  AddElements(elementHash, document.getElementsByTagName('textarea'));
  for(var elementName in elementHash)
  {
    var element = elementHash[elementName];
    type = element.getAttribute('type', null);
    value = element.value;
    if (element.getValue)
      value = element.getValue();
    else if (type == 'checkbox')
      value = element.getAttribute('checked',null);
    else if (type == 'select-multiple')
      value = GetSelectedValues(element);
    else
      value = element.value;
    unitType = document.getElementById(element.name + '_UnitType');
    if (unitType && element.value.length > 0)
      value = value + unitType.value;
    pckage.addValue(elementName, value);
  }
  return pckage;
}

function GetSelectedValues(selectBox)
{
  selectedValues = '';
  for (var j=0; j<selectBox.options.length; j++)
  {
    var option = selectBox.options[j];
    if (option.selected)
      selectedValues += ',' + option.value;
  }
  if (selectedValues && selectedValues.length > 0)
    selectedValues = selectedValues.substring(1);
  return selectedValues;
}

function SetSelectedValues(selectBox, selectedValues)
{
  selectedValues = selectedValues.split(',');
  for (var j=0; j<selectBox.options.length; j++)
    for (var k=0; k<selectedValues.length; k++)
      if (selectBox.options[j].value == selectedValues[k])
        selectBox.options[j].selected = true;
}

/////////////////////////////////////////////////////////
// Functions for hiding groups of objects.
/////////////////////////////////////////////////////////

function showSelects (id) {
  setSelectVisibility (true, id);
}

function hideSelects (id) {
  setSelectVisibility (false, id);
}

// Show or hide all select boxes - in IE they interfere with layers.
function setSelectVisibility (show, id) {
  // TODO: This isn't working completely
  return;
	if(isIE) {
		var tags = document.all.tags("select");
		
    // Check each Select tag.
		for (var i=0; i<tags.length; i++) {
			var obj = tags[i];
			if(!obj || !obj.offsetParent) continue;

			// Keep track of all the parent ID's of which this Select tag is a member.
/*			if (!obj.parentIDs) {
			  obj.parentIDs = new Array ();
			  var parent    = obj.parentNode;
			  
			  while (parent != window) {
			    if (parent.id != "")
			      obj.parentIDs.push (parent.id);
			      
			    parent = parent.parentNode;
			  }
			}
			
			// Don't hide the Select if it is a child of the given ID.
*/			var found = false;
/*			if (id) {
			  for (var parentID in obj.parentIDs)
			    if (parentID == id)
			      found = true;
      }
*/      
			if (!found)
			  obj.style.visibility = (show) ? 'visible' : 'hidden';
  	}
	}
}

// End: Functions for hiding groups of objects. /////////

/////////////////////////////////////////////////////////
// Image manipulation functions.
/////////////////////////////////////////////////////////

function ayudaShowPng (src, alt, height, width, href, map) {
  document.write (ayudaShowImg (src, alt, height, width, href, map));
}

// Output the img tag for a PNG based on the browser.
function ayudaShowImg (src, alt, height, width, href, map) {
  var html = '';
  
  // Add an optional link.
  if (href != null)
    html += "<a href='" + href + "'>";
  
  // IE doesn't support PNGs, so fudge.
  if (isIE && ayudaGetExtension (src) == "png") {
    html += "<img src='/i/pixel.gif' style='border:none;width:"+width+";height:"+height+";filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\""+src+"\",sizingMethod=\"scale\");'";
  }
  else {
    html += "<img src='"+src+"' alt='"+alt+"' style='border:none;width:"+width+";height:"+height+";'";
  }
  
  // Allow image maps.
  if (map != null)
     html += " usemap='" + map + "'";
  
  // Close the IMG tag.
  html += ">";
  
  if (href != null)
    html += "</a>";
    
  return html;
}

// End: Image manipulation functions. ///////////////////


/////////////////////////////////////////////////////////
// File manipulation functions.
/////////////////////////////////////////////////////////

function ayudaGetExtension (filename) {
  return filename.substring (filename.lastIndexOf ('.')+1, filename.length).toLowerCase ();
}

// End: File manipulation functions. ///////////////////