/**
 * Name: common.js
 * Version: 1.9.0
 * Description: Contains utility methods that can be used across multiple websites.
 */
var focusField = null;
var NS4 = (document.layers) ? 1 : 0;
var IE4 = (document.all) ? 1 : 0;
var W3C = (document.getElementById) ? 1 : 0;

var MONTH_NAMES = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
var MSG_PLEASE_FILL = "Please fill in or change the required fields (marked with a red asterix)";

/**
 * Allow string instances to be trimmed using a prototype method.
 * i.e. " test ".trim() == "test"
 */
String.prototype.trim = function() { return this.replace(/^\s*|\s*$/g, ""); };

/**
 * NOTE: This method requires the inclusion of the "browser_sniffer.js" javascript library
 */
function browserHasCalendarZindexIssues() {
	return ( is_ie && is_major <= 6 );
}

function setElementFocus(sElement) {
	var obj = getElement(sElement);
	if( obj != null ) {
		obj.focus();
	}
}

/**
 * Redirects the user to the given URL.
 * @param url the URL to redirect the user to
 */
function redirect(url) {
  window.location.href = url;
}

function wasEnterKeyPressed(e) {
	var keycode = null;
	if (window.event) keycode = window.event.keyCode;
	else if( e ) keycode = e.which;
	return ( keycode != null && keycode == 13 ) ;
}

function submitFormWithEnter(myfield, e) {
	var keycode;
	if (window.event) keycode = window.event.keyCode;
	else if( e ) keycode = e.which;
	else return true;
	if( keycode == 13 ) {
		 myfield.form.submit();
		 return false;
	} else return true;
}


/**
 * Submits the form with the given ID.
 * @param formId the ID of the form to be submitted
 */
function submitForm(formId) {
	if( formId == null ) formId = "form";
	document.forms[formId].submit();
}

function resetForm(formId) {
	if( formId == null ) formId = "form";
	document.forms[formId].reset();
}

function enforceTextareaMaxlength(textAreaObj, remainingCharCountSpan) {
	var mlength = (textAreaObj.getAttribute ? parseInt(textAreaObj.getAttribute("maxlength")) : "");
	if( textAreaObj.getAttribute && textAreaObj.value.length > mlength ) {
		textAreaObj.value = textAreaObj.value.substring(0, mlength);
	}
	if( remainingCharCountSpan != null ) {
		setInnerHTML(remainingCharCountSpan, mlength - textAreaObj.value.length);
	}
}

/**
function highlightRow(oRow, sColor) {
	oRow.style.background = sColor;
}

function highlightRowUsingStyle(oRow, sStyle) {
	oRow.className = sStyle;
}
*/

var marked_row = new Array();

/**
 * Highlights table rows for different states (mouseover, mouseout, mouseclick, etc).
 * @param   theRow          object   the table row
 * @param   theRowNum       integer  the row number
 * @param   theAction       string   the action calling this script (over, out or click)
 * @param   theDefaultColor string   the default background color
 * @param   thePointerColor string   the color to use for mouseover
 * @param   theMarkColor    string   the color to use for marking a row
 * @return  boolean         whether row is highlighted or not
 */
function highlightRow(theRow, theRowNum, theAction, theDefaultColor, thePointerColor, theMarkColor) {
  var theCells = null;
  
  // 1. Pointer and mark feature are disabled or the browser can't get the
  //    row -> exits
  if( (thePointerColor == '' && theMarkColor == '') || typeof(theRow.style) == 'undefined' ) {
    return false;
  }
  
  // 2. Gets the current row and exits if the browser can't get it
  if( typeof(document.getElementsByTagName) != 'undefined' ) {
    theCells = theRow.getElementsByTagName('td');
  } else if( typeof(theRow.cells) != 'undefined' ) {
    theCells = theRow.cells;
  } else {
    return false;
  }
  
  // 3. Gets the current color...
  var rowCellsCnt  = theCells.length;
  var domDetect    = null;
  var currentColor = theCells[0].style.backgroundColor;
  var newColor     = null;
  
  // 3.3 ... Opera changes colors set via HTML to rgb(r,g,b) format so fix it
  if( currentColor.indexOf("rgb") >= 0 ) {
    var rgbStr = currentColor.slice(currentColor.indexOf('(') + 1, currentColor.indexOf(')'));
    var rgbValues = rgbStr.split(",");
    currentColor = "#";
    var hexChars = "0123456789ABCDEF";
    for( var i = 0; i < 3; i++ ) {
      var v = rgbValues[i].valueOf();
      currentColor += hexChars.charAt(v/16) + hexChars.charAt(v%16);
    }
  }
  
  // 4. Defines the new color
  // 4.1 Current color is the default one
  if( currentColor == '' || currentColor.toLowerCase() == theDefaultColor.toLowerCase() ) {
    if( theAction == 'over' && thePointerColor != '' ) {
      newColor = thePointerColor;
    } else if( theAction == 'click' && theMarkColor != '' ) {
      newColor = theMarkColor;
      marked_row[theRowNum] = true;
      // Garvin: deactivated onclick marking of the checkbox because it's also executed
      // when an action (like edit/delete) on a single item is performed. Then the checkbox
      // would get deactived, even though we need it activated. Maybe there is a way
      // to detect if the row was clicked, and not an item therein...
      // document.getElementById('id_rows_to_delete' + theRowNum).checked = true;
    }
  }
  // 4.1.2 Current color is the pointer one
  else if( currentColor.toLowerCase() == thePointerColor.toLowerCase()
        && (typeof(marked_row[theRowNum]) == 'undefined' || !marked_row[theRowNum]) ) {
    if( theAction == 'out' ) {
      newColor = theDefaultColor;
    } else if( theAction == 'click' && theMarkColor != '' ) {
      newColor = theMarkColor;
      marked_row[theRowNum] = true;
      // document.getElementById('id_rows_to_delete' + theRowNum).checked = true;
    }
  }
  // 4.1.3 Current color is the marker one
  else if( currentColor.toLowerCase() == theMarkColor.toLowerCase() ) {
    if( theAction == 'click' ) {
      newColor = (thePointerColor != '' ? thePointerColor : theDefaultColor);
      marked_row[theRowNum] = 
      	((typeof(marked_row[theRowNum]) == 'undefined' || !marked_row[theRowNum]) ? true : null);
      // document.getElementById('id_rows_to_delete' + theRowNum).checked = false;
    }
  } // end 4
  
  // 5. Sets the new color...
  var c = null;
  if( newColor != null ) {
    // 5.1 ... with DOM compatible browsers except Opera
    if( domDetect ) {
      for( var c = 0; c < rowCellsCnt; c++ ) {
        theCells[c].setAttribute('bgcolor', newColor, 0);
      } // end for
    }
    // 5.2 ... with other browsers
    else {
      for( var c = 0; c < rowCellsCnt; c++ ) {
        theCells[c].style.backgroundColor = newColor;
      }
    }
  }
  
  return true;
}

