/*
 * All FORM VALIDATION functions in this file are DEPRECATED and WILL BE REMOVED
 * in a future release. Do not use them.
 *
 * The deprecated functions are marked @deprecated and have been moved to the end
 * of the file.
 *
 * See the documentation in validation.js for the correct way to do Javascript
 * validation in PiMS.
 */


//deprecated?
var fieldsForValidation;

/*
 * When users click to another page, they may lose their edits.
 */
document.attributeChanged = false;
document.warnChanged = true;
function onEdit() {
    document.attributeChanged = true;
}
function dontWarn() {
    //alert("dontwarn");
    document.warnChanged = false;
}
function warnChange() {
    if (!document.warnChanged || ! document.attributeChanged) {
        return true; // carry on regardless
    }
    ok = confirm(
            'Are you sure you want to navigate away from this page?'
            +'\nChanges that you have made will be lost.'
            +'\nPress OK to continue, or Cancel to stay on the current page.'
    );
    if (ok) {document.warnChanged = false;}
    return ok;
}
window.onbeforeunload = function() {
    if (!document.warnChanged || ! document.attributeChanged) {
        return; // carry on regardless
    }
    return false; // FF or IE will make warning message
}



/* Called when a page is loaded
 * Redefined at the bottom of the page if necessary
 * An empty function is defined here to prevent errors
 */
function onLoadPims() {}

/*
 * This for the same purpose as above
 */
function onSubmit() {}

/*
 * sets the form's onSubmit handler to askBeforeDeleting()
 *
 * Assumes there is only one form on the page!
 */
function confirmDelete() {
  if (document.forms[1]) {
      document.forms[1].onsubmit = askBeforeDeleting;
  }
}


/* Adds a confirmation dialogue.
 * Called in a page with a Delete button.
 * Returns true if OK is pressed, false if Cancel is pressed.
 */
function askBeforeDeleting() {
	var confirmationMessage;
	confirmationMessage  = "You are about to delete the following from PIMS:\n";
	confirmationMessage += "\n";
	if(null != className) { confirmationMessage += className + ": "; }
	confirmationMessage += objectName + "\n";
	confirmationMessage += "\n";
	confirmationMessage += "If you are sure you want to do this, click OK. Otherwise, click Cancel."

	return window.confirm(confirmationMessage);
}


/********************************************
 * Tab functionality
 */
function tab_fixIE6onLoad(){
  if(console && console.error){
  	console.error("Page uses deprecated 'tab_fixIE6onLoad()'");
  }		
  var currentTabLink=$$("h3.current")[0].down("a");
  currentTabLink.click();
}

/**
 * Inserts <input type="hidden" name="_tab" value="tabId"> into frm
 * - used for persistence of tab ID
 */
function tab_appendTabIdToForm(frm,tabId){
  if(!frm["_tab"]){
	var fld=document.createElement("input");
	fld.setAttribute("type","hidden");
	fld.setAttribute("name","_tab");
	fld.setAttribute("value",tabId);
	frm.appendChild(fld);
  }
}

function tab_appendTabIdToFormsInTab(tabHeadId){
  var tabBody=$(tabHeadId+"_body");
  var formsInTab=tabBody.getElementsBySelector("form");
  formsInTab.each(function(frm){
	tab_appendTabIdToForm(frm,tabHeadId);
  });
  //and remove the default mouseover and onclick methods
  // - they're only there to fire this, and it only needs doing once
  tabBody.onmouseover=null;
  tabBody.onkeypress=null;
}

function tab_showTab(elem){
  if(null==elem){ //set to current tab
    var tabs=document.body.down("div.tabs");
    elem=tabs.down("h3.current");
  }
  elem=$(elem);
  elem.blur();
  var tabSet=elem.up("div.tabs");
  var clickedTab=elem.up("h3.tab");
  if(null==clickedTab || clickedTab.hasClassName("greyedout")) {
    return false;
  }
  var currentTab=elem.up("div.tabs").down("h3.current");
  var clickedTabId=clickedTab.id;
  var clickedTabBody=$(clickedTabId+"_body");

  tab_appendTabIdToFormsInTab(clickedTabId);

  var tabBodies = tabSet.getElementsBySelector(".tabbody");

  for(i=0;i<tabBodies.length;i++){
    var tabBody=tabBodies[i];
    if(tabBody.id==clickedTabBody.id){
      tabBody.addClassName("currenttabbody");
    } else {
      tabBody.removeClassName("currenttabbody");
    }
  }

  currentTab.removeClassName("current");
  clickedTab.addClassName("current");
}

