
function MM_swapImgRestore() { //v3.0
  var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}

function MM_preloadImages() { //v3.0
  var d=document; if(d.images){
  if(!d.MM_p)
     d.MM_p=new Array();
    var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
    if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}

	/* This has nothing to do with loading images but it needs to happen
		during the onload so preview windows will pop to the front. This
		is just too much of a kludge. */
	window.self.focus();
}

function MM_findObj(n, d) { //v4.01
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
  if(!x && d.getElementById) x=d.getElementById(n); return x;
}

function MM_swapImage() { //v3.0
  var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
   if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
}

function MM_openBrWindow(theURL,winName,features) { //v2.0
  window.open(theURL,winName,features);
}

function MM_openBrWindowIncludeRef(theURL,winName,features) { //v2.0
  msgWin = window.open(theURL,winName,features);
  return msgWin;
}


/*
	Just like MM_openBrWindow() only this one returns False
	so it can be used in a form button. In addition it has
	a default window features string so that parameter is
	optional.
*/
function newWindowButton(theURL, winName, winFeatures) {
	if (!winFeatures) {
		winFeatures = "directories=yes,location=yes,menubar=yes,resizable=yes,scrollbars=yes,toolbar=yes";
	}
	window.open(theURL,winName,winFeatures);
	return false;
}

function URLEncode(str)
{
	var ms = "%25#23 20?3F<3C>3E{7B}7D[5B]5D|7C^5E~7E`60+2B";
	var msi = 0;
	var i,c,rs,ts;
	while (msi < ms.length)
	{
		c = ms.charAt(msi);
		rs = ms.substring(++msi, msi +2);
		msi += 2;
		i = 0;
		while (true)
		{
			i = str.indexOf(c, i);
			if (i == -1)
            break;
			ts = str.substring(0, i);
			str = ts + "%" + rs + str.substring(++i, str.length);
		}
	}
	return str
}


// This function provides the same conversion as that obtained from
// java.net.URLEncoder.encode().  The function converts a string into
// the x-www-form-urlencoded MIME format.
//
// To convert the string, each character is examined in turn:
//
//     o The ASCII characters 'a' through 'z', 'A' through 'Z',
//       '0' through '9', and '.', '-', '*', '_' remain the same.
//     o The space character (' ') is converted into a plus sign ('+').
//     o All other characters are converted into the 3-character string
//       %XY, where XY is the two-digit hexadecimal representation of the
//       lower 8-bits of the character.
//
// NB: The list of characters that are not encoded have been determined by
//     referencing O'Reilly's "HTML: The Definitive Guide" (page 164).
//
// The implementation is derived from that found at
// <http://summerholiday.org/freecode/JavaScript_URL_Encode.html>
// (which appears to share significant DNA with the code at
// <http://www.blooberry.com/indexdot/html/topics/urlencoding.htm>).
//
function URLEncodeParamValue (paramValue)
{
        var len       = paramValue.length;
        var i         = 0;
        var newStr    = "";
        var paramChar = "";
        for (i=0;i<len;i++)
        {
                paramChar = paramValue.substring (i, i + 1);
                if (isUrlOK (paramChar))
                {
                        newStr = newStr + paramChar;
                }
                else if (paramChar.charCodeAt(0) == 32)
                {
                	newStr = newStr + "+";
                }
                else
                {
                        tval1 = paramChar;
                        newStr = newStr + "%" + decToHex (tval1.charCodeAt(0), 16);
                }
        }
	return newStr;
}

// part of URLEncodeParamValue()
var hexVals = new Array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F");
function decToHex(num, radix)
{
        var hexString = "";
        while (num >= radix)
        {
               temp = num % radix;
               num = Math.floor(num / radix);
               hexString += hexVals[temp];
        }
        hexString += hexVals[num];
        return reversal(hexString);
}

// part of URLEncodeParamValue()
function reversal (s)
{
        var len = s.length;
        var trans = "";
        for (i=0; i<len; i++)
        {
                trans = trans + s.substring(len-i-1, len-i);
        }
        s = trans;
        return s;
}

// part of URLEncodeParamValue()
function isUrlOK(compareChar)
{
	var charCode = compareChar.charCodeAt(0);
        if ((charCode >= 97 && charCode <= 122)		// 'a'-'z'
            || (charCode >= 65 && charCode <= 90)	// 'A'-'Z'
            || (charCode >= 48 && charCode <= 57)	// '0'-'9'
            || charCode == 46				// '.'
            || charCode == 45				// '-'
            || charCode == 95				// '_'
            || charCode == 42)				// '*'
        {
                return true;
        }
        else
        {
                return false;
        }
}