/**
 * Highlights table rows for different states (mouseover, mouseout, mouseclick, etc) using CSS styles.
 * @param   theRow          object   the table row
 * @param   theRowNum       integer  the row number
 * @param   theAction       string   the action calling this script (over, out or click)
 * @param   theDefaultStyle string   the default style (for mouseout)
 * @param   thePointerStyle string   the style to use for mouseover
 * @param   theMarkStyle    string   the style to use for marking a row
 * @return  boolean         whether row is highlighted or not
 */
function highlightRowUsingStyle(theRow, theRowNum, theAction, theDefaultStyle, thePointerStyle, theMarkStyle) {
  var theCells = null;
  
  // 1. Pointer and mark feature are disabled or the browser can't get the
  //    row -> exits
  if( (thePointerStyle == '' && theMarkStyle == '') || typeof(theRow.style) == 'undefined' ) {
    return false;
  }

  // 2. Gets the current row and exits if the browser can't get it
  if( typeof(document.getElementsByTagName) != 'undefined' ) {
    theCells = theRow.getElementsByTagName('td');
  } else if( typeof(theRow.cells) != 'undefined' ) {
    theCells = theRow.cells;
  } else {
    return false;
  }
  
  // 3. Gets the current color...
  var rowCellsCnt  = theCells.length;
  var domDetect    = null;
  var currentStyle = theCells[0].className;//style.backgroundColor;
  var newStyle     = null;
  
  // 4. Defines the new color
  // 4.1 Current color is the default one
  if( currentStyle == '' || currentStyle.toLowerCase() == theDefaultStyle.toLowerCase() ) {
    if( theAction == 'over' && thePointerStyle != '' ) {
      newStyle = thePointerStyle;
    } else if( theAction == 'click' && theMarkStyle != '' ) {
      newStyle = theMarkStyle;
      marked_row[theRowNum] = true;
      // Garvin: deactivated onclick marking of the checkbox because it's also executed
      // when an action (like edit/delete) on a single item is performed. Then the checkbox
      // would get deactived, even though we need it activated. Maybe there is a way
      // to detect if the row was clicked, and not an item therein...
      // document.getElementById('id_rows_to_delete' + theRowNum).checked = true;
    }
  }
  // 4.1.2 Current color is the pointer one
  else if( currentStyle.toLowerCase() == thePointerStyle.toLowerCase()
        && (typeof(marked_row[theRowNum]) == 'undefined' || !marked_row[theRowNum]) ) {
    if( theAction == 'out' ) {
      newStyle = theDefaultStyle;
    } else if( theAction == 'click' && theMarkStyle != '' ) {
      newStyle = theMarkStyle;
      marked_row[theRowNum] = true;
      // document.getElementById('id_rows_to_delete' + theRowNum).checked = true;
    }
  }
  // 4.1.3 Current color is the marker one
  else if( currentStyle.toLowerCase() == theMarkStyle.toLowerCase() ) {
    if( theAction == 'click' ) {
      newStyle = (thePointerStyle != '' ? thePointerStyle : theDefaultStyle);
      marked_row[theRowNum] = 
      	((typeof(marked_row[theRowNum]) == 'undefined' || !marked_row[theRowNum]) ? true : null);
      // document.getElementById('id_rows_to_delete' + theRowNum).checked = false;
    }
  } // end 4
		
  // 5. Sets the new color...
  var c = null;
  if( newStyle != null ) {
    // 5.1 ... with DOM compatible browsers except Opera
    if( domDetect ) {
      for( var c = 0; c < rowCellsCnt; c++ ) {
        if( IE4 ) {
          obj.setAttribute("className", newStyle);
        } else {
          obj.setAttribute("class", newStyle);
        }
      } // end for
    }
    // 5.2 ... with other browsers
    else {
      for( var c = 0; c < rowCellsCnt; c++ ) {
        theCells[c].className = newStyle;
      }
    }
  }

  return true;
}

/**
 * Sets the CSS class of the given element.
 * @param sElement the element to set the class for
 * @param sClass the class to assign to the given element
 * @since 1.0.0
 */
function setClass(sElement, sClass) {
  var obj = getElement(sElement);
  if( obj == null ) return;
  if( IE4 ) {
    obj.setAttribute("className", sClass);
  } else {
    obj.setAttribute("class", sClass);
  }
}

/**
 * Copies a value from one element to the other.
 * NOTE: At present, this may only work on textbox elements.
 * @param oFrom the element to copy the value from
 * @param oTo the element to copy the value to
 * @return true if successful, false otherwise
 * @since 1.0.0
 */
function copyValue(oFrom, oTo) {
  if( oFrom == null || oTo == null ) return false;
  oTo.value = oFrom.value;
  return true;
}

function isValidObject(obj, labelName) {
  if( isNull(obj) || isUndefined(obj) ) {
    alert("setting '" + labelName + "' to * cause unable to locate it's related object");
    setInnerHTML(labelName, "*");
    return false;
  } else return true;
}

