//  Begin: BrowserDetect (copied from http://www.quirksmode.org/js/detect.html)
var BrowserDetect = {
    init: function () {
        this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
        this.version = this.searchVersion(navigator.userAgent)
            || this.searchVersion(navigator.appVersion)
            || "an unknown version";
        this.OS = this.searchString(this.dataOS) || "an unknown OS";
    },
    searchString: function (data) {
        for (var i=0;i<data.length;i++) {
            var dataString = data[i].string;
            var dataProp = data[i].prop;
            this.versionSearchString = data[i].versionSearch || data[i].identity;
            if (dataString) {
                if (dataString.indexOf(data[i].subString) != -1)
                    return data[i].identity;
            }
            else if (dataProp)
                return data[i].identity;
        }
    },
    searchVersion: function (dataString) {
        var index = dataString.indexOf(this.versionSearchString);
        if (index == -1) return;
        return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
    },
    dataBrowser: [
        {   string: navigator.userAgent,
            subString: "OmniWeb",
            versionSearch: "OmniWeb/",
            identity: "OmniWeb"
        },
        {
            string: navigator.vendor,
            subString: "Apple",
            identity: "Safari"
        },
        {
            prop: window.opera,
            identity: "Opera"
        },
        {
            string: navigator.vendor,
            subString: "iCab",
            identity: "iCab"
        },
        {
            string: navigator.vendor,
            subString: "KDE",
            identity: "Konqueror"
        },
        {
            string: navigator.userAgent,
            subString: "Firefox",
            identity: "Firefox"
        },
        {
            string: navigator.vendor,
            subString: "Camino",
            identity: "Camino"
        },
        {   // for newer Netscapes (6+)
            string: navigator.userAgent,
            subString: "Netscape",
            identity: "Netscape"
        },
        {
            string: navigator.userAgent,
            subString: "MSIE",
            identity: "Explorer",
            versionSearch: "MSIE"
        },
        {
            string: navigator.userAgent,
            subString: "Gecko",
            identity: "Mozilla",
            versionSearch: "rv"
        },
        {   // for older Netscapes (4-)
            string: navigator.userAgent,
            subString: "Mozilla",
            identity: "Netscape",
            versionSearch: "Mozilla"
        }
    ],
    dataOS : [
        {
            string: navigator.platform,
            subString: "Win",
            identity: "Windows"
        },
        {
            string: navigator.platform,
            subString: "Mac",
            identity: "Mac"
        },
        {
            string: navigator.platform,
            subString: "Linux",
            identity: "Linux"
        }
    ]
};
BrowserDetect.init();
// End: BrowserDetect

var ID_DELIMITER = ';';

var xmlHttp;
var xmlHttpAsync=true;

function createXMLHttpRequest() {
   xmlHttp = getNewXMLHttpRequest();
}

function getNewXMLHttpRequest() {
   if (window.ActiveXObject) {
      return new ActiveXObject("Microsoft.XMLHTTP");
   } else if (window.XMLHttpRequest) {
      return new XMLHttpRequest();
   }
}



function getSuffix(value){
   //should return all after last _ character in value, blank if no _
   var idx = value.lastIndexOf("_");
   if (idx >= 0 ) {
      return value.substring(idx + 1);
   } else {
      return "";
   }   
}

function money(value){
	return Number(value).toFixed(2);
	
}

function checkTailingZero(value){
   if (value-Math.floor(value)>0){
      if (value*10 == Math.round(value*10)){
         value += "0";
      }else{
      	value=value+"";
      }
   } else {
      value += ".00";
   }
   return value;
}

function loadOptions(element,value){
   element.options.length=0;
   var ddIndex=0;
   while(value!=null&&value.indexOf("~")!=-1){
      var index=value.indexOf("~");
      var id=value.substring(0,index);
      value=value.substr(index+1);
      index=value.indexOf("~");

      var name="";
      if(index==-1){
         name=value;
         value="";
      }else{
         name=value.substring(0,index);
         value=value.substr(index+1);
      }
      element.options[ddIndex] = new Option(name, id);
      ddIndex=ddIndex+1;
   }
}

function loadElement(element,value){
   if (typeof(element) == 'string') {
      element = document.getElementById(element);
   }

   if(element.tagName=="SELECT"){
      for(var i=0;i<element.options.length;i++){
         if(element.options[i].value==value){
            element.selectedIndex=i;
            break;
         }
      } 
   }else if(element.type=="checkbox"){
      if("1"==value||"on"==value||"Y"==value){
         element.checked=true;
      }else{
         element.checked=false;
      }
   }else{
      if (typeof(element.value) != 'undefined') { 
         element.value = value;
      } else { 
         element.innerHTML = value;
      }
   }
}

function stripCommas(){
   var inputs = document.getElementsByTagName("input");
   var i;
   for (i=0; i<inputs.length; i++){
      var field = inputs[i];
      if (field.type == 'text'){
         s = field.value;
         filteredValues = ",$";     // Characters stripped out
         var j;
         var returnString = "";
         for (j = 0; j < s.length; j++) {  // Search through string and append to unfiltered values to returnString.
            var c = s.charAt(j);
            if (filteredValues.indexOf(c) == -1) returnString += c;
         }
         field.value = returnString;
      } 
   }
}