/*
	Limit the size of a text area.
	limitArea should be called form onKeyUp.
	textAreaID should be sent as a JavaScript this self-referent.
	lengthLimit is an integer.
	warningText is optional but should be specified as an M0 or M1 tag.
		global.properties has a nice default message key - text_size_warning.
*/
function limitArea(textAreaID, lengthLimit, warningText) {
	if (!lengthLimit) { lengthLimit = 255; }
	if (!warningText) { warningText = "This text area has a limit of " + lengthLimit + " characters."; }
	currentString = new String(textAreaID.value);
	if (currentString.length > lengthLimit) {
		alert(warningText);
		textAreaID.value = currentString.substr(0, lengthLimit);
	}
}

/*
	Tell if I'm being rendered in the browser I expect.
	If I spec a platform tell me that too (versionPlatform
	is optional). Platform values are Win32, Win16, Mac68k,
	MacPPC and various Unix.
*/
function isNS(versionNumber, versionPlatform) {
	if (versionPlatform) {
		return (navigator.appName.indexOf("Netscape") > -1) & (parseInt(navigator.appVersion) >= versionNumber) & (navigator.platform.indexOf(versionPlatform) > -1);
	} else {
		return (navigator.appName.indexOf("Netscape") > -1) & (parseInt(navigator.appVersion) >= versionNumber);
	}
}


function isIE(versionNumber, versionPlatform) {
	if (versionPlatform) {
		return (navigator.appName.indexOf("Microsoft") > -1) & (parseInt(navigator.appVersion) >= versionNumber) & (navigator.platform.indexOf(versionPlatform) > -1);;
	} else {
		return (navigator.appName.indexOf("Microsoft") > -1) & (parseInt(navigator.appVersion) >= versionNumber);
	}
}

/* find all the checkboxes in form formname that have checkname in their id and set
	their checked property to val */
function SetChecked(formname, checkname, val) {
	dml = document[formname];
	len = dml.elements.length;
	var i=0;
	for( i=0 ; i<len ; i++) {
		if (dml.elements[i].type == 'checkbox' &&
				dml.elements[i].name.indexOf(checkname) >= 0) {
			dml.elements[i].checked=val;
		}
	}
}

function fixSSN(textObject) {
	var ssnString    = textObject.value;
	var returnString = "";
	var re           = new RegExp("([0-9]{9})");

	if (re.test(ssnString)) {

		returnString = ssnString.substring(0, 3) + "-" +
			ssnString.substring(3, 5) + "-" +
			ssnString.substring(5, 9);

		textObject.value = returnString;

	}
}


function chkZipCode(objName)
{
	var checkOK = "0123456789";
	var checkStr = objName;
	var allValid = true;
	var decPoints = 0;
	var allNum = "";

	if (checkStr.value.length < 5) {
		alertsay = "Please enter a 5 digit ZIP code or a ZIP+4 code in the format nnnnn-nnnn.";
		allValid = false;
	}
 	else if (checkStr.value.length > 5 && checkStr.value.length != 10) {
		alertsay = "Please enter a 5 digit ZIP code or a ZIP+4 code in the format nnnnn-nnnn.";
		allValid = false;
	}

	if (allValid) {
		for (i = 0;  i < 5;  i++)
		{
			ch = checkStr.value.charAt(i);
			for (j = 0;  j < checkOK.length;  j++)
				if (ch == checkOK.charAt(j))
					break;
			if (j == checkOK.length)
			{
				allValid = false;
				alertsay = "ZIP code must be numeric.";
				break;
			}
		}
		if (allValid && checkStr.value.length > 5) {
			if (checkStr.value.charAt(5) != "-") {
				allValid = false;
				alertsay = "ZIP+4 must be in the format nnnnn-nnnn.";
			}
			else if (checkStr.value.substring(6, 10) == "0000") {
				allValid = false;
				alertsay = "0000 is not a valid ZIP+4 extension.";
			}
			else {
				for (i = 6;  i < 10;  i++)
				{
					ch = checkStr.value.charAt(i);
					for (j = 0;  j < checkOK.length;  j++)
						if (ch == checkOK.charAt(j))
							break;
					if (j == checkOK.length)
					{
						allValid = false;
						alertsay = "ZIP+4 must be numeric.";
						break;
					}
				}
			}
		}
	}
	if (!allValid)
	{
		alert(alertsay);
		return (false);
	}
	return (true);
}