/**
 * Validation function used for checkboxes.
 * @param checkboxes the checkboxes in question
 * @param labelId the ID of the label to use for validation response status
 * @param successClass the style used to define a successful validation
 * @param failureClass the style used to define a failed validation
 * @return whether or not the validation was successful
 */
function checkCheckedChangeColorAndSetFocus(checkboxes, labelId, successClass, failureClass) {
  var bRet = checkCheckedAndSetFocus(checkboxes, labelId);
  setInnerHTML(labelId, "*");
  setClass(labelId, (bRet ? successClass : failureClass));
  return bRet;
}

function checkCheckedAndSetFocus(checkboxes, labelName) {
  if( checkChecked(checkboxes, labelName) ) {
    return true;
  } else {
    if( focusField == null ) {
      focusField = checkboxes[0];
    }
    return false;
  }
}

function checkChecked(checkboxes, id) {
  if( !isValidObject(checkboxes, id) ) {
    return false;
  }
  if( isAtLeastOneChecked(checkboxes) ) {
    clearInnerHTML(id);
    return true;
  } else {
    setInnerHTML(id, "*");
    return false;
  }
}

function isChecked(checkbox) {
	return (checkbox == null ? false : checkbox.checked);
}

function isAtLeastOneChecked(checkboxes) {
  for( var i = 0; checkboxes != null && i < checkboxes.length; i++ ) {
    if( isChecked(checkboxes[i]) ) {
      return true;
    }
  }
  return false;
}

function checkSelected(formField, labelName) {
  clearInnerHTML(labelName);
  if( !isValidObject(formField, labelName) ) {
    return false;
  }
  if( !isSomethingSelected(formField) ) {
    setInnerHTML(labelName, "*");
    return false;
  }
  return true;
}

function checkSelectedAndSetFocus(formField, labelName) {
  if( checkSelected(formField, labelName) ) {
    return true;
  } else {
    if( focusField == null ) {
      focusField = formField;
    }
    return false;
  }
}

/**
 * Validation function used for dropdowns.
 * @param formField the dropdown in question
 * @param labelId the ID of the label to use for validation response status
 * @param successClass the style used to define a successful validation
 * @param failureClass the style used to define a failed validation
 * @return whether or not the validation was successful
 */
function checkSelectedChangeColorAndSetFocus(formField, labelId, successClass, failureClass) {
  var bRet = checkSelectedAndSetFocus(formField, labelId);
  setInnerHTML(labelId, "*");
  setClass(labelId, (bRet ? successClass : failureClass));
  return bRet;
}

function isSomethingSelected(formField) {
	var output = true;
  if( formField.value == null || formField.value == "" || 
		 	formField.value == "0" || formField.value == "-1" ) output = false;
  return output;
}

function checkDateAndSetFocus(formField, labelName, empty) {
  if( !isValidObject(formField, labelName) ) return false;
  var bRet = checkDate(formField.value, labelName, empty, false);
  if( !bRet && focusField == null ) focusField = formField;
  return bRet;
}

function checkFutureDateAndSetFocus(formField, labelName, empty) {
  if( !isValidObject(formField, labelName) ) return false;
  var bRet = checkDate(formField.value, labelName, empty, true);
  if( !bRet && focusField == null ) focusField = formField;
  return bRet;
}

function checkDate(d, id, empty, mustBeInFuture) {
  var ok = true;
  if( id != null ) {
    clearInnerHTML(id);
  }
  if( d == "" ) {
    if( empty ) {
      return true;
    } else {
      ok = false;
    }
  }
  var strspl = d.split("/");
  if( ok && strspl.length == 3 ) {
    var inDate = new Date(strspl[2], (strspl[1]-1), strspl[0], 23, 59, 59);
    d = inDate.getYear() + 1900;
    if( strspl[2] < 1901 || strspl[2] > 9999 || 
        inDate.getMonth() != (strspl[1]-1) || inDate.getMonth() >= 12 ||
        inDate.getDate() != strspl[0] || inDate.getDate() >= 32 ) ok = false;
    if( ok ) {
      if( !mustBeInFuture ) {
        return true;
      }
      var now = new Date();
      if( inDate.getTime() > now.getTime() ) {
        return true;
      } else {
        ok = false;
      }
    }
  } else {
    ok = false;
  }
  if( !ok && id != null ) {
    setInnerHTML(id, "*");
  }
  return ok;
}

function checkNumbers(value, id, empty, minV, maxV) {
  return checkNumber(value, id, empty, minV, maxV);
}

function checkNumber(value, id, empty, minV, maxV) {
  var s = (value == null ? "" : value.replace(",", ""));
  if( id != null ) {
    clearInnerHTML(id);
  }
  if( empty != null && !empty && s == "" ) {
    if( id != null ) {
      setInnerHTML(id, "*");
    }
    return false;
  }
  if( s != "" && (isNaN(s) || !isNumeric(s) ||
      (minV != null && s < minV) || (maxV != null && s > maxV)) ) {
    if( id != null ) {
      setInnerHTML(id, "*");
    }
    return false;
  }
  return true;
}

function checkNumbersAndSetFocus(formField, labelName, empty, minV, maxV) {
  return checkNumberAndSetFocus(formField, labelName, empty, minV, maxV);
}

function checkNumberAndSetFocus(formField, labelName, empty, minV, maxV) {
  if( !isValidObject(formField, labelName) ) {
    return false;
  }
  var bRet = checkNumber(formField.value, labelName, empty, minV, maxV);
  if( !bRet && focusField == null ) {
    focusField = formField;
  }
  return bRet;
}

function checkNumberChangeColorAndSetFocus(formField, labelId, empty, minV, maxV, successClass, failureClass) {
  var bRet = checkNumberAndSetFocus(formField, labelId, empty, minV, maxV);
  setInnerHTML(labelId, "*");
  setClass(labelId, (bRet ? successClass : failureClass));
  return bRet;
}