function getValue(element){
   if(element.tagName=="SELECT"){
      if (element.options.length == 0 || element.selectedIndex < 0) {
         return null;
      }
      return element.options[element.selectedIndex].value;
   }else{
      return element.value;
   }
}

function getAJAXValue(element){
   if(element.tagName=="SELECT"){
      var value = getValue(element);
      if (value == null) {
         return null;
      }
      return value.split('~')[0];
   }else{
      return element.value;
   }
}

function getField(fieldname) {
   var result = getFieldIfExists(fieldname);
   return result == null ? "" : result;
}

function getFieldIfExists(fieldname) {
   var matchingElems = xmlHttp.responseXML.getElementsByTagName(fieldname);
   if (matchingElems.length == 0) return null;
   
   var fieldNode = matchingElems[0];
   //alert("before escape substr ok "+fieldNode.childNodes[0].nodeValue.substr(fieldNode.childNodes[0].nodeValue.length-10));
   return fieldNode.childNodes.length > 0 ? unescape(fieldNode.childNodes[0].nodeValue) : "";
}

function getFieldNodeArray(arrayname, fieldname){
   var xmlDoc = xmlHttp.responseXML;
   var arrayNode = xmlDoc.getElementsByTagName(arrayname)[0];
   if (arrayNode&&arrayNode.childNodes.length>0&&arrayNode.childNodes[0]) {  
      var fieldNodeArray = arrayNode.getElementsByTagName(fieldname);
      return fieldNodeArray;
   }
   return "";
}

function getArrayFieldFromList(fieldNodeArray, arrayindex){
   var fieldNode = fieldNodeArray[arrayindex];
   if (fieldNode&&fieldNode.childNodes.length>0&&fieldNode.childNodes[0]) {
      return unescape(fieldNode.childNodes[0].nodeValue);
   }
   return "";  
}

function getArrayField(arrayname, fieldname, arrayindex) {
   var xmlDoc = xmlHttp.responseXML;
   var arrayNode = xmlDoc.getElementsByTagName(arrayname)[0];
   var fieldNode = arrayNode.getElementsByTagName(fieldname)[arrayindex];
   if (fieldNode&&fieldNode.childNodes.length>0&&fieldNode.childNodes[0]) {
      return unescape(fieldNode.childNodes[0].nodeValue);
   }
   return "";
}

function getArrayLength(arrayname, fieldname) {
   var xmlDoc = xmlHttp.responseXML;
   if (xmlDoc == null) return 0;
   var myarray = xmlDoc.getElementsByTagName(arrayname);
   if (myarray.length < 1) {
      return 0;
   }
   var arrayNode = xmlDoc.getElementsByTagName(arrayname)[0];
   var entityNodes = arrayNode.getElementsByTagName(fieldname);
   return entityNodes.length;  
}

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