/*
 * End tab functionality
 ********************************************/


/*
 * Removes leading and trailing spaces from the string
 */
function trim(stringToTrim) {
  stringToTrim=stringToTrim.replace(/^\s*/, ''); //trim leading spaces
  stringToTrim=stringToTrim.replace(/\s*$/, ''); //trim trailing spaces
  return stringToTrim;
}


/*
 * Colours the offending field to make the error more obvious
 */
function highlightField(fieldName) {
  document.forms[1][fieldName].style.backgroundColor='#ffaaaa';
}


/*
 * Resets a form field's background to transparent
 */
function clearHighlight(fieldName) {
  document.forms[1][fieldName].style.backgroundColor='transparent';
}


/*
 * Sends the user back one page - equivalent to their clicking the Back button.
 */
function goBack() {
  history.go(-1);
}


/* Function open new window with help information on the attribute in it.
 * @param - parameter - The URL to the Help servlet
 */

// Help window
var nwindow = null;

function getHelpWindow(parameter) {
    alert('This funcationality is obsolete');
/*
 	if(! window_opened()) {
	  var wheight = screen.availHeight
	  var wheight = screen.availWidth
    nwindow = window.open(parameter,"HelpWindow","height=400, width=400, resizable, scrollbars");
    nwindow.focus();
	}
	else {
		nwindow.location=parameter;
		nwindow.focus();
	}
*/
}

/*
 * Check whether or not the opened window already closed.
 */
function window_opened() {
	if(!nwindow) {
		return false;
	}
	else if (nwindow.closed){
		return false;
	}
	else {
		return true;
	}
}

// Function to hide and show column in the table
// hide column in the table
function hideColumn (tableName, colIndex) {
  var table = document.all ? document.all.tableName :
              document.getElementById(tableName);
  for (var r = 0; r < table.rows.length; r++)
    table.rows[r].cells[colIndex].style.display = 'none';
}
// show column in the table
function showColumn (tableName, colIndex) {
  var table = document.all ? document.all.tableName :
              document.getElementById(tableName);
  for (var r = 0; r < table.rows.length; r++)
    table.rows[r].cells[colIndex].style.display = '';
}
//show all columns in the table
function showAll(tabName, list) {
	for (var counter = 0; counter < list.options.length; counter++) {
		showColumn(tabName, list.options[counter].index)
	}
}
//show columns in the table
function showColumns (tabName, list) {
	var chosed_el = new Array()
	chosed_el = getSelected(list)
	for (var r = 0; r < chosed_el.length; r++) {
		showColumn (tabName, chosed_el[r]);
	}
}
//hide columns in the table
function hideColumns(tabName, list) {
	var chosed_el = new Array()
	chosed_el = getSelected(list)
	for (var r = 0; r < chosed_el.length; r++) {
		hideColumn (tabName, chosed_el[r]);
	}
}
// Get selected elements from the list
function getSelected(currentList) {
var selected_array = new Array()
var cur_index = 0
	for (var counter = 0; counter < currentList.options.length; counter++) {
		if(currentList.options[counter].selected) {
			selected_array[cur_index]=currentList.options[counter].index
			cur_index++
		}
	}
return selected_array
}

/* Temporary not in use
// Display an example value in the field
// Usage onfocus="clearfield(false, this, 'dd/mm');" dd/mm - text to display
//       onblur="clearfield(true,this,'dd/mm');"
function clearfield(add, field, replace) {
	if(add)	{
		if (field.value == '' || field.value == replace) {
			field.value = replace;
			field.style.color = '#999999';
		}
	} else {
		if (field.value == replace)	{
			field.value = '';
			field.style.color = '#222222';
		}
	}
}

function init(forms) {
    for (var f=0; f < forms.length; f++) {
		form = forms[f];
		for (var c=0; c < form.elements.length; c++) {
			form.elements[c].focus();
		}
	}
}
*/

//Set of functions to hide and show particular area of the page
// surrounded by DIV
//TODO remove when open/close replaced by toggle
function obj(sID) {
    var o=null;
    if (document.layers)
        o=document.layers[sID];
    else if (document.all)
        o=document.all(sID);
    else if (document.getElementById)
        o=document.getElementById(sID);
    return o;
}

//TODO remove when open/close replaced by toggle
function oOpen(sID) {
//	var o=obj(sID);
	var o=document.getElementById(sID);
	if (o) o.style.display="block";
}