function checkNumeric(value, id, empty, minV, maxV) {
  if( id != null ) {
    clearInnerHTML(id);
  }
  if( empty != null && !empty && value == "" ) {
    if( id != null ) {
      setInnerHTML(id, "*");
    }
    return false;
  } else if( empty != null && empty && value == "" ) {
    return true;
  }
  var tmp = "", strChar, charCode, validChars = " -", isValidChar;
  var zeroCode = "0".charCodeAt(0), nineCode = "9".charCodeAt(0);
  //  test strString consists of valid characters listed above
  for( var i = 0; i < value.length ; i++ ) {
    strChar = value.charAt(i);
    isValidChar = false;
    // Get the character code of the current character
    charCode = strChar.charCodeAt(0);
    // Check if the current character is a digit
    if( charCode >= zeroCode && charCode <= nineCode ) {
      isValidChar = true;
      tmp += strChar;
    } else {
      // If it's not a digit, check if it's considered a valid character
      for( j = 0; !isValidChar && j < validChars.length; j++ ) {
        if( strChar == validChars[j] ) {
          isValidChar = true;
        }
      }
    }
  }
  if( tmp == "" ) {
		if( (tmp.length != value.length && id != null) || (!empty && id != null) ) {
			setInnerHTML(id, "*");
    }
		return false;
  } else if( tmp != "" && (isNaN(tmp) ||
      (minV != null && tmp < minV) || (maxV != null && tmp > maxV)) ) {
    if( id != null ) {
      setInnerHTML(id, "*");
    }
    return false;
  }
  return true;
}

function checkPhoneNumbersAndSetFocus(formField, labelName, empty) {
  return checkPhoneNumberAndSetFocus(formField, labelName, empty);
}

function checkPhoneNumberAndSetFocus(formField, labelName, empty) {
  if( !isValidObject(formField, labelName) ) {
    return false;
  }
  var bRet = checkNumeric(formField.value, labelName, empty, null, null);
  if( !bRet && focusField == null ) {
    focusField = formField;
  }
  return bRet;
}

function checkValue(value, id, minLength, maxLength, required, disallowedCharacters) {
  var length = value.length;
	var isRequired = (required == null ? true : required); // default (if not supplied) is true
	var error = (length == 0 && isRequired);
	error = error || (isRequired && minLength != null && length < minLength);
	error = error || (maxLength != null && length > maxLength);
	for( i = 0; disallowedCharacters != null && i < disallowedCharacters.length; i++ ) {
		if( value.indexOf(disallowedCharacters.charAt(i)) >= 0 ) {
			error = true;
			break;
		}
	}
  if( error ) {
    if( id != null ) {
      setInnerHTML(id, "*");
    }
    return false;
  }
  if( id != null ) {
    clearInnerHTML(id);
  }
  return true;
}

function checkValueAndSetFocus(formField, labelName, minLength, maxLength, required, disallowedCharacters) {
  if( !isValidObject(formField, labelName) ) {
    return false;
  }
  var bRet = checkValue(formField.value, labelName, minLength, maxLength, required, disallowedCharacters);
  if( !bRet && focusField == null ) {
    focusField = formField;
  }
  return bRet;
}

/**
 * Validation function used for textboxes.
 * @param formField the textbox in question
 * @param labelId the ID of the label to use for validation response status
 * @param successClass the style used to define a successful validation
 * @param failureClass the style used to define a failed validation
 * @return whether or not the validation was successful
 */
function checkValueChangeColorAndSetFocus(formField, labelId, successClass, failureClass) {
  var bRet = checkValueAndSetFocus(formField, labelId);
  setInnerHTML(labelId, "*");
  setClass(labelId, (bRet ? successClass : failureClass));
  return bRet;
}

function checkEmail(value, id) {
  if( value == null || value.indexOf("@") <= 0 || value.indexOf(".") <= 0 ) {
    if( id != null ) {
      setInnerHTML(id, "*");
    }
    return false;
  }
  if( id != null ) {
    clearInnerHTML(id);
  }
  return true;
}

function checkEmailAndSetFocus(formField, labelName) {
  if( !isValidObject(formField, labelName) ) {
    return false;
  }
  var bRet = checkEmail(formField.value, labelName);
  if( !bRet && focusField == null ) {
    focusField = formField;
  }
  return bRet;
}

function checkAtLeastOneSelectedAndSetFocus(formField, labelName) {
  if( !isValidObject(formField, labelName) ) {
    return false;
  }
  var bRet = checkAtLeastOneSelected(formField, labelName);
  if( !bRet && focusField == null ) {
    focusField = formField;
  }
  return bRet;
}

function checkAtLeastOneSelected(oSelect, id) {
  if( oSelect == null || oSelect.options.length == 0 ) {
    if( id != null ) {
      setInnerHTML(id, "*");
    }
    return false;
  }
  for( var i = 0; i < oSelect.options.length; i++ ) {
    if( oSelect.options[i].selected ) {
      if( id != null ) {
        clearInnerHTML(id);
      }
      return true;
    }
  }
  if( id != null ) {
    setInnerHTML(id, "*");
  }
  return false;
}

function getSelectedValue(sElement) {
  return getObjectSelectedValue(getElement(sElement));
}

function getObjectSelectedValue(oElement) {
	if( oElement != null ) {
		if( oElement.options != null ) {
			for( var i = 0; i < oElement.options.length; i++ ) {
				if( oElement.options[i].selected ) {
					return oElement.options[i].value;
				}
			}
		} else {
			for( var i = 0; i < oElement.length; i++ ) {
				if( oElement[i].selected ) {
					return oElement[i].value;
				}
			}
		}
	}
  return null;
}

function getCheckedValue(sForm, sElement) {
  return getObjectCheckedValue(getElementArray(sForm, sElement));
}

function getObjectCheckedValue(oElement) {
  for( var i = 0; oElement != null && i < oElement.length; i++ ) {
    if( oElement[i].checked ) {
      return oElement[i].value;
    }
  }
  return null;
}

/**
 * Gets the value of the selected radio button in a radio button group.
 * NOTE: A radio button group is a bunch of radio buttons with the same id/name.
 * @param oRadioGroup the radio button group element
 * @return the value of the selected radio button or null if nothing is selected
 * @since 1.0.0
 */