// If the user hits 'OK' on the confirm panel,
// fetches a popup from the server, refreshing the
// users session
function keepAlive(logoutWarning, confirmURL)
{

	if (confirm(logoutWarning)) {
		msgWin = MM_openBrWindowIncludeRef(confirmURL, '', 'scrollbars=no,resizable=no,alwaysRaised=yes,dependent=yes,width=1,height=1');
      if (msgWin != null)
         msgWin.close();

		resetTimeout();
    }
}


function forceKeepAlive(confirmURL)
{
	msgWin = MM_openBrWindowIncludeRef(confirmURL, '', 'scrollbars=no,resizable=no,alwaysLowered=yes,dependent=yes,width=1,height=1');
	msgWin.close();
        // Uncomment the line below to make this last forever.
	// resetTimeout();
}


/*
appends the given param/val pair to the given original url
*/

function appendToUrl (original, param, val)
{
	var url = new String (original);
	var sep ="";

	if (url.indexOf("?") == -1)
      sep= "?";
	else
      sep= "&";

	return url.valueOf() + sep + param + "=" + val;
}

// If you permform multiple validation steps in an onSubmit event handler,
// then it is important to call submitOnce() last because it sets an internally
// used flag that indicates that the form has been submitted.
// Otherwise, calling submitOnce() might set _submitOnce=true and then some
// other validation might return false (which aborts the form submission).
// But then the FORM could not be submitted again because _submitOnce==true.
var _submitOnce = false;

function submitOnce(msg)
{
  if (_submitOnce) {
    alert(msg);
    return false;
  }
  else {
    _submitOnce = true;
    return true;
  }
}

function submitEnter(mybutton,e)
{
	var keycode;

	if (window.event)
		keycode = window.event.keyCode;
	else if (e)
		keycode = e.which;
	else
		return true;

	if (keycode == 13) {
		mybutton.click();
		return false;
	}
	else
		return true;
}

// returns the currently selected option of a SELECT element.
function getOptionSelection (formName, selectName)
{
	var selList = null;

	if (document.getElementById)
		selList = document.getElementById (selectName);
	else if (formName)
		selList = document.forms[formName].elements[selectName];

  return (selList != null) ? selList.options[selList.selectedIndex].value : null;
}

//
// The functions below can be used to make embedded surveys
// change the choices as you fill out the questions.
//

function choiceSelected(question, choice) {
   return true;
}


function relateQuestion(formName, question, question2, choice, optionList) {


   // Array offsets of values in Array optionList

   memberOf		= 0;
   sTag			= 1;
   optionLabel		= 2;

   var optionListCounter = 0;
   var selectListCounter = 0;

   // clear the old options
   for (optionListCounter = document.forms[formName].elements[question].options.length - 1; optionListCounter >= 0 ; optionListCounter--) {
      document.forms[formName].elements[question].options[optionListCounter] = null;
   }

   // set the new options
   for (optionListCounter = 0; optionListCounter < optionList.length; optionListCounter++) {
      if (optionList[optionListCounter][memberOf] == choice) {
         var newoption = new Option(optionList[optionListCounter][optionLabel], optionList[optionListCounter][sTag]);
         document.forms[formName].elements[question2].options[selectListCounter++] = newoption;
      }
   }

   // set selected element
   document.forms[formName].elements[question].options[0].selected = true;

   // refresh if necessary
   if (navigator.appName == 'Netscape' && parseInt(navigator.appVersion) < 5) {
      history.go(0);
   }
}

// The lc_* functions support the list component ability to hide or show columns.
// As soon as all customized page wrappers get upgraded to 3.8, then this section
// (which is duplicated in admin_wrapper.js) should be separated out into a new
// 'list_component.js' file.

// The lcColFilter objects are created in the template for each table
// and have information specific to each instance.
function lcColFilter (table_id, param_name, hidden_cols, has_extra_col) {
   this.tableId = table_id;
   this.paramName = param_name;
   this.hiddenCols = (hidden_cols != null) ? hidden_cols.split ('_') : new String[0];
   this.hasExtraCol = has_extra_col;
}