//TODO remove when open/close replaced by toggle
function oClose(sID) {
//	var o=obj(sID);
	var o=document.getElementById(sID);
	if (o) o.style.display="none";
}



function isValidDnaOrProteinSequence(seq){
	var seq = removeSpaces(seq);
	if(seq.charAt("0") == ">"){
		var firstNewline=seq.indexOf("\n");
		seq = seq.substr(firstNewline);
	}
	if(isValidDnaSequence(seq) || isValidProteinSequence(seq)) {
		return true;
	}
	return false;
}

function cleanSequence(string){
	string=string.toUpperCase();
	string=removeSpaces(string);
	string = string.replace(/[^A-Z]/g, "");
	return string;
}

//modification of cleanSequence to avoid reformatting to single string during editing
function cleanSequence2(string){
	string=string.toUpperCase();
	string=trim(string);
	string = string.replace(/[^A-Z\s{2,}]/g, "");
	return string;
}

function removeSpaces(string) {
	var tstring = "";
	string = '' + string;
	splitstring = string.split(" ");
	for(i = 0; i < splitstring.length; i++)
	tstring += splitstring[i];
	return tstring;
}



/*
* Check whether the field value is a valid position in the holder.
*/
function validHolderPosition(fieldName,alias) {
  addToCheckList(fieldName,alias,"validHolderPosition",true);
}




function checkSequence() {
    thisElement = getElement(document.forms[1], "org.pimslims.model.refSampleComponent.MolComponent:seqString");
    if (thisElement) {
        var myElement = getElement(document.forms[1], "org.pimslims.model.refSampleComponent.MolComponent:molType");
        if (myElement) {
    	    var myType = myElement.value;
            if (myType=="protein") {
                if (!isValidProteinSequence(thisElement.value)) {
                    alert("Invalid protein sequence, valid characters are [ABCDEFGHIKLMNPQRSTVWYXZ]");
                    return false;
                }
            }
            if (myType=="DNA") {
                if (!isValidDnaSequence(thisElement.value)) {
                    alert("Invalid DNA sequence, valid characters are [ACGTRYMKSWBDHVN]");
                    return false;
                }
            }
            if (myType=="RNA") {
                if (!isValidDnaSequence(thisElement.value)) {
                    alert("Invalid DNA sequence, valid characters are [ACGTRYMKSWBDHVN]");
                    return false;
                }
            }
        }
    }
    return true;
}

function checkProteinSequence(theSeq) {
	if (!isValidProteinSequence(theSeq)) {
		alert("Invalid protein sequence, valid characters are [ABCDEFGHIKLMNPQRSTVWYXZ]");
		return false;
	}
	return true;
}

function checkDNASequence(theSeq) {
	if (!isValidDnaSequence(theSeq)) {
		alert("Invalid DNA sequence, valid characters are [ACGTRYMKSWBDHVN]");
		return false;
	}
	return true;
}

function getElement(thisForm, thisName) {
    for (var index=0;index<thisForm.elements.length;index++) {
    	    myelement=thisForm.elements[index];
       	    if (myelement.name == thisName) {
                return myelement;
            }
    }
    return null;
}

/*
For use with tree structures, for example view of protocols. clicking on the +/- icon opens/closes
the information underneath.
Assumes HTML structure:
<div>
  <div id="TOGGLENAMEhead"><!-- The header bar, containing the title and the +/- button -->
    <img id="TOGGLENAMEimg" src="[path]plus.gif" onClick="toggleView('TOGGLENAME')" />
  </div>
  <div id="TOGGLENAMEbody"><!-- the body, which appears/disappears-->

  </div>
</div>

 */
function toggleView(divname, path) {
  if(document.getElementById(divname+"body").style) {
    if(document.getElementById(divname+"body").style.display=="block" || document.getElementById(divname+"body").style.display=="") {
      document.getElementById(divname+"body").style.display="none";
      document.getElementById(divname+"img").src=path+"/images/icons/plus.gif";
    } else {
      document.getElementById(divname+"body").style.display="block";
      document.getElementById(divname+"img").src=path+"/images/icons/minus.gif";
    }
  }
}

function scrollSidebar(anchor) {
	var target = document.getElementById(anchor);
	if (!target) {return;}
	var sidebar = document.getElementById('sidebar');
	var offset = 0;
	if (target.y) {
	   offset = target.y - sidebar.y;
	} else if (target.offsetTop) {
		 offset = target.offsetTop;
	}
	sidebar.scrollTop =  offset;
}