function getRadioGroupSelectedValue(sForm, sRadioGroup) {
  return getObjectCheckedValue(getElementArray(sForm, sRadioGroup));
}

function getRadioGroupObjectSelectedValue(oRadioGroup) {
  return getObjectCheckedValue(oRadioGroup);
}

/**
 * Gets the value of the innerHTML property of the given <span> or <div> element.
 * @param oDiv the id/name of the element to get the contents of
 * @return the innerHTML value or null if the object couldn't be located
 * @since 1.0.0
 */
function getInnerHTML(oDiv) {
  var obj = retrieveElement(oDiv);
  return (obj == null ? null : obj.innerHTML);
}

/**
 * Clears the innerHTML property of the given <span> or <div> element.
 * @param oDiv the id/name of the element to clear the contents of
 * @return true if the operation was successful, false otherwise
 * @see #setInnerHTML(oDiv, sValue)
 * @since 1.0.0
 */
function clearInnerHTML(oDiv) {
  if( oDiv != null ) {
    return setInnerHTML(oDiv, "");
  } else {
    return false;
  }
}

/**
 * Sets the innerHTML property of the given <span> or <div> element.
 * @param oDiv the id/name of the element to set the contents of
 * @param sValue the new contents of the supplied element
 * @return true if the operation was successful, false otherwise
 * @since 1.0.0
 */
function setInnerHTML(oDiv, sValue) {
  if( oDiv != null ) {
    var obj = retrieveElement(oDiv);
    if( obj != null ) {
      obj.innerHTML = sValue;
      return true;
    }
  }
  return false;
}

function selectAllOptions(oSelect) {
  if( oSelect != null ) {
		if( oSelect.type == "select-multiple" ) {
			for( var i = 0; i < oSelect.options.length; i++ ) {
				oSelect.options[i].selected = true;
			}
		} else {
			alert("selectAllOptions(): The dropdown you've specified (" + oSelect.name + ") doesn't allow this");
		}
  }
}

function isAllOptionsSelected(oSelect) {
	var output = false;
	if( oSelect != null ) {
		output = true;
    for( var i = 0; i < oSelect.options.length; i++ ) {
      if( !oSelect.options[i].selected ) {
				output = false;
				break;
			}
    }
  }
	return output;
}

function clearRadioButtonGroupSelection(sForm, sName) {
	var obj = getElementArray(sForm, sName);
	for( i = 0; obj != null && i < obj.length; i++ ) {
		obj[i].checked = false;
	}
}

function toggleRadioButton(sForm, sName, iIndex) {
	toggleRadioButtonObject(getElementArray(sForm, sName)[iIndex]);
}

function toggleRadioButtonObject(rObj) {
	if( !rObj ) return false;
	rObj.__chk = rObj.__chk ? rObj.checked = !rObj.__chk : rObj.checked
}

function clickElement(obj) {
  if( obj == null ) return;
  var o = retrieveElement(obj);
  if( o == null ) return;
  clickObjectElement(o);
}

function clickElementArray(sFormName, sElement, iIndex) {
  var o = getElementArray(sFormName, sElement);
  if( o == null ) return;
  if( isUndefined(o.length) ) {
    clickObjectElement(o);
  } else {
    clickObjectElement(o[iIndex]);
  }
}

function clickObjectElement(obj) {
  if( obj == null ) return;
  if( obj.click != null && obj.blur != null ) {
    obj.click();
    obj.blur();
  }
}

function disableElementArray(sFormName, sElement) {
  enableDisableElementArray(false, sFormName, sElement);
}

function disableFormElementArray(sFormName, sElement) {
  enableDisableElementArray(false, sFormName, sElement);
}

function enableElementArray(sFormName, sElement) {
  enableDisableElementArray(true, sFormName, sElement);
}

function enableFormElementArray(sFormName, sElement) {
  enableDisableElementArray(true, sFormName, sElement);
}

function enableDisableElementArray(bEnable, sFormName, sElement) {
  var obj = getFormElement(sFormName, sElement);
  if( obj == null ) return;
  if( isUndefined(obj[0]) ) {
    obj.disabled = !bEnable;
  } else {
    for( var i = 0; i < obj.length; i++ ) {
      obj[i].disabled = !bEnable;
    }
  }
}

function selectAllChkBoxItems(oChkBoxArray) {
  setAllChkBoxItems(oChkBoxArray, true);
}

function deselectAllChkBoxItems(oChkBoxArray) {
  setAllChkBoxItems(oChkBoxArray, false);
}

function setAllChkBoxItems(oChkBoxArray, bSelect) {
  for( var i = 0; i < oChkBoxArray.length; i++ ) {
    oChkBoxArray[i].checked = bSelect;
  }
}

function selectCheckbox(sChkBox) {
  setChecked(sChkBox, true);
}

function deselectCheckbox(sChkBox) {
  setChecked(sChkBox, false);
}

function setChkBoxItems(oChkBox, bSelect) {
  setChecked(oChkBox, bSelect);
}

function setChecked(sChkBox, bSelect) {
	var obj = getElement(sChkBox);
  if( obj != null ) obj.checked = bSelect;
}

function helpText(id, text) {
  setInnerHTML(id, text);
}

function showHelpSection(oDiv) {
  if( !showdiv(oDiv) ) return false;
  return setStatusBarText(getInnerHTML(oDiv));
}

function hideHelpSection(oDiv) {
  if( !hidediv(oDiv) ) return false;
  return setStatusBarText('');
}

function setStatusBarText(sTxt) {
  window.status = sTxt;
  return true;
}

function clearStatusBarText() {
  window.status = ' ';
  return true;
}

function getBrowserSupport() {
  if( W3C ) {
    alert("Your browser is W3C compatible");
  } else if( NS4 ) {
    alert("Your browser is Netscape 4 compatable");
  } else {
    alert("Your browser must be Internet Explorer based");
  }
}