// This is the main entry point to hide or show a column.
// It can be called in response to users' actions.
//
//    colFilter is the lcColFilter instance for the table
//    origin is the element within the table initiating the invocation
//    colNum is the index of the column to be hidden or shown
//    hideIt indicates whether to hide or show the column
function lc_hideOrShowCol (colFilter, origin, colNum, hideIt) {
   var table = null;
   var parent = origin;

   if ((colNum == null) || (colNum == ''))
      return;

   if (hideIt == null)
      hideIt = true;

   // Search up the DOM to find enclosing lc_Table
   while ((parent != null) && (table == null)) {
      if (parent.nodeName == 'TABLE') {
         var att = parent.attributes;
         var cls = (att != null) ? att.getNamedItem ('class') : null;

         if ((cls != null) && (cls.nodeValue == 'lc_Table'))
            table = parent;
         else
            parent = parent.parentNode;
      }
      else
         parent = parent.parentNode;
   }

   // If table not found, look for it by ID.
   if (table == null) {
      table = document.getElementById (colFilter.tableId);
   }

   // If the table was found, hide or show the column
   if (table != null) {

      // column header
      var ths = table.getElementsByTagName ('TH');
      var hdrNum = (colNum * 2);

      if (colFilter.hasExtraCol)
         hdrNum--;

      lc_hideOrShowNode (ths, hdrNum, hideIt);
      lc_toggleHdr (ths, (hdrNum + 1), hideIt);

      // I first found the TDs to hide by going through the rows, getting the
      // array of TDs for each row, and then invoking the lc_hideOrShowNode
      // method using the colNum index.  But that failed with IE6 on the initial
      // load of the page (it worked when the user clicked on the hide or show
      // icons).
      // So this approach of getting all TDs and finding the appropriate ones
      // based on their ID fixed that.
      var tds = table.getElementsByTagName ('TD');
      var cellIdRegex = 'lc_cell_[0-9]*_' + colNum;

      for (var t = 0; t < tds.length; t++) {
         var td = tds.item(t);

         if (td != null) {
            var tdAttrs = td.attributes;

            if (tdAttrs != null) {
               var idAttr = (tdAttrs != null) ? tdAttrs.getNamedItem ('id') : null;

               if ((idAttr != null) && (idAttr.value != null) && idAttr.value.match (cellIdRegex))
                  lc_hideOrShowNode (tds, t, hideIt);
            }
         }
      }

      // Update the variables that track which columns are hidden.
      // Also update any links in the page that contain the column filter.
      if (hideIt) {
         var found = false;

         // First, make sure it isn't already in the list of hidden columns.
         // It shouldn't be, but this helps prevent unnecessary processing.
         for (var c = 0; ((found == false) && (c < colFilter.hiddenCols .length)); c++) {
            if (colFilter.hiddenCols[c] == colNum)
               found = true;
         }

         if (found == false) {
            colFilter.hiddenCols[colFilter.hiddenCols.length] = colNum;
            lc_update_filter_in_links (colFilter.paramName, colFilter.hiddenCols);
         }
      }
      // Show the column (remove it from the filter)
      else {
         // Remove all references to this column number in the list of hidden
         // columns.  There should just be one.
         for (var c = 0; (c < colFilter.hiddenCols .length); ) {
            if (colFilter.hiddenCols[c] == colNum)
               colFilter.hiddenCols.splice (c, 1);
            else
               c++;
         }

         lc_update_filter_in_links (colFilter.paramName, colFilter.hiddenCols);
      }
   }
}

// This method updates the visual elements in the column header to reflect
// the new state (shown / hidden) of the column.
//   hdrList is a list of all header items.
//   hdrNum is the index of the header item to be changed.
//   hideIt indicates whether the column is being hidden or shown.
function lc_toggleHdr (hdrList, hdrNum, hideIt) {
   if (hdrList.length > hdrNum) {
      var hdr = hdrList.item(hdrNum);

      if (hdr != null) {
         // This is a dependency on list_component_header.tpt.
         // The hide / show images are within anchors ('<a ...>') to trick
         // NS & Mozilla into rendering their ALT text as fly-over text.
         var imgs = hdr.getElementsByTagName ('A');

         for (var i = 0; (i < imgs.length); i++) {
            var img = imgs.item(i);

            if (img != null) {
               // When hiding, show the link/image for showing and hide everything else.
               var name = img.getAttribute ('name');

               if ((name != null) && (name == 'lc_open')) {
                  if (hideIt)
                     lc_showNode (img);
                  else
                     lc_hideNode (img);
               }
               // When showing, hide the link/image for showing and show everything else.
               else {
                  if (hideIt)
                     lc_hideNode (img);
                  else
                     lc_showNode (img);
               }
            }
         }
      }
   }
}