function confirmAbandon() {
    var agree=confirm('Are you sure you want to abandon this work?\nIf you click OK, you will lose any information you have entered here.');
    if (agree) {
        history.go(-1);
    }
    
	return false ;
}


/*****************************************************************
 * For dealing with IE6 and SELECTs. (ED, Mar 2008)
 */

/**
 * Hides all SELECTs if the browser is detected as IE6.
 * IE6 has "issues" with SELECTs, we need to hide them
 * before overlaying any other content.
 */
function hideAllSelectsIfIE6(){
  if(console && console.error){
  	console.error("Page uses deprecated 'hideAllSelectsIfIE6()'");
  }		
  //All IEs have document.all, but only 7+ have XMLHttpRequest
  if(document.all&&!window.XMLHttpRequest){
    var allSelects=$$("select");
    allSelects.each(function (sel){
      sel.style.visibility="hidden";
    });
  }
}

/**
 * Unhides all SELECTs if the browser is detected as IE6.
 * IE6 has "issues" with SELECTs, we need to hide them
 * before overlaying any other content. This function
 * undoes the hide.
 */
function unhideAllSelectsIfIE6(){
  if(console && console.error){
  	console.error("Page uses deprecated 'unhideAllSelectsIfIE6()'");
  }		
  if(document.all&&!window.XMLHttpRequest){
    var allSelects=$$("select");
    allSelects.each(function (sel){
      sel.style.visibility="visible";
    });
  }
}

/*****************************************************************
 * For opening and closing collapsible boxes. (ED, Sep 2007)
 */
function oldToggleCollapsibleBox(headerElem){
  var box=Element.extend(headerElem).up(1);
  box.toggleClassName("collapsibleBox_opened");
  box.toggleClassName("collapsibleBox_closed");
}
function openBox(headerElem){
  var box=Element.extend(headerElem).up(1);
  box.addClassName("collapsibleBox_opened");
  box.removeClassName("collapsibleBox_closed");
}
function closeBox(headerElem){
  var box=Element.extend(headerElem).up(1);
  box.removeClassName("collapsibleBox_opened");
  box.addClassName("collapsibleBox_closed");
}

/*****************************************************************
 * For opening and closing context menus. (ED, Oct 2007)
 */

/**
 * Shows the context menu - should be called on mouseover of the pulldown image.
 *
 * @param img The pulldown arrow image.
 */
function old_showContextMenu(img,menuItems) {
  Element.extend(img); //for IE
  Position.clone(img,$("contextmenu_real"),{setWidth:false,setHeight:false} );
  $("contextmenu_real").innerHTML="";
  $("contextmenu_real").style.display="block";
  for(i=0;i<menuItems.length;i++){
    $("contextmenu_real").innerHTML+=old_writeContextMenuItem(menuItems[i]);
  }
}

/**
 * Writes the context menu item.
 *
 * @param item A Javascript object containing the menu item info.
 */
function old_writeContextMenuItem(item){
  var onclick="";
  if(item["onclick"]){ onclick='onclick="'+item["onclick"]+';return false"'; }
  var link ='<a href="'+ item["url"] +'" '+onclick+'>';
  link += '<img src="'+ contextPath +'/images/icons/'+ item["icon"] +'" alt="" height="16" width="16">';
  link += item["label"];
  link += '</a>';
  return link;
}

/**
 * Hides the context menu - should be called on mouseout of the menu.
 *
 */
function old_hideContextMenu() {
  $("contextmenu_real").style.display="none";
}

/**
 * Highlights a row in a table.
 * @param elem The object clicked (probably a "highlight" icon)
 */
function toggleHighlight(elem){
  elem=$(elem);
  var tr=elem.up("tr");
  tr.toggleClassName("highlighted");
  var tds=Element.immediateDescendants(tr);
  for(i=0;i<tds.length;i++){
    tds[i].toggleClassName("highlighted");
  }
}




/*******************************************************************************
 Start of deprecated form validation functions
 *******************************************************************************/
/**
 * @deprecated
 * Adds the fieldName to be checked for a non-null value when
 * the form is submitted, if another field has a non-null value.
 *
 * The form is valid if
 * - otherFieldName is empty, regardless of fieldName
 * - otherFieldName is not empty AND fieldName is not empty
 *
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 * @param otherFieldName - the other form field
 * @param otherAlias     - a more user-friendly label for the other form field
 */
function requireIfOtherNotEmpty(fieldName,alias,otherFieldName,otherAlias){
  addToCheckList(fieldName,alias,"requireIfOtherNotEmpty",{fieldName:otherFieldName, alias:otherAlias});
}