/**
 * Returns the element of the given form and element ID. <br />
 * <B>NOTE:</B> This method (as opposed to getElement()) will return 
 * an object array (i.e. a radio group)
 * @param sForm the name/id of the form where the element resides
 * @param sName the name/id of the element to retrieve
 * @return the element described or null if no item exists
 * @see getElement(String)
 * @since 1.0.0
 */
function getElementArray(sForm, sName) {
  if( sName == null ) {
    sName = sForm;
    sForm = "form";
  }
  var obj = document.forms[sForm].elements[sName];
  if( obj == null ) return null;
  if( IE4 ) {
    if( isUndefined(obj.type) ) return obj;
    else return new Array(obj);
  } else if( W3C && isObject(obj) && obj.constructor != NodeList ) {
//		if( !isUndefined(obj.length) ) return obj;
		if( (!isUndefined(obj.length) && obj.length > 1 && obj.type != "select-one") || 
				(isUndefined(obj.type) && !isArray(obj)) ) {
			return obj;
		} else {
			return new Array(obj);
		}
  } else {
    return obj;
  }
}

/**
 * Returns the element of the given form and element ID. <br />
 * <B>NOTE:</B> This method (as opposed to getElement()) will return 
 * an object array (i.e. a radio group)
 * @param sForm the name/id of the form where the element resides
 * @param sName the name/id of the element to retrieve
 * @return the element described or null if no item exists
 * @see getElement(String)
 * @since 1.0.0
 */
function getFormElement(sForm, sName) {
  return getElementArray(sForm, sName);
}

function getElement(sName) {
  if( W3C ) {
    return document.getElementById(sName);
  } else if( NS4 ) {
    return document.layers[sName];
  } else { // meant for IE4
    return document.all[sName];
  }
}

function getElementValue(sName) {
  var obj = getElement(sName);
  if( obj != null ) {
    if( obj.type == "checkbox" || obj.type == "password" || obj.type == "text" || obj.type == "textarea" || obj.type == "hidden" || obj.type == "file" ) {
			return obj.value;
    } else if( obj.type == "select-one" ) {
      return getSelectedValue(sName);
		}
  }
  return null;
}

function setElementValue(sName, sValue) {
  var obj = getElement(sName);
  if( obj != null ) {
    if( obj.type == "checkbox" || obj.type == "password" || obj.type == "text" || obj.type == "textarea" || obj.type == "hidden" || obj.type == "file" ) {
      obj.value = sValue;
      return true;
    } else if( obj.type == "select-one" ) {
      for( i = 0; i < obj.options.length; i++ ) {
        if( obj.options[i].value == sValue ) {
          obj.options[i].selected = true;
          return true;
        }
      }
    }
  }
  return false;
}

function clearElementValue(sName) {
  return setElementValue(sName, "");
}

/**
 * Returns a reference to the either the passed-in element or the element with the specified ID.
 * @param obj either an object instance or the ID of the element to retrieve
 * @return a reference to the element
 * @see getElement(String)
 * @since 1.0.0
 */
function retrieveElement(obj) {
  var o = obj;
  if( isString(obj) ) {
    o = getElement(obj);
    if( !isReturnedElementValid(obj, o) ) return null;
  }
  return o;
}

/**
 * Determines whether the passed-in element is valid (not null).
 * @param id the form ID of the element in question
 * @param obj the object to validate
 * @return true if the object is valid, false otherwise
 * @since 1.0.0
 */
function isReturnedElementValid(id, obj) {
  if( isNull(obj) ) {
    alert("Failed to locate the specified element [" + id + "]");
    return false;
  }
  return true;
}

/**
 * Shows or hides everything within the passed <div> tag.
 * Changes visibility to the oposite of it's current state.
 * @param sDiv the ID of the div tag to show or hide
 * @since 1.0.0
 */
function showhide(sDiv) {
  return setVisible(sDiv, !isVisible(sDiv));
} 

/**
 * Shows everything within the passed <div> or <span> tag.
 * @param sDiv the ID of the div or span tag to show
 * @since 1.0.0
 */
function show(sDiv) {
  return setVisible(sDiv, true);
}

/**
 * Shows everything within the passed <div> or <span> tag.
 * @param sDiv the ID of the div or span tag to show
 * @deprecated since 1.0.0 - use #show() instead
 * @see #show()
 * @since 1.0.0
 */
function showdiv(sDiv) {
  return setVisible(sDiv, true);
} 

/**
 * Shows everything within the passed <div> or <span> tag.
 * @param sDiv the ID of the div or span tag to show
 * @see #show()
 * @since 1.0.0
 */
function showElement(sDiv) {
  return setVisible(sDiv, true);
}

/**
 * Hides everything within the passed <div> or <span> tag.
 * @param sDiv the ID of the div or span tag to hide
 * @since 1.0.0
 */
function hide(sDiv) {
  return setVisible(sDiv, false);
}

/**
 * Hides everything within the passed <div> or <span> tag.
 * @param sDiv the ID of the div or span tag to hide
 * @deprecated since 1.0.0 - use #hide() instead
 * @see #hide()
 * @since 1.0.0
 */
function hidediv(sDiv){ 
  return setVisible(sDiv, false);
} 

/**
 * Hides everything within the passed <div> tag.
 * @param sDiv the ID of the div or span tag to hide
 * @see #hide()
 * @since 1.0.0
 */
function hideElement(sDiv) {
  return setVisible(sDiv, false);
}

function setElementVisible(sDiv, bVisible) {
	return setVisible(sDiv, bVisible);
}

function setVisible(sDiv, bVisible) {
  var obj = retrieveElement(sDiv);
  if( obj == null ) return false;
  if( NS4 ) {
    obj.visibility = (bVisible ? "collapse" : "hidden");
  } else {
    obj.style.display = (bVisible ? "inline" : "none");
  }
  return true;
}

function toggleTableRowVisibility(sDiv) {
	var obj = retrieveElement(sDiv);
  if( obj == null ) return false;
	if( obj.style.display == 'none' ) {
		try {
			obj.style.display='table-row';
		} catch(e) {
			obj.style.display = 'block';
		}
	} else {
		obj.style.display = 'none';
	}
}