// This method hides or shows a DOM node by hiding or showing all of the
// children of the node.  The node itself is not changed so that its
// background, borders, etc. are not removed.
//   nodeList is a list of all nodes.
//   nodeNum is the index of the node to be changed.
//   hideIt indicates whether the column is being hidden or shown.
function lc_hideOrShowNode (nodeList, nodeNum, hideIt) {
   if (nodeList.length > nodeNum) {
      var node = nodeList.item(nodeNum);

      if (node != null) {
         var children = node.childNodes;

         for (var n = 0; n < children.length; n++) {
            var child = children.item(n);

            if (child != null) {
               var attrs = child.attributes;
               var attrClass = (attrs != null) ? attrs.getNamedItem ('class') : null;

               if ((attrClass != null) && (attrClass.nodeValue == 'lc_empty')) {
                  if (hideIt)
                     lc_showNode (child);
                  else
                     lc_hideNode (child);
               }
               else {
                  if (hideIt)
                     lc_hideNode (child);
                  else
                     lc_showNode (child);
               }
            }
         }
      }
   }
}

// This hides a node by setting its 'display' style to 'none'.
function lc_hideNode (node) {
   if ((node != null) && (node.style != null)) {
      if ((node.style.display == null) || (node.style.display == ''))
         node.style.display = 'none';
   }
}

// This shows a node by setting its 'display' style to '' if it is 'none'.
function lc_showNode (node) {
   if ((node != null) && (node.style != null)) {
      if (node.style.display == 'none')
         node.style.display = '';
   }
}

// This method updates all links in the page that contain the column filter
// parameter.
// It also updates the similarly named hidden field, if it exists.
function lc_update_filter_in_links (param_name, col_f_array) {
   var links = document.getElementsByTagName ('A');
   var regex = new RegExp ("(" + param_name + "=)[0-9_]*");
   var filter_string = col_f_array.join ('_');

   for (var a = 0; (a < links.length); a++) {
      var href = links[a].getAttribute ('HREF');

      if (href != null) {
         // If the filter parameter is already in the URL,
         // then change its value.
         if (href.match (regex))
            href = href.replace (regex, '$1' + filter_string);

         // otherwise, add the parameter and value to the URL
         else if (href.match ('^http'))
            href = appendToUrl (href, param_name, filter_string);
         else
            href = null;

         // Mozilla doesn't care about case, but IE6 seems to.
         if (href != null) {
            links[a].setAttribute ('HREF', href);
            links[a].setAttribute ('href', href);
         }
      }
   }

   // Update the hidden field
   var hidden = document.getElementById (param_name);

   if (hidden != null) {
      hidden.value = filter_string;
   }
}

// This method is for initializing the columns according to the current
// filter.  It assumes that all columns are displayed and only takes action
// to hide the ones that are supposed to be hidden.
function lc_init_cols (colFilter) {
   if (colFilter.hiddenCols != null) {
      var tbl = document.getElementById (colFilter.tableId);

      for (var c = 0; (c < colFilter.hiddenCols .length); c++) {
         lc_hideOrShowCol (colFilter, tbl, colFilter.hiddenCols[c], true);
      }
   }
}

// Returns the HTML for the expand/collapse images to be inserted into the
// document.
function lc_write_toggle_images (openTitle, closeTitle, filterSuffix, columnNumber) {
   var str = '';

   // the anchors around the images are a trick to make NS render the tool tips -->
   if (openTitle != null) {
      str += '<a name="lc_open" title="'
             + openTitle
             + '" style="display: none;"><img src="../images/open_pane2.gif" border="0" alt="'
             + openTitle
             + '" onClick="lc_hideOrShowCol(lc_col_filter_'
             + filterSuffix
             + ', this, '
             + columnNumber
             + ', false); return false;" /></a>\n';
   }

   if (closeTitle != null) {
      str += '<a name="lc_close" title="'
            + closeTitle
            + '"><img src="../images/close_pane2.gif" border="0" alt="'
            + closeTitle
            + '" onClick="lc_hideOrShowCol(lc_col_filter_'
            + filterSuffix
            + ', this, '
            + columnNumber
            + ', true); return false;" /></a>\n';
   }

   return str;
}