/**
 * @deprecated
 * Adds the two fields to be checked, so that the form is only
 * valid if BOTH are empty or BOTH contain a value.
 *
 * @param firstFieldName,secondFieldName - the form field names
 * @param firstAlias, secondAlias - more user-friendly label for form fields
 */
function mutuallyRequire(firstFieldName,firstAlias,secondFieldName,secondAlias){
  addToCheckList(firstFieldName,firstAlias,  "requireIfOtherNotEmpty",{fieldName:secondFieldName, alias:secondAlias});
  addToCheckList(secondFieldName,secondAlias,"requireIfOtherNotEmpty",{fieldName:firstFieldName,   alias:firstAlias});

}

/**
 * @deprecated
 * Adds the fieldName to be checked for a non-null value when the form is submitted.
 *
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 */
function require(fieldName,alias) {
  addToCheckList(fieldName,alias,"required",true);
}

/**
 * @deprecated
 * Adds the fieldName to be checked for a valid email address when the form is submitted.
 *
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 */
function emailAddress(fieldName,alias) {
  addToCheckList(fieldName,alias,"requireValidEmail",true);
}


/**
 * @deprecated
 * Adds the fieldName to be checked for a numeric value when the form is submitted.
 *
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 */
function numeric(fieldName,alias) {
  addToCheckList(fieldName,alias,"requireNumeric",true);
}

/**
 * @deprecated
 * Adds the fieldName to be checked for a minimum value when the form is submitted.
 *
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 * @param min       - the minimum acceptable value
 */
function minimum(fieldName,alias,min) {
  addToCheckList(fieldName,alias,"minValue",min);
}

/**
 * @deprecated
 * Adds the fieldName to be checked for a maximum value when the form is submitted.
 *
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 * @param max       - the maximum acceptable value
 */
function maximum(fieldName,alias,max) {
  addToCheckList(fieldName,alias,"maxValue",max);
}


/**
 * @deprecated
 * Adds the fieldName to be checked for a valid date when the form is submitted.
 *
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 */
function validDate(fieldName,alias) {
  addToCheckList(fieldName,alias,"requireValidDate",true);
}

/**
 * @deprecated
 * Adds the fieldName to be checked when the form is submitted.
 * Field can only contain A-z, a-z and underscore(_).
 *
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 */
function alphaPlusUnderscore(fieldName,alias) {
  addToCheckList(fieldName,alias,"requireAlphaPlusUnderscore",true);
}

/**
 * @deprecated
 * Adds the fieldName to be checked when the form is submitted.
 * Field can only contain A-z, a-z, 0-9 and underscore(_).
 *
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 */
function alphaNumericPlusUnderscore(fieldName,alias) {
  addToCheckList(fieldName,alias,"requireAlphaNumericPlusUnderscore",true);
}

/**
 * @deprecated
 * Adds the fieldName to be checked for no whitespace when the form is submitted.
 *
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 */
function noWhitespace(fieldName,alias) {
  addToCheckList(fieldName,alias,"requireNoWhitespace",true);
}


/**
 * @deprecated
 * Adds the fieldName to be checked for a valid protein sequence when the form is submitted.
 *
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 */
function validProteinSequence(fieldName,alias) {
  addToCheckList(fieldName,alias,"requireValidProteinSequence",true);
}


/**
 * @deprecated
 * Adds the fieldName to be checked for a valid DNA sequence when the form is submitted.
 *
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 */
function validDnaSequence(fieldName,alias) {
  addToCheckList(fieldName,alias,"requireValidDnaSequence",true);
}

/**
 * @deprecated
 * Adds the fieldName to be checked for a valid DNA sequence when the form is submitted.
 *
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 */
function validDnaOrProteinSequence(fieldName,alias) {
  addToCheckList(fieldName,alias,"requireValidDnaOrProteinSequence",true);
}


/**
 * @deprecated
 * Adds the fieldName to be checked for a valid hyperlink when the form is submitted.
 *
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 */
function validHyperlink(fieldName,alias) {
  addToCheckList(fieldName,alias,"requireValidHyperlink",true);
}


/**
 * @deprecated
 * Adds the fieldName to be checked as between two values (inclusive) when the form is submitted.
 *
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 * @param min       - the minimum acceptable value
 * @param max       - the maximum acceptable value
 */
function range(fieldName,alias,min,max) {
  addToCheckList(fieldName,alias,"minValue",min);
  addToCheckList(fieldName,alias,"maxValue",max);
}