function setTableRowVisible(sDiv, bVisible) {
	var obj = retrieveElement(sDiv);
  if( obj == null ) return false;
	if( bVisible ) {
		try {
			obj.style.display = 'table-row';
		} catch(e) {
			obj.style.display = 'block';
		}
	} else {
		obj.style.display = 'none';
	}
  return true;
}

function isTableRowVisible(sDiv) {
	var obj = getElement(sDiv); //retrieveElement(sDiv);
  if( obj == null ) return false;
	return (obj.style.display == 'table-row' || obj.style.display == 'block');
}

function isVisible(oDiv) {
  var obj = getElement(oDiv); //retrieveElement(oDiv);
  if( isNull(obj) ) return false;
  if( NS4 ) {
    return ( obj.visibility != "hidden" );
  } else { // IE4 & W3C
    return ( obj.style.display != "none" );
  }
  return false;
}

function enableElement(sElement) {
  setElementDisabled(sElement, false);
}

function enabledElement(sElement) {
  enableElement(sElement);
}

function disableElement(sElement) {
  setElementDisabled(sElement, true);
}

function disabledElement(sElement) {
  disableElement(sElement);
}

function enableDisableElement(sElement, bEnable) {
  setElementDisabled(sElement, !bEnable);
}

function setElementDisabled(sElement, bDisabled) {
  var obj = retrieveElement(sElement);
  if( obj != null ) obj.disabled = bDisabled;
}

function centerWindow(width, height) {
  var actualWidth = screen.width;
  var actualHeight = screen.height;
  window.resizeTo(width, height);
  window.moveTo((actualWidth / 2) - (width / 2), (actualHeight / 2) - (height / 2));
}

/**
 * Opens a new window (with maximum height) to the given URL.
 * @param theURL the URL of the page to open
 * @param winName the name to refer to the new window as
 * @param xtraDetail the Javascript window.open feature list (eg. resizable, scrollbars, etc)
 */
function openWindowMaxHeight(theURL, winName, xtraDetail) {
  var featureList;
  featureList = xtraDetail + ",height=" + (screen.height - 100);
  top.consoleRef = window.open(theURL, winName, featureList);
  top.consoleRef.moveTo(0,0);
  top.consoleRef.focus();
}

function openWindowOffScreen(theURL, winName) {
	var windowObj = window.open(theURL,winName,'width=1,height=1');
	if( is_ie ) {
		windowObj.moveTo(screen.width - 2, screen.height - 2);
	} else {
		windowObj.moveTo(screen.width + 10, screen.height + 10);
	}
}

function MM_openBrWindow(theURL, winName, features) { //v2.0
  return window.open(theURL, winName, features);
}

//center  	yes | no | 1 | 0 | on | off  	Center the dialog
//dialogHeight 	Length/units 	Outer height of dialog
//dialogLeft 	Integer 	Left pixel offset (overrides center)
//dialogTop 	Integer 	Top pixel offset (overrides center)
//dialogWidth 	Length/units 	Outer width of dialog
//edge 	raised | sunken 	Transition style between border and content area
//help 	yes | no | 1 | 0 | on | off 	Display help icon in titlebar
//resizable 	yes | no | 1 | 0 | on | off 	Dialog is resizable
//status 	yes | no | 1 | 0 | on | off 	Display status bar
function openModalWindow(theURL, winName, features) {
	if( window.showModalDialog ) {
		window.showModalDialog("xpopupex.htm","name","dialogWidth:255px;dialogHeight:250px");
	} else {
		window.open('xpopupex.htm','name','height=255,width=250,toolbar=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=no,modal=yes');
	}
}

function redirectWindowOpener(url) {
	window.opener.location.href = url;
	return false;
}

function refreshWindowOpener() {
  if( js_version == "1.0" ) {
    // Javascript v1.0
    //  This version of the refresh function will cause a new
    //  entry in the visitor's history.  It is provided for
    //  those browsers that only support JavaScript 1.0.
    window.opener.location.href = unescape(window.opener.location.pathname);
  } else if( js_version == "1.1" ) {
    // Javascript v1.1
    //  This version does NOT cause an entry in the browser's
    //  page view history.  Most browsers will always retrieve
    //  the document from the web-server whether it is already
    //  in the browsers page-cache or not.
    window.opener.location.replace(unescape(window.opener.location.pathname));
  } else if( js_version == "1.2" || js_version == "1.3" || js_version == "1.4" ) {
    // Javascript v1.2
    //  This version of the refresh function will be invoked
    //  for browsers that support JavaScript version 1.2
    //  The argument to the location.reload function determines
    //  if the browser should retrieve the document from the
    //  web-server.  In our example all we need to do is cause
    //  the JavaScript block in the document body to be
    //  re-evaluated.  If we needed to pull the document from
    //  the web-server again (such as where the document contents
    //  change dynamically) we would pass the argument as 'true'.
    window.opener.location.reload(true);
  }
}

/**
 * Adds the given option name & value pair to the given dropdown.
 * @param oSelParent the dropdown element to add the option to
 * @param sText the text part of the option to be added
 * @param sValue the value part of the option to be added
 * @param sSelectedValue the value used to indicate whether this option should be selected
 */
function addSelectEntry(oSelParent, sText, sValue, sSelectedValue) {
  oSelParent.appendChild(createOption(sText, sValue, sSelectedValue));
}

function removeSelectEntryByIndex(oSelParent, iIndex) {
  oSelParent.remove(iIndex);
}

function createOption(sText, sValue, sSelectedValue) {
  var child = document.createElement("option");
  child.innerHTML = sText;
  child.setAttribute("value", sValue);
  if( sSelectedValue != null && sSelectedValue == sValue ) {
    child.setAttribute("selected", "selected");
  }
  return child;
}

function addBlankSelectEntry(oSelParent, bAutoSelect) {
  var sSelect = (bAutoSelect ? "" : null);
  addSelectEntry(oSelParent, "", "", sSelect);
}