function escapeJQuerySelector(str) {
   return str.replace(/([#;&,\.\+\*~':"\!\^\$\[\]\(\)=>\|\/])/g, '\\$1');
}

String.prototype.splitOnce = function(separator) {
   var index = this.indexOf(separator);
   if (index >= 0) {
      return [this.substring(0,index), this.substring(index + 1)];
   } else {
      return [this.toString()];
   }
}

String.prototype.substringAfter = function(substring) {
   var index = this.indexOf(substring);
   if (index >= 0) {
      return this.substring(index + substring.length);
   }
   return "";
}

function isBlank(str) {
   if (str == null) return true;
   return /^\s*$/.test(str);
}

// This is for getting valueFormula working in popins.
// Should be called after the cloned nodes have been inserted,
// so node ids have already been updated with the counter.
// Form tag stores the necessary javascript call as string in a var.
// Everytime we popin we'll grab the corresponding string here and call
// eval on it so that the cloned fields will have the same valueFormula functionality.
function doTotalFunctionForPopin(node, counter) {
   var children = node.childNodes;
   if (children) {
      for (var i=0;i<children.length;i++) {
         if (children[i].nodeType == 1) {
            var elemId = children[i].id.replace(new RegExp(counter + "$"), "");
            var formulaVarName = 'totalformula_' + elemId.replace(/[\~;%-\.\/:]/g, ''); // NOTE: can't have "~" in the variable name in javascript
            formulaVarName = formulaVarName.replace(/\s*/g, ''); // get rid of spaces
            var formulaVarType = eval('typeof ' + formulaVarName + ' ');   
            if (formulaVarType != 'undefined') {
               var formula = eval('new String(' + formulaVarName + ')');
               formula = formula.replace(/___popincounter___/g, counter); //"___popincounter___" is injected by FormTag
               eval(formula);
            } 
         }
         doTotalFunctionForPopin(children[i], counter);
      }
   }
}

function cloneFields(templateId, destinationId, counterId) {
   counterInput = document.getElementById(counterId);
   var counter = parseInt(counterInput.value);
   
   var clone = document.getElementById(templateId).cloneNode(true);
   clone.id = templateId + counter;
   if (window.navigator.appName == 'Netscape') {
      clone.style.display = clone.tagName == 'TBODY' ? 'table-row-group' : 'table-row'; 
   } else {
      if (clone.style.display) clone.style.display = 'block'; 
   }
   clone.disabled = false;
   
   incrementNodeData(clone, counter);
   counterInput.value = counter+1;
   
   var insertHere = document.getElementById(destinationId);
   var hereParent = insertHere.parentNode;
   hereParent.insertBefore(clone,insertHere);
   
   // hack for FF, FF does the insertBefore properly for tables as far as the DOM is concerned, but for some reason doesn't display it properly.
   if (BrowserDetect.browser == "Firefox" && hereParent.tagName == 'TABLE') {
      var tempTable = document.createElement('table');
      hereParent.parentNode.replaceChild(tempTable, hereParent);
      tempTable.parentNode.replaceChild(hereParent, tempTable);
   }
   
   // update totalling formula functions for new fields (if any), must be done after elements have been inserted
   doTotalFunctionForPopin(clone, counter);
   
   setCloneFieldDefaultValues(counter);
   setCloneFieldDefaultCheckedValues(counter);
   doCheckboxesAsRadioAfterElementsAreInserted();
}

function setCloneFieldDefaultValues(counter) {
   if (!document.ids_to_default) return;
   for (var i=document.ids_to_default.length - 1 ; i>=0 ; i--){
      var id = document.ids_to_default[i];
      if (counter != getPopinNumberFromId(id)) continue;
      var elem = document.getElementById(id);
      if (elem){
         elem.value = document.values_to_default[i];
         document.ids_to_default.splice(i, 1);
         document.values_to_default.splice(i, 1);
      }
   }
}

function setCloneFieldDefaultCheckedValues(counter){
   if (!document.defaultchecked_ids_to_default) return;
   for (var i = document.defaultchecked_ids_to_default.length - 1 ; i>=0 ; i--){
      var id = document.defaultchecked_ids_to_default[i];
      if (counter != getPopinNumberFromId(id)) continue;
      var elem = document.getElementById(id);
      if (elem){
         elem.checked = (document.defaultchecked_values_to_default[i] == 'true');
         document.defaultchecked_ids_to_default.splice(i, 1);
         document.defaultchecked_values_to_default.splice(i, 1);
      }
   }   
}

function doCheckboxesAsRadioAfterElementsAreInserted() {
   if (!document.popin_checkboxesAsRadios) return;
   while (document.popin_checkboxesAsRadios.length > 0) {
      var obj = document.popin_checkboxesAsRadios.pop();
      CheckboxesAsRadio.add(obj.group, obj.id);
   }
}

function getPopinNumberFromId(elemId) {
   if (elemId.match(/_([^_]*)$/) != null) { 
      return RegExp.$1;
   } else {
      return new RegExp('[0-9]*$').exec(elemId)[0];
   }
}

function getIdWithoutPopinNumber(elemId) {
   if (elemId.match(/(.*_)[^_]*$/) != null ) { 
      return RegExp.$1;
   } else {
      return elemId.replace(/[0-9]*$/, '');
   }
}

// this function is assigned to the onclick event of calendar images
// which is handled in incrementNodeData function below - rob
function returnShowCalendar(triggerid,counter){
   var parts=triggerid.split(ID_DELIMITER);
   var elemid=parts[1]+counter;
   var format = parts[2];
   return showCalendar(elemid,format);
}

function incrementNodeData(node, counter) {
   var children = node.childNodes;
   if (children) {
      for (var i=0;i<children.length;i++) {
         // increment names for data separation
         var aName = children[i].name
            if (aName) {
               children[i].name = aName + counter;
            }
         // increment 'id' and 'for' attrs so <label> tags match
         var anId = children[i].id
            if (anId) {
               if (anId.indexOf('trigger' + ID_DELIMITER)!=-1){ // this handles calendar popup function for date tag popin fields - rob
                  var triggerid=counter+''+anId;
                  children[i].onclick=function () { returnShowCalendar(triggerid,counter); };
                  if (children[i].captureEvents) children[i].captureEvents(Event.CLICK);
                  children[i].id = triggerid;
               }else{
                  children[i].id = anId + counter;
               }
            }

         if (children[i].nodeType == 1) {
            children[i].disabled = false; // alf - I disabled input fields in the template tag so that it won't submit, re-enable here

            // validation for popins
            var validateId;
            if (BrowserDetect.browser == "Firefox") {
               validateId = children[i].getAttribute("for"); // this is for firefox
            } else {
               validateId = children[i].getAttribute("htmlfor"); // this is for IE
               if (validateId === null) {
                  validateId = children[i].htmlFor; // this is for IE8
               }
            }
            if (validateId != null) {
               validateId = validateId + counter;
               doLabelMarkerActions(validateId, children[i].title);
            }
         }
         incrementNodeData(children[i], counter);
      }
   }
}

// handle stuff passed via title attribute of labels added to popin fields
function doLabelMarkerActions(elemId, labelTitle) {
   if ("" == labelTitle) return;
   var actionParts = labelTitle.split(";");
   for (var x=0 ; x<actionParts.length ; x++) {
      var parts = actionParts[x].splitOnce(':');
      var actionType = parts[0];
      var actionValue =(parts.length == 2) ? parts[1] : null;
      
      if (eval('typeof(' + actionType + 'LabelMarkerAction)') == 'function') {
         eval(actionType + 'LabelMarkerAction(\'' + elemId + '\', \'' + actionValue + '\');');
      } else {
         alert('function ' + actionType + 'LabelMarkerAction not defined');
      }
   }
}

function requireLabelMarkerAction(id) {
   if (!document.ids_to_validate) {
      document.ids_to_validate = new Array();
   }
   document.ids_to_validate.push(id);
}

function datatypeLabelMarkerAction(id, type) {
   if (!document.datacheck_ids_to_add) {
      document.datacheck_ids_to_add = new Array();
   }
   document.datacheck_ids_to_add.push(id);

   if (!document.datacheck_types_to_add) {
      document.datacheck_types_to_add = new Array();
   }
   document.datacheck_types_to_add.push(type);
}

function defaultcheckedLabelMarkerAction(id, checked) {
   if (!document.defaultchecked_ids_to_default){
      document.defaultchecked_ids_to_default=new Array();
   }
   document.defaultchecked_ids_to_default.push(id);

   if (!document.defaultchecked_values_to_default){
      document.defaultchecked_values_to_default=new Array();
   }
   document.defaultchecked_values_to_default.push(checked);
}

function defaultvalueLabelMarkerAction(id, defaultvalue) {
   if (!document.ids_to_default){
      document.ids_to_default=new Array();
   }
   document.ids_to_default.push(id);

   if (!document.values_to_default){
      document.values_to_default=new Array();
   }
   document.values_to_default.push(defaultvalue);
}

function ajaxreceiveLabelMarkerAction(elemId, ajaxreceiveValue) {
   if (ajaxreceiveObj) { //ajaxreceiveObj defined in ajaxsend.js
      var parts = ajaxreceiveValue.splitOnce(':');
      var callName = parts[0];
      var ajaxField =(parts.length == 2) ? parts[1] : elemId;
      ajaxreceiveObj.addField(elemId, ajaxField, callName);
   }
}

function checkboxesasradioLabelMarkerAction(elemId, radioGroupName) {
   if (!document.popin_checkboxesAsRadios) {
      document.popin_checkboxesAsRadios = new Array();
   }
   document.popin_checkboxesAsRadios.push({group:radioGroupName + getPopinNumberFromId(elemId), id:elemId});
}

function createHiddenInputField(newId, newValue) {
   var newField = document.createElement('input');
   newField.id = newId;
   newField.name = newId;
   newField.type = 'hidden';
   newField.value = newValue;
   return newField;
}

function parseSQLDate(datestr) {
   if (datestr == null || typeof(datestr) != 'string') return null;
   var re = /^(\d{4})-(\d+)-(\d+)(\s(\d{2}):(\d{2})(:(\d{2})(\.\d+)?)?)?$/;
   var matchArray = re.exec(datestr.trim());
   if (matchArray != null) {
      if (typeof (matchArray[4]) == 'undefined') {
         return new Date(matchArray[1], matchArray[2] - 1, matchArray[3]);
      } else if (typeof (matchArray[7]) == 'undefined') {
         return new Date(matchArray[1], matchArray[2] - 1, matchArray[3], matchArray[5], matchArray[6]);
      } else {
         return new Date(matchArray[1], matchArray[2] - 1, matchArray[3], matchArray[5], matchArray[6], matchArray[8]);
      }
   } 
   
   if (/^[A-Za-z]{3}\s\d+\s\d{2}:\d{2}$/.test(datestr)) {
      var result = new Date();
      result.setTime(Date.parse(getCurrentYear() + ' ' + datestr));
      return result;
   }
   
   if (/^\d{2}\s[A-Za-z]{3},\s\d{4}$/.test(datestr.trim())) {
      var result = new Date();
      result.setTime(Date.parse(datestr));
      return result;
   }
   return null;
}

function getCurrentYear() {
	return new Date().getFullYear();
}

function getHoursBetween(fromDate, toDate) {
   if (typeof(fromDate) == 'string') { 
      fromDate = parseSQLDate(fromDate);
   } 
   if (typeof(toDate) == 'string') { 
      toDate = parseSQLDate(toDate);
   } 
   
   if (fromDate != null && toDate != null) {
      return (toDate - fromDate) / (1000 * 60 * 60);
   } else {
      return NaN;
   }
}

function popover(myspan) {
   myspan.style.display = "none";

   var hiddenfieldspan = document.getElementById(myspan.id + "field");
   hiddenfieldspan.style.display = "inline";

   //put focus on field that was displayed
   var actualfieldname = myspan.id.substring(0,myspan.id.length-7); //7 is the number of characters of 'popover';
   var actualfield = document.getElementById(actualfieldname);
   actualfield.focus();
}

function cancelpopover(popoverid) {
   var popoverspan = document.getElementById(popoverid+"popover");
   var hiddenspan = document.getElementById(popoverid + "popoverfield");
   var hiddenfield = document.getElementById(popoverid);
   if(hiddenfield.type == "text" || (hiddenfield.tagName == 'INPUT' && hiddenfield.type!="button")){
      hiddenfield.value = popoverspan.innerText;
      //        hiddenfield.disabled = true;
   }
   hiddenspan.style.display = "none";
   popoverspan.style.display = "inline";
}

function showpopover(popoverid) {
   var popoverspan = document.getElementById(popoverid+"popover");
   var hiddenspan = document.getElementById(popoverid + "popoverfield");
   var hiddenfield = document.getElementById(popoverid);

   //      hiddenfield.disabled = false;
   hiddenspan.style.display = "inline";
   popoverspan.style.display = "none";
}

var popovercolor;
function popovermouseover(anElement) {
   if (popovercolor == null) {
      popovercolor = anElement.style.color;
   }
   if (anElement.tagName == 'TD') {
      anElement.style.backgroundColor = 'yellow';
   } else {
      if (anElement.parentNode) {
         popovermouseover(anElement.parentNode);
      }
   }
}

function popovermouseout(anElement) {
   if (anElement.tagName == 'TD') {
      anElement.style.backgroundColor = popovercolor;
   } else {
      if (anElement.parentNode) {
         popovermouseout(anElement.parentNode);
      }
   }
}

function isValidObject(obj) {
   return (null != obj  &&  "undefined" != typeof(obj));
}   

// gets the selected value from a group of radio buttons
function getCheckedValue(radioObj) {
   if(!radioObj)
      return "";

   var radioLength = radioObj.length;
   if(radioLength == undefined)
      if(radioObj.checked)
         return radioObj.value;
      else
         return "";

   for(var i = 0; i < radioLength; i++) {
      if(radioObj[i].checked) {
         return radioObj[i].value;
      }
   }
   return "";                       
}  

// used by yesab forms on submit
// Usage: strToCheck is optional, if given then only matches on that string within square brackets,
//        otherwise matches on anything within square brackets
function checkTextArea(textAreaId, strToCheck){
   if (typeof(tinyMCE) != 'undefined') {
      // if tinyMCE editor, textarea contents must be saved before we can access it via value attribute
      tinyMCE.triggerSave();
   }

   var textAreaContents = null;
   var textArea = document.getElementById(textAreaId);
   // special case for Firefox, document.getElementById(textAreaId) returns null
   // so we have to get the html contents directly from tinyMCE editor (includes html tags, but that's ok)
   if (BrowserDetect.browser == "Firefox" && textArea == null && typeof(tinyMCE) != 'undefined') {
      textAreaContents = tinyMCE.getContent(textAreaId);
   } else {
      if (textArea != null) {
         textAreaContents = textArea.value;
      }
   }

   if (textAreaContents != null) {
      var searchStr;
      if ( strToCheck === undefined){
    	  searchStr = "\\[[^\\]]+\\]";
      } else {
         searchStr = "\\[" + strToCheck + "\\]";
      }
      var arrayMatch = textAreaContents.match(searchStr);
      var ignoreWords = ["mso", "gte"];
      var noIgnoreWords = true;
      for(var i = 0; i < ignoreWords.length; i++) {
    	if(arrayMatch[0].match(ignoreWords[i])){
    		noIgnoreWords = false;
    	}
      }
      if (arrayMatch && noIgnoreWords){
    	  alert (strToCheck);
         var msg = "You must modify this document. \n\n";
         msg += "Enter the appropriate value where you read " + arrayMatch[0];
         alert (msg);
         return false;
      }
   } 
   return true;
}

// Given a tag name and a RegExp object, return elements with matching ids
function getElementsMatchingId(tagName, regex) {
   var allWithTag = document.getElementsByTagName(tagName);
   var filtered = new Array();
   for (var idx = 0; idx < allWithTag.length ; idx++){
      if (regex.test(allWithTag[idx].id)) {
         filtered.push(allWithTag[idx]);
      }
   }    
   return filtered;
}

function triggerOnchangeWhenOnKeyUp(elemId) {
   var elem = document.getElementById(elemId);
   if (elem != null && typeof(elem) != 'undefined') {
      if (elem.onchange != null) {
         updateEvent('onkeyup', elemId, 'this.onchange();');   
      }
   }
}

// dynamically adds the string specified by 'addition' to the event (currently onchange or onkeyup or onclick) function of the specified element
function updateEvent(eventName, elemId, addition) {
   if (typeof(addition) == 'undefined') { return; }
   var elem = document.getElementById(elemId);

   var event;
   if (eventName == 'onchange') {
      event = elem.onchange;
   } else if (eventName == 'onkeyup') {
      event = elem.onkeyup;
   } else if (eventName == 'onclick') {
      event = elem.onclick;
   } else {
      alert('Cant process event ' + eventName + ' in updateEvent');
      return;
   }

   var oldEvent = '';
   if (event != null) {
      oldEvent = event.toString(); 
      //alert("before: " + event.toString());
      oldEvent = new RegExp('.*\n*\{(\n*(.*\n*)*)\}').exec(oldEvent)[1];
      if (!new RegExp(';$').test(oldEvent)) { oldEvent += ';'; }
   }
   var newEvent = oldEvent;
   if (newEvent.indexOf(addition) < 0) {
      newEvent += addition;
   }
   if (eventName == 'onchange') {
      elem.onchange = new Function(newEvent);
      //alert("after: " + elem.onchange.toString());
   } else if (eventName == 'onkeyup') {
      elem.onkeyup = new Function(newEvent);
      //alert("after: " + elem.onkeyup.toString());
   } else if (eventName == 'onclick') {
      elem.onclick = new Function(newEvent);
   } 
}  

// Looks up the fields to use from the totalsMap or formulaMap and calculates total. 
// Use addTotalField to add fields to the totaling map.
// forumulaMap should be populated automatically by FormTag/FieldTag.
function doTotalsForField(totalFieldId) {
   var totalField = document.getElementById(totalFieldId);
   if (totalField == null) {
      return;
   }

   var total = "";
   if (typeof(document.totalsMap) != 'undefined') {
      var fieldsMap = document.totalsMap[totalFieldId];
      if (fieldsMap != null) {
         for (var key in fieldsMap) {
            var field = document.getElementById(key);
            if (field != null && typeof(field) != 'undefined') {
               var operator = fieldsMap[key];
               if (total == "") {
                  total = Number(field.value);
               } else {
                  total = eval(total + operator + Number(field.value));
               }
            } 
         }
      } 
   } 

   if (typeof(document.formulaMap) != 'undefined') {
      var formula = document.formulaMap[totalFieldId];
      if (formula != null) {
         total = eval(formula);  
      }
   }

   totalField.value = total;
   if (totalField.onchange != null) {
      totalField.onchange();
   }
}

function initialEvaluateFormulas() {
	for (var totalFieldId in document.formulaMap) {
		doTotalsForField(totalFieldId);
	}
}

// Keep a map of maps for totaling.
// Keys are ids of total fields.
// Values are pairs, each pair consists of id of field to total and the operator to use for totaling (eg. '+' or '*')
function addTotalField(totalFieldId, operator, fieldId) {
   var totalField = document.getElementById(totalFieldId);
   var field = document.getElementById(fieldId);

   if (!isNaN(field.value)) { 
      document.totalsMap = (typeof(document.totalsMap) == 'undefined') ? new Array() : document.totalsMap; 

      if (document.totalsMap[totalFieldId] == null) {
         document.totalsMap[totalFieldId] = new Array();
      }
      document.totalsMap[totalFieldId][fieldId] = operator; 
   }
}

// Keep a map of formulas.
// Keys are ids of total fields.
// values are the formulas to calculate the totals.
function addFormula(totalFieldId, formula) {
   var totalField = document.getElementById(totalFieldId);
   document.formulaMap = (typeof(document.formulaMap) == 'undefined') ? new Array() : document.formulaMap; 
   document.formulaMap[totalFieldId] = formula; 
}

function clearSearchFields(form){
   var inputs = form.getElementsByTagName("input");
   for (i = 0; i < inputs.length; i++){
      if (inputs[i].type == 'text'){
         inputs[i].value = '';
      } else if (inputs[i].type == 'checkbox'){
         inputs[i].checked = false;
      }
   }
   inputs = form.getElementsByTagName("select");
   for (i = 0; i < inputs.length; i++){
      inputs[i].selectedIndex = 0;
   }
}


function toggleUsers(ppElem){
   var name=ppElem.id;
   var id=name.substring(name.indexOf("_")+1);
   var elements=document.getElementsByTagName("input");
   for(var i=0;i<elements.length;i++){
      var elem=elements[i];
      if(elem.name.indexOf("notifyuserid")!=-1&&elem.name.indexOf(id)!=-1){
         elem.checked=true;
      }
   }
}

function resize(containerFrameId, sourceframeid){
   var defaultheight=25;
   var navframe = document.getElementById(containerFrameId);
   var frame = document.getElementById(sourceframeid);
   var rows=navframe.rows.split(",");
   var framesexpanded=0;
   for (var i=0;i<rows.length;i++){
      if (rows[i]!=defaultheight)
         framesexpanded++;
   }
   var frameheight=rows[frame.id];
   if (frameheight==defaultheight){
      framesexpanded++;
      rows[frame.id]=0;
   }else{
      rows[frame.id]=defaultheight;
   }
   var percent = 100/framesexpanded;
   var attrib="";
   for (var j=0;j<rows.length;j++){
      if (rows[j]!=defaultheight){
         attrib=attrib+percent+"%";
      }else{
         attrib=attrib+defaultheight;
      }
      if (j!=rows.length-1){
         attrib=attrib+",";
      }
   }
   navframe.setAttribute('rows',attrib,0);
}

function toggle() {
   for (var i=0 ; i<arguments.length ; i++) {
      var elem = arguments[i];
      if (typeof(elem) == 'string') {
         elem = document.getElementById(elem);
      } else if (typeof(elem) == 'object' && typeof(elem.length) == 'number') {
         for (var j=0 ; j<elem.length ; j++) {
            toggle(elem[j]);
         }
         continue;
      }
      elem.style.display = (elem.style.display != 'none' ? 'none' : '' );
   }
}

function showAll() {
   for (var i=0 ; i<arguments.length ; i++) {
      var elem = arguments[i];
      if (typeof(elem) == 'string') {
         elem = document.getElementById(elem);
      } else if (typeof(elem) == 'object' && typeof(elem.length) == 'number') {
         for (var j=0 ; j<elem.length ; j++) {
            showAll(elem[j]);
         }
         continue;
      }
      elem.style.display = '';
   }
}

function hideAll() {
   for (var i=0 ; i<arguments.length ; i++) {
      var elem = arguments[i];
      if (typeof(elem) == 'string') {
         elem = document.getElementById(elem);
      } else if (typeof(elem) == 'object' && typeof(elem.length) == 'number') {
         for (var j=0 ; j<elem.length ; j++) {
            hideAll(elem[j]);
         }
         continue;
      }
      elem.style.display = 'none';
   }
}

function getQueryStringValue(param){
   param = param.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
   var regexS = "[\\?&]"+param+"=([^&#]*)";
   var regex = new RegExp( regexS );
   var results = regex.exec( window.location.href );
   if( results == null )
      return "";
   else
      return results[1];
}

function isNumber(field){
   var fieldvalue = field.value;
   var myregexp = new RegExp("^[0-9]+$");
   if (!myregexp.test(fieldvalue)) {
      field.focus();
      alert("Invalid format.  Please enter a number only.");
      return false;
   }
   return true;
}

function addRowToTable() {
   var table = arguments[0];
   var cellTag = arguments[1];
   var theadbody;
   if ('th' == cellTag){
      theadbody = document.createElement('thead');
   }else{
      theadbody = document.createElement('tbody');
   }
   var row = document.createElement('tr');
   for (var i=2 ; i<arguments.length ; i++) {
      addCellToRow(cellTag, arguments[i], row);
   }
   theadbody.appendChild(row);
   table.appendChild(theadbody);
}

function addCellToRow(tag, value, row) {
   var cell = document.createElement(tag);
   if (typeof(value) == 'string') {
      cell.appendChild(document.createTextNode(value));
   } else {
      cell.appendChild(value);
   }
   row.appendChild(cell);   
}

function makeCheckbox(name, value, checked) {
   var checkbox = document.createElement('input');
   checkbox.type = 'checkbox';
   checkbox.id = name;
   checkbox.name = name;
   if (typeof(value) != 'undefined') {
      checkbox.value = value;
   }
   if (typeof(checked) != 'undefined') {
      checkbox.checked = checked;
   }
   return checkbox;
}

function getFormByName(formName) {
   for (var index = 0 ; index < document.forms.length ; index++) {
      if (document.forms[index].getAttribute('name') == formName) {
         return document.forms[index];
      }
   }
}

function getAllFormFieldsAsParameterString(formName) {
   var paramString = '';
   var elements = new Object();
   var names = new Array();
   var form = getFormByName(formName);
   for (var index = 0 ; index < form.elements.length ; index++) {
      var elem = form.elements[index];
      if (elem != null) {
    	 if (elem.className != null && elem.className.indexOf("ignorechange") != -1) {
    		 continue;
    	 }
         if (elem.type == 'radio' || elem.type == 'checkbox') {
            if (elem.checked && elem.name != null && elem.name.length > 0) {
            	elements[elem.name]=elem.value;
            	names.push(elem.name);
            }
         } else {
            if (typeof(elem.name) != 'undefined' && typeof(elem.value) != 'undefined' && elem.name != null && elem.name.length > 0) {
            	elements[elem.name]=elem.value;
            	names.push(elem.name);
            }
         }
      }
   }
   names.sort();
   for (var i = 0; i < names.length; i++) {
	   paramString += names[i] + '=' + elements[names[i]] + '&';
   }
   return paramString.replace(/&$/, '');
}

function synchronousLoadScript(url){
   newXMLHttpReq = getNewXMLHttpRequest();
   newXMLHttpReq.open('GET', url, false);
   newXMLHttpReq.send(null);

   if (newXMLHttpReq.status == 200) {
      var script = document.createElement("script");
      script.type = "text/javascript";
      script.languate = "javascript";
      script.text = newXMLHttpReq.responseText;
      document.getElementsByTagName("head")[0].appendChild(script);
   }
} 

var CheckboxesAsRadio = {
   isNoneAllowed: new Object(),
   groups : new Object(),
   
   clear : function () {
      this.groups = new Object();
   },
   
   allowNone:function(groupName){
      var allowed = this.isNoneAllowed[groupName];
      if (allowed == null) { allowed = 1; this.isNoneAllowed[groupName] = allowed; }
   },
   
   add : function (groupName, checkboxId) {
      var array = this.groups[groupName];
      if (array == null) { array = new Array(); this.groups[groupName] = array; }
      array.push(checkboxId);
      updateEvent('onclick', checkboxId, 'CheckboxesAsRadio.clicked(\'' + groupName + '\', \'' + checkboxId + '\')');
   },
   
   clicked : function (groupName, checkboxId) {
      var array = this.groups[groupName];
      if (array != null) {
         var allowed=this.isNoneAllowed[groupName];
      
         if(!document.getElementById(checkboxId).checked && allowed == 1){
         	//do nothing, unchecking was ok
         }else{
            for(var i=0 ; i<array.length ; i++) {
               var checkbox = document.getElementById(array[i]);
               if (checkbox != null) { checkbox.checked = false; }
            }
            document.getElementById(checkboxId).checked = true;
         }
      }
   }
}

function TextFilter() {
   this.targets = new Object();
   this.clear = function(){ this.targets = new Object(); };
   this.addTargetText = function(elemId, matchableText){
      var matchables = this.targets[elemId];
      if (matchables == null) {matchables = new Array(); this.targets[elemId] = matchables;}
      matchables.push(matchableText);
   };
   this.checkMatch = function(matchable, inputText){return matchable.toUpperCase().indexOf(inputText.toUpperCase()) >= 0;};
   this.filterAction = function(elem, matched){ elem.style.display = (matched ? '' : 'none' ); };
   
   this.filter = function(inputText){ this.filterInternal(inputText,true,true,false); };
   this.filterShowOnly = function(inputText){ this.filterInternal(inputText,true,false,false); };
   this.filterHideOnly = function(inputText){ this.filterInternal(inputText,false,true,false); };
   this.filterHideMatch= function(inputText){ this.filterInternal(inputText,false,false,true); };
   
   this.filterInternal= function(inputText,show,hide,hideMatch){
      for(var elemId in this.targets){
         var matched = false;
         var matchables = this.targets[elemId];
         for(var i=0 ; i<matchables.length ; i++) {
            if (this.checkMatch(matchables[i], inputText)){
               matched = true;
               break;
            }
         }
         if(matched&&hideMatch){
         	this.filterAction(document.getElementById(elemId), !matched);
         }else if((matched&&show)||(!matched&&hide)){
         	this.filterAction(document.getElementById(elemId), matched);
         }
      }
   };
   this.showAll = function(){ for(var elemId in this.targets){ document.getElementById(elemId).style.display = ''; } };
   this.hideAll = function(){ for(var elemId in this.targets){ document.getElementById(elemId).style.display = 'none'; } };
}

function getFirstParentWithTagName(elem, tagName) {
   if (elem == null || elem.parentNode == null) return null;
   if (elem.parentNode.tagName.toUpperCase() == tagName.toUpperCase()) return elem.parentNode;
   return getFirstParentWithTagName(elem.parentNode, tagName);
}

function toInt(strValue, defaultIntValue, radix) {
   var defaultValue = (typeof(defaultIntValue) == 'undefined') ? 0 : defaultIntValue;
   var parseRadix = (typeof(radix) == 'undefined') ? 10 : radix;
   var result = parseInt(strValue, parseRadix);
   return isNaN(result) ? defaultValue : result;
}

function ElementDetail(elemId) {
   this.elemId = elemId;
   this.attributes = new Array();
   this.values = new Array();
   this.actions = new Array();
   this.addDetail = function (attributeName, attributeValue) {
      this.attributes.push(attributeName);
      this.values.push(typeof(attributeValue) == 'undefined' ? document.getElementById(this.elemId)[attributeName] : attributeValue);
      return this;
   };
   this.addAction = function (elemAction) {
      this.actions.push(elemAction);
      return this;
   };
}

function restoreElementDetails(elemDetails) {
   for(var i=0 ; i<elemDetails.length ; i++) {
      var elemDetail = elemDetails[i];
      var elem = document.getElementById(elemDetail.elemId);
      for(var j=0 ; j<elemDetail.attributes.length ; j++) {
         elem[elemDetail.attributes[j]] = elemDetail.values[j];
      }
      for(var j=0 ; j<elemDetail.actions.length ; j++) {
         eval('document.getElementById(\'' + elemDetail.elemId + '\').' + elemDetail.actions[j]);
      }
   }   
}

function ChangeDetector(formName) {
   this.formName = formName;
   this.detector = getAllFormFieldsAsParameterString(this.formName);
   this.changed = function() { return getAllFormFieldsAsParameterString(this.formName) != this.detector; };
}

function isNumberKey(e) {
  var key;
  if (window.event)
    key = window.event.keyCode;
  else if (e)
    key = e.which;
  else
    return true;
  if ((key == 13 /*enter*/) || (key == 8 /*backspace*/) || (key == null) || (key == 0 /*left arrow, right arrow, delete on mozilla*/))
    return true;
  return ("0123456789.-").indexOf(String.fromCharCode(key)) > -1;
}

function willKeyAffectLength(e) {
	  var key;
	  if (window.event)
	    key = window.event.keyCode;
	  else if (e)
	    key = e.which;
	  else
	    return false;
	  if ((key == 13 /*enter*/) || (key == 8 /*backspace*/) || (key == null) || (key == 0 /*left arrow, right arrow, delete on mozilla*/))
	    return false;
	  return true;
}

if (typeof jQuery !== 'undefined') {
	function maxlengthfunction(e,elem,fromBlur) {
		var val = elem.val();
		var ge = !fromBlur && (elem.get(0).tagName === 'INPUT');
		if (ge && !willKeyAffectLength(e)) return true;
		if ((ge && val.length >= elem.attr('maxlength')) || (!ge && val.length > elem.attr('maxlength'))) {
			elem.val(val.substr(0,elem.attr('maxlength')));
			alert("The maximum length of " + elem.attr('maxlength') + " has been reached");
			return false;
		}
		return true;
	}
	
	function maxlengthkeypress(e) {
		maxlengthfunction(e,$(this),false);
	}
	
	function maxlengthblur(e) {
		maxlengthfunction(e,$(this),true);
	}
	
	$(function() {
		$('.maxlen').keypress(maxlengthkeypress).blur(maxlengthblur).filter('textarea').keyup(maxlengthkeypress);
	});
	
	
    (function($) {
       $.fn.disable = function() {
          return $(this).attr('disabled','disabled');
       };
       $.fn.enable = function() {
          return $(this).removeAttr('disabled');
       };
    })(jQuery);
}