/**
 * @deprecated
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 */
function wholeNumber(fieldName,alias) {
  addToCheckList(fieldName,alias,"requireNumeric",true)
  addToCheckList(fieldName,alias,"requireWholeNumber",true)
}

/**
 * @deprecated
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 */
function javaInt(fieldName,alias) {
  wholeNumber(fieldName,alias);
  range(fieldName,alias,-2147483648,2147483647)
}

/**
 * @deprecated
 * @param fieldName - the form field we need to check
 * @param alias     - a more user-friendly label for the form field
 */
function javaLong(fieldName,alias) {
  wholeNumber(fieldName,alias);
  range(fieldName,alias,-9223372036854775000,9223372036854775000)
}




/**
 * @deprecated
 * Adds the fieldName to be checked for a specific value or condition when the form is submitted.
 *
 * fieldName - the form field we need to check
 * alias     - a more user-friendly label for the form field
 * check     - what kind of check needs to be performed
 * value     - for range checks, a numeric value, otherwise should be true
 */
function addToCheckList(fieldName,alias,checkNeeded,requiredValue) {
  if(console && console.error){
  	console.error(fieldName+"('"+alias+"') uses deprecated validation '"+checkNeeded+"'");
  }	

  if(!fieldsForValidation) {
    fieldsForValidation=new Array();
    document.forms[1].onsubmit = validateFields;
  }

  //try to find existing array for this field name - if no luck, create it
  var indexOfField=-1;
  for(i=0;i<fieldsForValidation.length;i++){
    if(fieldName==fieldsForValidation[i]["name"]){
      indexOfField=i;
      break;
    }
  }
  if(-1==indexOfField) {
    indexOfField=fieldsForValidation.length;
    fieldsForValidation[indexOfField]=new Array();
    fieldsForValidation[indexOfField]["name"] = fieldName;
    fieldsForValidation[indexOfField]["alias"]= alias;
  }

  var field=fieldsForValidation[indexOfField];
  if(!field["checks"]) {field["checks"]=new Array();}
  var numChecks=field["checks"].length;

  if("requireNumeric"==checkNeeded || "requireWholeNumber"==checkNeeded ||
	     "maxValue"==checkNeeded || "minValue"==checkNeeded){
    var theNumericChecks=-1;
    for(i=0;i<numChecks;i++){
      if(field["checks"][i]["requireNumeric"]){
        theNumericChecks=i;
	break;
      }
    }
    if(-1==theNumericChecks){
      theNumericChecks=field["checks"].length;
      field["checks"][theNumericChecks]=new Array();
      field["checks"][theNumericChecks]["requireNumeric"]=true;
    }
    if("requireWholeNumber"==checkNeeded) { field["checks"][theNumericChecks]["requireWholeNumber"]=true; }
    if("minValue"==checkNeeded) { field["checks"][theNumericChecks]["minValue"]=requiredValue; }
    if("maxValue"==checkNeeded) { field["checks"][theNumericChecks]["maxValue"]=requiredValue; }
  } else {
    //not a numeric check
    numChecks=field["checks"].length;
    field["checks"][numChecks]=new Array();
    field["checks"][numChecks][checkNeeded]=requiredValue;
  }
}

/**
 * @deprecated
 * Validates form fields prior to form submission.
 *
 */