function fillWithFutureDates(oSelect, iDays, bLabels, sSelectedValue) {
  fillWithDates(oSelect, iDays, bLabels, sSelectedValue, null);
}

function fillWithDates(oSelect, iDays, bLabels, sSelectedValue, oStartDate) {
  var mydate = new Date(), str, name, child, day, month;
  if( oStartDate != null ) mydate = oStartDate;
  for( var i = 0; i < iDays; i++ ) {
    day = mydate.getDate();
    if( day < 10 ) day = "0" + day;
    month = mydate.getMonth() + 1;
    if( month < 10 ) month = "0" + month;
    str = day + "/" + month + "/" + mydate.getFullYear();
    if( bLabels && oStartDate == null && i == 0 ) name = "Today";
    else if( bLabels && oStartDate == null && i == 1 ) name = "Tomorrow";
    else name = str;
    addSelectEntry(oSelect, name, str, sSelectedValue);
    day++;
    mydate.setDate(day);
  }
}

function fillWithHours(oSelect, sSelectedValue) {
  fillWithNumbers(oSelect, 0, 11, sSelectedValue);
}

function fillWith24Hours(oSelect, sSelectedValue) {
  fillWithNumbers(oSelect, 0, 23, sSelectedValue);
}

function fillWithNumbers(oSelect, iFrom, iTo, sSelectedValue) {
  for( var i = iFrom; i <= iTo; i++ ) {
    if( i < 10 ) str = "0" + i;
    else str = "" + i;
    addSelectEntry(oSelect, str, str, sSelectedValue);
  }
}

function fillWithMinutes(oSelect, sSelectedValue) {
  fillWithNumbers(oSelect, 0, 59, sSelectedValue);
}

function fillWithMinuteIntervals(oSelect, iMinuteInterval, sSelectedValue) {
  var items = 60 / iMinuteInterval;
  var itemsUnderTen = 10 / iMinuteInterval;
  for( var i = 0; i < items; i++ ) {
    if( i < itemsUnderTen ) str = "0" + (i * iMinuteInterval);
    else str = "" + (i * iMinuteInterval);
    addSelectEntry(oSelect, str, str, sSelectedValue);
  }
}

function fillWithDays(oSelect, sSelectedValue) {
  fillWithNumbers(oSelect, 1, 31, sSelectedValue);
}

function fillWithMonths(oSelect, sSelectedValue) {
  for( var i = 1; i <= 12; i++ ) {
    str = MONTH_NAMES[i - 1];
    addSelectEntry(oSelect, str, i, sSelectedValue);
  }
}

function fillWithYears(oSelect, iStartYear, sSelectedValue) {
  fillWithNumbers(oSelect, iStartYear, new Date().getFullYear(), sSelectedValue);
}

function confirmDelete(sRedirect, sText) {
  var ok = confirm("You are about to delete " + sText + ", press OK to proceed");
  if( ok ) {
    redirect(sRedirect);
  }
}

function confirmEdit(sRedirect, sText) {
  var ok = confirm("You are about to edit " + sText + ", press OK to proceed");
  if( ok ) {
    redirect(sRedirect);
  }
}

//  check for valid numeric strings	
function isNumeric(str) {
  if( str.length == 0 ) return false;
  var strChar, strValidChars = "0123456789.-";
  for( var i = 0; i < str.length; i++ ) {
    strChar = str.charAt(i);
    if( strValidChars.indexOf(strChar) == -1 ) return false;
  }
  return true;
}

function isNumeric_DigitsOnly(sInput) {
  if( sInput == null || (sInput != null && sInput.length == 0) ) return false;
  var output = true;
  var zeroCode = "0".charCodeAt(0);
  var nineCode = "9".charCodeAt(0);
  for( var i = 0; i < sInput.length; i++ ) {
    charCode = sInput.charCodeAt(i);
    if( charCode < zeroCode || charCode > nineCode ) {
      output = false;
    }
  }
  return output;
}

function stripNonDigits(sInput) {
  if( sInput == null ) return null;
  var charCode, output = "";
  var zeroCode = "0".charCodeAt(0);
  var nineCode = "9".charCodeAt(0);
  for( var i = 0; i < sInput.length; i++ ) {
    charCode = sInput.charCodeAt(i);
    if( charCode >= zeroCode && charCode <= nineCode ) output += sInput.charAt(i);
  }
  return output;
}

function isAlien(obj) {
  return isObject(obj) && typeof obj.constructor != 'function';
}

function isArray(obj) {
  return isObject(obj) && obj.constructor == Array;
}

function isBoolean(obj) {
  return typeof obj == 'boolean';
}

function isEmpty(obj) {
  var i, v;
  if( isObject(obj) ) {
    for( var i in obj ) {
      v = obj[i];
      if( isUndefined(v) && isFunction(v) ) return false;
    }
  }
  return true;
}

function isFunction(obj) {
  return typeof obj == 'function';
}

function isNull(obj) {
  return typeof obj == 'object' && !obj;
}

function isNumber(obj) {
  return typeof obj == 'number' && isFinite(obj);
}

function isObject(obj) {
  return (obj && typeof obj == 'object') || isFunction(obj);
}

function isString(obj) {
  return typeof obj == 'string';
}

function isUndefined(obj) {
  return typeof obj == 'undefined';
} 

function isNotNull(obj) {
  return obj != null && !isUndefined(obj);
}

function functionExists(functionName) {
	return isFunction(window[functionName]);
}

/**
 * Uses numberformatter.js to format decimal numbers correctly.
 * @since 1.0.0
 */
function formatNumber(sNumber, commas, places) {
  var formatter = new NumberFormat(sNumber);
  formatter.setCurrency(false);
  if( commas == null ) formatter.setCommas(true);
  else formatter.setCommas(commas);
  if( places == null || isNaN(places) ) formatter.setPlaces(2);
  else formatter.setPlaces(places);
  return formatter.toFormatted();
}