function validateFields() {

  hasErrors = false;
  var errorMessage = "Please correct the following:\n";
  var errorLine=""; //used for building individual lines in the error
  fieldValue="";
  firstErrorField="";

  for(f=0; f<fieldsForValidation.length;f++) { //iterate through fields
    var field=fieldsForValidation[f];
    var fieldHasErrors=false;
    var fieldName=field["name"];
    var fieldAlias=field["alias"];
    // if there's no field by this name, go on to the next
    // - could happen if it's a hidden input with a fixed value, or....
    if(!document.forms[1][fieldName]) {
      continue;
    }
    //trim whitespace in field
    fieldValue= document.forms[1][fieldName].value;
    fieldValue=trim(fieldValue);
    document.forms[1][fieldName].value = fieldValue;

    for(c=0; c<field["checks"].length;c++) { //iterate through checks on each field
      var thisCheck=field["checks"][c];

      //check if required field
      if(thisCheck["required"] && (fieldValue=="" || fieldValue==null))  {
	fieldHasErrors=true;
	errorMessage += "\n* " + fieldAlias + " is required.";
      }
      //check if required because another field is populated
      if(thisCheck["requireIfOtherNotEmpty"]
           && (fieldValue=="" || fieldValue==null)
           && ("" != document.forms[1][thisCheck["requireIfOtherNotEmpty"]["fieldName"]].value)
           && (null!=document.forms[1][thisCheck["requireIfOtherNotEmpty"]["fieldName"]].value))  {
        fieldHasErrors=true;
        otherAlias=thisCheck["requireIfOtherNotEmpty"]["alias"];
        errorMessage += "\n* " + fieldAlias + " is required, because "+otherAlias+" is not empty.";
      }
      //check if valid position field
      if(thisCheck["validHolderPosition"] && fieldValue!="" && ! isValidHolderPosition(fieldValue))  {
        fieldHasErrors=true;
        errorMessage += "\n* " + fieldAlias + " should contain first letter in the range from A->P, and second digit from 0->9.";
      }
      //check for no whitespace
      if(thisCheck["requireNoWhitespace"] && fieldValue!="" && !hasNoWhitespace(fieldValue)) {
        fieldHasErrors=true;
        errorMessage += "\n* " + fieldAlias + " cannot contain any spaces, tabs or newlines.";
      }
      //check if should be valid email
      if(thisCheck["requireValidEmail"] && fieldValue!="" && !isValidEmail(fieldValue)) {
        fieldHasErrors=true;
        errorMessage += "\n* " + fieldAlias + " must be a valid email address.";
      }
      //check if should be alpha plus underscore
      if(thisCheck["requireAlphaPlusUnderscore"] && fieldValue!="" && !isAlphaPlusUnderscore(fieldValue)) {
        fieldHasErrors=true;
        errorMessage += "\n* " + fieldAlias + " must contain only letters and underscores (_).";
      }
      //check if should be alphanumeric plus underscore
      if(thisCheck["requireAlphaNumericPlusUnderscore"] && fieldValue!="" && !isAlphaNumericPlusUnderscore(fieldValue)) {
        fieldHasErrors=true;
        errorMessage += "\n* " + fieldAlias + " must contain only letters, numbers and underscores (_).";
      }
      //check if should be valid DNA sequence
      var WHITE_SPACE = new RegExp("\s", "g");
      if (thisCheck["requireValidDnaSequence"]) {
        fieldValue.replace(WHITE_SPACE,""); // strip white space
        document.forms[1][fieldName].value = fieldValue;
      }
      if(thisCheck["requireValidDnaSequence"] && fieldValue!="" && !isValidDnaSequence(fieldValue)) {
        fieldHasErrors=true;
        errorMessage += "\n* " + fieldAlias + " must be a valid DNA sequence.";
      }
      //check if should be valid protein sequence
      if(thisCheck["requireValidProteinSequence"] && fieldValue!="" && !isValidProteinSequence(fieldValue)) {
        fieldHasErrors=true;
        errorMessage += "\n* " + fieldAlias + " must be a valid protein sequence.";
      }
      //check if should be valid protein sequence
      if(thisCheck["requireValidDnaOrProteinSequence"] && fieldValue!="" && !isValidDnaOrProteinSequence(fieldValue)) {
        fieldHasErrors=true;
        errorMessage += "\n* " + fieldAlias + " must be a valid DNA or protein sequence.";
      }
      //check if should be valid hyperlink
      if(thisCheck["requireValidHyperlink"] && fieldValue!="" && !isValidHyperlink(fieldValue)) {
        fieldHasErrors=true;
        errorMessage += "\n* " + fieldAlias + " must be a valid hyperlink.";
      }
      //check if should be valid date
      if(thisCheck["requireValidDate"] && fieldValue!="") {
        if(!isDateFormat(fieldValue)) {
          fieldHasErrors=true;
          errorMessage += "\n* " + fieldAlias + " must be a date, in the format DD/MM/YYYY.";
        } else if (!isValidDate(fieldValue)) {
    	  fieldHasErrors=true;
	      errorMessage += "\n* " + fieldAlias + " must be a valid date, in the format DD/MM/YYYY.";
        }
      }
      //check whether numeric and within range, if appropriate
      if(thisCheck["requireNumeric"] || thisCheck["minValue"] || thisCheck["maxValue"]) {
      if(!isNumeric(fieldValue) && fieldValue!="") {
        fieldHasErrors=true;
        errorLine = "\n* "+ fieldAlias + " must be a number";
        if(null!=thisCheck["minValue"] && null!=thisCheck["maxValue"]) {
            errorLine += " between "+ thisCheck["minValue"] +" and "+ thisCheck["maxValue"] +".";
          } else if(null!=thisCheck["minValue"]) {
            errorLine += " not less than "+ thisCheck["minValue"] +".";
          } else if(null!=thisCheck["maxValue"]) {
            errorLine += " not greater than "+ thisCheck["maxValue"] +".";
          } else {
            errorLine += ".";
          }
          errorMessage += errorLine + "";
        } else if(fieldValue!="") {
          //value is numeric
//          if(thisCheck["requireWholeNumber"] && Math.abs(fieldValue*1) != parseInt(Math.abs(fieldValue*1))) {
          if(thisCheck["requireWholeNumber"] && !isWholeNumber(fieldValue)) {
            fieldHasErrors=true;
            errorMessage += "\n* " + fieldAlias + " must be a whole number.";
          } else if(null!=thisCheck["minValue"] && null!=thisCheck["maxValue"] && fieldValue!="" && (fieldValue<thisCheck["minValue"] || fieldValue>thisCheck["maxValue"])) {
          //value is out of specified range
            fieldHasErrors=true;
            errorMessage += "\n* " + fieldAlias + " must be between "+ thisCheck["minValue"] +" and "+ thisCheck["maxValue"] +".";
          } else if (null!=thisCheck["minValue"] && fieldValue<thisCheck["minValue"]) {
          //value is below minimum
            fieldHasErrors=true;
            errorMessage += "\n* " + fieldAlias + " must not be less than "+ thisCheck["minValue"] +".";
          } else if (null!=thisCheck["maxValue"] && fieldValue>thisCheck["maxValue"]) {
          //value is above maximum
            fieldHasErrors=true;
            errorMessage += "\n* " + fieldAlias + " must not be greater than "+ thisCheck["maxValue"] +".";
          } else {
            //everything's OK
          }
        }
      }
      if(fieldHasErrors) {
        if(firstErrorField==("")) { firstErrorField=fieldName; }
        highlightField(fieldName);
        hasErrors=true;
      } else {
        clearHighlight(fieldName);
      }
    } //end iteration through checks on this field
  }//end iteration through fieldsForValidation
  if(hasErrors) {
    alert(errorMessage);
  if(firstErrorField!=("")) {
    eval('document.forms[1]["'+firstErrorField+ '"].focus();');
  }
  return false;
}


} //end of function validateFields()


/**
 * @deprecated
 * Returns true if stringToTest has no whitespace
 */
function hasNoWhitespace(stringToTest) {
  regEx = /\s/;
  return !regEx.test(stringToTest);
}


/**
 * @deprecated
 * Returns true if string consists entirely of the following characters:
 * Upper case A-Z, lower case a-z, numerals 0-9, underscore (_)
 */
function isAlphaNumericPlusUnderscore(stringToTest) {
  regEx = /^[A-Za-z0-9_]*$/;
  return regEx.test(stringToTest);
}

/**
 * @deprecated
 * Returns true if string consists entirely of the following characters:
 * Upper case A-Z, lower case a-z, underscore (_)
 */
function isAlphaPlusUnderscore(stringToTest) {
  regEx = /^[A-Za-z_]*$/;
  return regEx.test(stringToTest);
}

/*******************************************************************************
 End of deprecated form validation functions
 *******************************************************************************/

/**
 * used by <pims:inputamount> in inputsamples.jsp outputsamples.jsp viewsample.jsp
 */
function sampleOnChange(field, prop){
    //alert("sampleOnChange ["+field.name+":"+prop+"]");
	var index = field.name.lastIndexOf(':');
	var basename = field.name.substring(0,index);
	var amountElement = basename+":"+prop;
	var valueElement = basename+":value";
	var unitsElement = basename+":units";
	var value = field.form.elements[valueElement].value;
	var units = field.form.elements[unitsElement].value;
	if(!isNumeric(value))
		alert("Amount value must be numeric");
	field.form.elements[amountElement].value=value+units;
}

/**
 * This function is used in Leeds sequencing management CompletedSO.jsp and ListPlateSOrdersWithFiles.jsp
 * To display copying... test and send data to the servlet 
 * @param form
 * @return
 */
function wait(form) { 
	if(confirm('Copy experiments to the new Order?')) { 
		var id = $(form).id; 
		var orderId = id.substring('orderForCopying'.length,id.length);
		$('copyHolder'+orderId).innerHTML='Copying' + "<span style='text-decoration: blink'>...</span>"; 
		$(form).submit();
	}
}