// $Id: form_utilities.js,v 1.40 2011-01-06 12:06:38 nelf Exp $

var d = document;	
var isVerbose = false;
var isTags = true;

function gId(sIdentity){
    
    // Replaces document.getElementById()
    
    if (d.getElementById){
	return d.getElementById(sIdentity);
    }else{
	verboseDisplay("This browser does not support document.getElementById()");
    }
}

function verboseDisplay(sText){
    if (!isVerbose){return;}
    var oBody = d.getElementsByTagName("body")[0];
    var oVerbose = d.createElement('pre');
    oVerbose.setAttribute('class', "cpep-verbose"); 
    oVerbose.appendChild(d.createTextNode('Verbose: "'+sText+'"'));	
    oBody.appendChild(d.createElement('hr'));
    oBody.appendChild(oVerbose);	
}


function tagsDisplay(oDocumentation){

    // This function takes a json data structure of all the tags available to use within a page and appends them to the document (d).

    if (!isTags){return;}
    var iNumProps = 0;
    for (var iProp in oDocumentation) { iNumProps++; }
    if(!iNumProps) return;

    var oBody = d.getElementsByTagName("body")[0];

    var oVerbose = d.createElement('div');
    oVerbose.setAttribute('id', "cpep-tag-holder"); 

    var oHeader = d.createElement('h1');
    oHeader.appendChild(d.createTextNode("Available dolnml tags\u00A0\u00A0"));
    var oLink = d.createElement('a');
    oLink.appendChild(d.createTextNode("(show)"));
    oLink.onclick = function(){
	if (this.parentNode.nextSibling.style.display == "block"){
	    this.parentNode.nextSibling.style.display="none";
	    this.parentNode.nextSibling.style.visibility = "hidden";
	    this.firstChild.nodeValue = "(show)";
	}else{
	    this.parentNode.nextSibling.style.display="block";
	    this.parentNode.nextSibling.style.visibility = "visible";
	    this.firstChild.nodeValue = "(hide)";
	}
    }	   
    
    oHeader.appendChild(oLink);
    oVerbose.appendChild(oHeader); 

    var oVerbose_holder = d.createElement('div');
    oVerbose_holder.className='cpep-tag-switchable-holder';
    
    for (var oHeading in oDocumentation){
	oTagClass = oDocumentation[oHeading];
	
	// Apply a header for each type=xxxx available

	var oHolder = d.createElement('div');
	oHolder.className = 'cpep-type-holder'; 

	var oHeader = d.createElement('h2');
	oHeader.appendChild(d.createTextNode(oHeading+"\u00A0\u00A0"));
	var oLink = d.createElement('a');
	oLink.appendChild(d.createTextNode("(show available tags)"));
	oLink.onclick = function(){
	    if (this.parentNode.nextSibling.style.display == "block"){
		this.parentNode.nextSibling.style.display="none";
		this.parentNode.nextSibling.style.visibility = "hidden";
		this.firstChild.nodeValue = "(show available tags)";
	    }else{
		this.parentNode.nextSibling.style.display="block";
		this.parentNode.nextSibling.style.visibility = "visible";
		this.firstChild.nodeValue = "(hide available tags)";
	    }
	}	   

	oHeader.appendChild(oLink);
	oHolder.appendChild(oHeader);

	// Now run through each data=xxxx tag available

	var oHolder_inner = d.createElement('div');
	oHolder_inner.className = 'cpep-data-holder';
	
	
	if (oTagClass.tags){
	    for (var x=0; x<oTagClass.tags.length; x++){
		var oTag = oTagClass.tags[x];
		
		oHeader = d.createElement('h3');
		if(oTagClass.type=='loop') {
		    oHeader.appendChild(d.createElement('br'));
		    oHeader.appendChild(d.createTextNode("<!--\u00A0[?\u00A0dolnml\u00A0type=begin\u00A0data="+oTag.name+"\u00A0?] -->"));
		    oHeader.appendChild(d.createElement('br'));
		    oSpan = d.createElement('span');
		    oSpan.setAttribute("style","color:#cc33ff");
		    oSpan.appendChild(d.createTextNode("\u00A0\u00A0\u00A0\u00A0 You may use extra tags between these two. See \"show loop contents\" for details."));
		    oHeader.appendChild(oSpan);
		    oHeader.appendChild(d.createElement('br'));
		    oHeader.appendChild(d.createTextNode("<!--\u00A0[?\u00A0dolnml\u00A0type=end\u00A0data="+oTag.name+"\u00A0?] -->"));
		    oHeader.appendChild(d.createElement('br'));
		    oHeader.appendChild(d.createElement('br'));
		    oHeader.appendChild(d.createTextNode("<!--\u00A0[?\u00A0dolnml\u00A0type=begin_empty\u00A0data="+oTag.name+"\u00A0?] -->"));
		    oHeader.appendChild(d.createElement('br'));
 oSpan = d.createElement('span');
		    oSpan.setAttribute("style","color:#cc33ff");
		    oSpan.appendChild(d.createTextNode("\u00A0\u00A0\u00A0\u00A0 Any HTML placed between these two will only appear if there are no database rows returned."));
		    oHeader.appendChild(oSpan);
		    oHeader.appendChild(d.createElement('br'));
		    oHeader.appendChild(d.createTextNode("<!--\u00A0[?\u00A0dolnml\u00A0type=end_empty\u00A0data="+oTag.name+"\u00A0?] -->\u00A0\u00A0"));

		    var oLink = d.createElement('a');
		    oLink.appendChild(d.createTextNode("(show loop contents)"));
		    
		    oLink.onclick = function(){
			if (this.parentNode.nextSibling.style.display == "block"){
			    this.parentNode.nextSibling.style.display="none";
			    this.parentNode.nextSibling.style.visibility = "hidden";
			    this.firstChild.nodeValue = "(show loop contents)";
			}else{
			    this.parentNode.nextSibling.style.display="block";
			    this.parentNode.nextSibling.style.visibility = "visible";
			    this.firstChild.nodeValue = "(hide loop contents)";
			}
		    }

		} else {
		    oHeader.appendChild(d.createTextNode(oTag.name+"\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0 [?\u00A0dolnml\u00A0type="+oTagClass.type+"\u00A0data="+oTag.name+"\u00A0?]\u00A0\u00A0"));
		    
		    var oLink = d.createElement('a');
		    oLink.appendChild(d.createTextNode("(show value)"));
		    
		    oLink.onclick = function(){
			if (this.parentNode.nextSibling.style.display == "block"){
			    this.parentNode.nextSibling.style.display="none";
			    this.parentNode.nextSibling.style.visibility = "hidden";
			    this.firstChild.nodeValue = "(show value)";
			}else{
			    this.parentNode.nextSibling.style.display="block";
			    this.parentNode.nextSibling.style.visibility = "visible";
			    this.firstChild.nodeValue = "(hide value)";
			}
		    }
		}
		oHeader.appendChild(oLink);
		
		oHolder_inner.appendChild(oHeader);
		    
		    
		var oValue =  d.createElement('pre');
		oValue.setAttribute('id', oHeading+"-"+oTag.name); 
		oValue.className = "cpep_tag_values"; 
		oValue.appendChild(d.createTextNode(oTag.value));
		oHolder_inner.appendChild(oValue);	
		oHolder.appendChild(oHolder_inner);	
		oVerbose_holder.appendChild(oHolder);

	    }
	}
    }
    oVerbose.appendChild(oVerbose_holder);
    oBody.appendChild(oVerbose);

}



function getCookie_value(offset){
    var sEnd = d.cookie.indexOf(";" , offset);
    if (sEnd == -1){
	sEnd = d.cookie.length;
    }
    return unescape(d.cookie.substring(offset,sEnd));
}

function appendCookie(){
    // A defence against the dark art of Cross Site Request Forgery
    //   this function should append the cookie to each get request
    //   and as a value in a hidden field for each form request

    if (!d.cookie){return false;}

    var sCookie = getCookie_value(0);

    // Create a hidden field object which holds the cookie
    var oHidden_field = d.createElement('input');
    oHidden_field.setAttribute('type','hidden');	
    oHidden_field.setAttribute('name','token');	
    oHidden_field.setAttribute('value', sCookie);	

    // Attach the hidden cookie field to each form
    var aForms = d.getElementsByTagName("form");
    for (var x=0; x<aForms.length; x++){
	aForms[x].appendChild(oHidden_field);
    }

    sCookie = encodeURI(sCookie);

    // Now to handle the links

    var aLinks = d.getElementsByTagName("a");
    var sOut='';
    for (x=0; x<aLinks.length; x++){
	if (aLinks[x].href.indexOf('?') == -1){
	    aLinks[x].href+= '?token='+sCookie;	
	}else{
	    aLinks[x].href+= '&token='+sCookie;
	}
	sOut+= aLinks[x].href+'\n';
    }
    alert(sOut);
}

function convertCharEntitiesToChars(sOldText) {
    
    sOldText = sOldText.toString();
    
    rExpression = /&nbsp;/g;
    sOldText = sOldText.replace(rExpression, '\u00A0');
    rExpression = /&eacute;/g;
    sOldText = sOldText.replace(rExpression, '\u00e9');
    rExpression = /&Eacute;/g;
    sOldText = sOldText.replace(rExpression, '\u00c9');
    rExpression = /&amp;/g;
    sOldText = sOldText.replace(rExpression, '&');
    rExpression = /&euro;/g;
    sOldText = sOldText.replace(rExpression, '\u20ac');
    rExpression = /&atilde;/g;
    sOldText = sOldText.replace(rExpression, '\u00e3');
    rExpression = /&oacute;/g;
    sOldText = sOldText.replace(rExpression, '\u00f3');

    var sVerbose = 'Called /shared_javascript/form_utilities.js :: convertCharEntitiesToChars("'+sOldText+'").\nThis function converts various character entities to unicode.\nReturning the value: '+sOldText;
    verboseDisplay(sVerbose);

    return sOldText;
}

function selectPopulate(data, select_id, current) {

    for (i = 0; i < data.length; i++) {
	var oOption = new Option();
	oOption.value = data[i][0];
	oOption.text = convertCharEntitiesToChars(data[i][1]);
	gId(select_id).options[i] = oOption;
	if (current != null && oOption.value == current) {
	    gId(select_id).options[i].selected = true;
	}
    }
}

// The following function will replace entirely the previous one at some point
// This function takes an array of OptionItems().

function selectPopulateNew(data, select_id, current) {
    
    var select_element = gId(select_id);

    // Empty the list unless it contains actual values
    for (i=0; i<select_element.length; i++) {
	if(select_element.options[i].value.length==0 && select_element.options[i].text.length==0) {
	    select_element.options[i] = null;
	}
    }
    var iSelectIndex = select_element.options.length;
    //  Populate the list.
    for (i = 0; i < data.length; i++) {
	data[i].text = convertCharEntitiesToChars(data[i].text);
	select_element.options[iSelectIndex]  = new Option(data[i].text, data[i].value);
	if (current != null && data[i].value == current) {
	    select_element.options[i].selected = true;
	}
	iSelectIndex++;
    }
}

function displayProperties(oObject){
    var sNames = "";
    for (var sName in oObject){
	sNames += sName + ": "+ oObject[sName]+"\n";
	
    }
    alert(sNames);
}

// Similar to selectPopulateNew, but accepts a json data structure
// and builds the options using the DOM.
// Removes any existing <options> unless they have a 'value' attribute set.

function selectPopulateJSON(aOptions, sIdentity, sValue) {
    

    var isRemove_all; // This option ignores whether an option has a 
    // value and removes it anyway. Use it to clear the select rather 
    // than add.
    
    if (arguments.length > 3){
	isRemove_all = arguments[3] ?  true : false;
    };
    
    var oSelectNode = gId(sIdentity);

    
    var aChildren = oSelectNode.childNodes;

    
    for (var i=0; i < aChildren.length; i++) {
    	if(aChildren[i].nodeName == 'OPTION'){
    	    if(isRemove_all || aChildren[i].value.length == 0) {
    		oSelectNode.removeChild(aChildren[i]);
		i = -1;
 	    }
	}
    } 
    

    for (var i=0; i < aOptions.length;i++) {
	var oOption = d.createElement('option');
	oOption.setAttribute('value',aOptions[i].value);
	if (sValue != null && aOptions[i].value == sValue) {
	    oOption.setAttribute('selected',true);
	}
	
	oOption.appendChild(d.createTextNode(convertCharEntitiesToChars(aOptions[i].textNode)));
	
	oSelectNode.appendChild(oOption);
    }

    var sVerbose = 'Called /shared_javascript/form_utilities.js :: selectPopulateJSON(aOptions, '+sIdentity+', '+sValue+').\nThis function takes a JSON data structure and populates a dropdown select box.\nIf the third argument is set it is used to set selected="selected"\nReturns nothing';
    verboseDisplay(sVerbose);

}

function selectPopulateDependentJSON(oJSON, sIdentity_1 , sIdentity_2){
    
    var aChildren = [];
    for (x=0; x<oJSON.length; x++){
	if (gId(sIdentity_1).options[gId(sIdentity_1).selectedIndex].value == oJSON[x].value){
	    aChildren = oJSON[x].children;
	}
    }
 
    selectPopulateJSON(aChildren, sIdentity_2 ,'unselected',true);      
}

function removeChildNodes (oNode) {
    
	var aChildren = oNode.childNodes;
	for (var i=0; i < aChildren.length; i++) {	
	    oNode.removeChild(aChildren[i]);
	    i=-1;
	}
}

// Same as selectPopulateNew but it replaces the previous contents regardless

function selectPopulateReplace(data, select_id, current) {
    
    var select_element = gId(select_id);

    // Empty the list regardless of if it contains actual values
    //  working backwards as select object.length changes
    //  dynamically.
    for (i=select_element.length; i>=0; i--) {
	select_element.options[i] = null;
    }
    var iSelectIndex = select_element.options.length;
    //  Populate the list.
    for (i = 0; i < data.length; i++) {
	data[i].text = convertCharEntitiesToChars(data[i].text);
	select_element.options[iSelectIndex]  = new Option(data[i].text, data[i].value);
	if (current != null && data[i].value == current) {
	    select_element.options[i].selected = true;
	}
	iSelectIndex++;
    }
}

function selectPopulateMultiple(aOption_items, sIdentity, aCurrent) {
    
    // This function populates a multi-select box with id of sIdentity
    //   with the array of options in aOption_items
    //   selecting each of the values in the array aCurrent 
    
    var oSelect = gId(sIdentity);
    // Empty the list
    for (i=0; i < oSelect.length; i++) {
	oSelect.options[i] = null;
    }
    //  Populate the list.
    for (i = 0; i < aOption_items.length; i++) {
	aOption_items[i].text = convertCharEntitiesToChars(aOption_items[i].text);
	oSelect.options[i]  = new Option(aOption_items[i].text, aOption_items[i].value);
	// Check if the option is on the current list
	for (j = 0; j < aCurrent.length; j++) {
	    if (aCurrent[j] != null && aOption_items[i].value == aCurrent[j]) {
		oSelect.options[i].selected = true;
	    }
	}
    }
}


// This generic function is used for populating dropdown date boxes.
// They require a set of three <select> tags.
// The function takes a 'stem' parameter, and then looks for three arrays
// to provide the data to populate the dropdowns:
//   stem_days, stem_months, stem_years.
// The function then looks for three variables:
//   stem_day, stem_month and stem_year
// And sets the three <select> tags, which should be named:
//   stem-days, stem-months, stem-years
//
function date_dropdown(stem) {
    for (i = 0; i < eval(stem + '_days').length; i++) {
	var oOption = new Option();
	oOption.value = eval(stem + '_days')[i][0];
	oOption.text = eval(stem + '_days')[i][1];
	gId(stem + '-days').options[i]=oOption;
	
	if(oOption.value == eval(stem + '_day')) {
	    oOption.selected = true;
	}
    }
    
    for (i = 0; i < eval(stem + '_months').length; i++) {
	var oOption = new Option();
	oOption.value = eval(stem + '_months')[i][0];
	oOption.text = eval(stem + '_months')[i][1];
	gId(stem + '-months').options[i]=oOption;
	    
	if(oOption.value == eval(stem + '_month')) {
	    oOption.selected = true;
	}
    }
    
    for (i = 0; i < eval(stem + '_years').length; i++) {
	var oOption = new Option();
	oOption.value = eval(stem + '_years')[i][0];
	oOption.text = eval(stem + '_years')[i][1];
	gId(stem + '-years').options[i]=oOption;
	    
	if(oOption.value == eval(stem + '_year')) {
	    oOption.selected = true;
	}
    }

    // Fail silently for following
    try {
	if(eval(stem + '_hours') && gId(stem + '-hours')){
	    // nothing
	} else {
	    return;
	}
    } catch(e) {
	return; 
    }
	
    for (i = 0; i < eval(stem + '_hours').length; i++) {
	var oOption = new Option();
	oOption.value = eval(stem + '_hours')[i][0];
	oOption.text = eval(stem + '_hours')[i][1];
	gId(stem + '-hours').options[i]=oOption;
	
	if(oOption.value == eval(stem + '_hour')) {
	    oOption.selected = true;
	}
    }

    // Fail silently for following
    try { 
	if(!eval(stem + '_minutes') || !gId(stem + '-minutes')){ return; }
    } catch(e) { return; }
	
    for (i = 0; i < eval(stem + '_minutes').length; i++) {
	var oOption = new Option();
	oOption.value = eval(stem + '_minutes')[i][0];
	oOption.text = eval(stem + '_minutes')[i][1];
	gId(stem + '-minutes').options[i]=oOption;
	
	if(oOption.value == eval(stem + '_minute')) {
	    oOption.selected = true;
	}
    }



    // Fail silently for following
    try {
	if(eval(stem + '_seconds') && gId(stem + '-seconds')){
	    // nothing
	} else {
	    return;
	}
    } catch(e) {
	return; 
    }
	
    for (i = 0; i < eval(stem + '_seconds').length; i++) {
	var oOption = new Option();
	oOption.value = eval(stem + '_seconds')[i][0];
	oOption.text = eval(stem + '_seconds')[i][1];
	gId(stem + '-seconds').options[i]=oOption;
	
	if(oOption.value == eval(stem + '_second')) {
	    oOption.selected = true;
	}
    }

}

// The following are for ordering of lists.

function fillList(listElement, orderArray, orderHiddenElement) {
    
    //This function runs a "join" on all the list values in order,
    //  split with commas 
    
    var sList = "";
    
    for (i=0; i<orderArray.length; i++){
	if (i<orderArray.length-1){
	    sList += orderArray[i].value + ','; 
	}else{
	    sList += orderArray[i].value;
	}
    }
    orderHiddenElement.value = sList;
    //gId('item_order').value = sList;
}

function moveOptionNodeUp (oSelect){
    var aKids = oSelect.childNodes;

    for(var i = 0; i<aKids.length; i++) {
	if(i 
	   && aKids[i].nodeName == 'OPTION' 
	   && aKids[i].selected) {
	    // Swap with previous unselected OPTION node
	    for(var j = i-1; j>=0;j--) {
		if(aKids[j].nodeName == 'OPTION' 
		   && !aKids[j].selected) {
		    var tempNodeI = aKids[i].cloneNode(true);
		    var tempNodeJ = aKids[j].cloneNode(true);
		    oSelect.replaceChild(tempNodeI,aKids[j]);
		    oSelect.replaceChild(tempNodeJ,aKids[i]);
		    aKids[j].selected=true;
		    j=-1;
		}
	    }
	}
    }
}

function moveOptionNodeDown (oSelect){
    var aKids = oSelect.childNodes;
    for(var i = aKids.length - 1; i>=0; i--) {
	if(i < aKids.length - 1
	   && aKids[i].nodeName == 'OPTION' 
	   && aKids[i].selected) {
	    // Swap with next unselected OPTION node
	    for(var j = i+1; j<aKids.length;j++) {
		if(aKids[j].nodeName == 'OPTION' 
		   && !aKids[j].selected) {
		    var tempNodeI = aKids[i].cloneNode(true);
		    var tempNodeJ = aKids[j].cloneNode(true);
		    oSelect.replaceChild(tempNodeI,aKids[j]);
		    oSelect.replaceChild(tempNodeJ,aKids[i]);
		    aKids[j].selected=true;
		    j=aKids.length+1;
		}
	    }
	}
    }
}

function moveUp(listElement, orderArray, orderHiddenElement){ // was listHandle
    if (listElement.selectedIndex == 0){
	return;
    }
    
    //cache the one to move
    
    var iIndex = listElement.selectedIndex;
    var oHolder = orderArray[iIndex];
    
    //Move the above option down in the array
    orderArray[iIndex] = orderArray[iIndex-1];
    // and in the list
    
    listElement.options[iIndex].value = orderArray[iIndex].value;
    listElement.options[iIndex].text = orderArray[iIndex].text;
    
    //then put the cached option back
    orderArray[iIndex-1] = oHolder;
    
    listElement.options[iIndex-1].value = oHolder.value;
    listElement.options[iIndex-1].text = oHolder.text;
    
    listElement.selectedIndex = iIndex-1;
    
    fillList(listElement,orderArray, orderHiddenElement);
    
}

function moveDown(listElement, orderArray, orderHiddenElement){
    if (listElement.selectedIndex == listElement.options.length-1){
	return;
    }
    
    //cache the one to move
    
    var iIndex = listElement.selectedIndex;
    var oHolder = orderArray[iIndex];
    
    //Move the below option up in the array
    orderArray[iIndex] = orderArray[iIndex+1];
    // and in the list
    
    listElement.options[iIndex].value = orderArray[iIndex].value;
    listElement.options[iIndex].text  = orderArray[iIndex].text;
    
    //then put the cached option back
    orderArray[iIndex+1] = oHolder;
    
    listElement.options[iIndex+1].value = oHolder.value;
    listElement.options[iIndex+1].text = oHolder.text;
    
    listElement.selectedIndex = iIndex+1;
	  
    fillList(listElement, orderArray, orderHiddenElement);
}

function optionItem (text, value){      //     Option item object constructor function
    this.text = text;
    this.value = value;
}  


function optionItemWithParent (parent,text,value){ // Option item with parent node
    this.text = text;
    this.value = value;
    this.parent = parent;
}  

function emptyList(listObject){     // Empties select list
    while ( listObject.options.length ) {listObject.options[0] = null;}
}

function checkboxValueToField(sCheckboxId, sFieldId, sOnValue, sOffValue) { // set's a field according to checkbox value

    if (sOnValue == '') sOnValue = 'yes';
    if (sOffValue == '') sOffValue = 'no';

    if (gId(sCheckboxId).checked == true) {
	gId(sFieldId).value = sOnValue;
    } else {
	gId(sFieldId).value = sOffValue;
    }
}

function selectSwap(select_id_a, select_id_b){
    oDonor_list    = gId(select_id_a);
    oReceiver_list = gId(select_id_b);
    // Add selected option from the donor list to the submit list

    for (i=0; i < oDonor_list.length; i++) {
  	if(oDonor_list.options[i]){	
	    if(oDonor_list.options[i].selected == true) {
		oReceiver_list.options[oReceiver_list.length] = new Option(oDonor_list.options[i].text, oDonor_list.options[i].value);
		oDonor_list.options[i] = null;
		i=-1; // Start again, just in case!
	    }
	}	
    }
}

// Moves any selected nodes from one select box to another
function optionNodeSwap(sFromId, sToId){
    oDonorList    = gId(sFromId);
    oReceiverList = gId(sToId);

    if(!oDonorList.hasChildNodes) { return;}
	
    var aDonorNodes = oDonorList.childNodes;
    for (i=0; i < aDonorNodes.length; i++) {
	if(aDonorNodes[i].nodeName == 'OPTION' && aDonorNodes[i].selected) {
	    aDonorNodes[i].selected = false;
	    oReceiverList.appendChild(oDonorList.removeChild(aDonorNodes[i]));
	    i=-1; // Start again as nodeLists change automatically!
	}
    }
}

function optionNodeSort(sSelectId){
    oSelectNode    = gId(sSelectId);

    if(!oSelectNode.hasChildNodes) { return;}

    var aChildren = oSelectNode.childNodes;
    var aOptions = [];
    for (i=0; i < aChildren.length; i++) {
	if(aChildren[i].nodeName == 'OPTION') {
	    aOptions.push(aChildren[i]);
	}
    }
    
    aOptions.sort(function(a,b){  
	
	var x = a.firstChild.nodeValue.toLowerCase();
	var y = b.firstChild.nodeValue.toLowerCase();
	return ((x < y) ? -1 : ((x > y) ? 1 : 0));
    });

    for (i=0; i < aOptions.length; i++) {
	oSelectNode.appendChild(oSelectNode.removeChild(aOptions[i]));
    }
}

function selectChooseByValue(sIdentity, sValue){

    // Switch on the selectedIndex of a select list
    //   depending on the value of sValue
    //   NOT for use with multiple="multiple"
    
    if (sValue != '') {
	var oList = gId(sIdentity);
	if(!oList.options) {
	    return;
	}
	for (i = 0; i < oList.options.length; i++) {
	    if (oList.options[i].value == sValue) {
		oList.options[i].selected = true;
		return;
	    }
	}
    }
}

function showDivClass(sClassName , isShow){
    
    // Shows or hides a div based on its style class
    
    if(d.getElementsByTagName){
	var aNodes = d.getElementsByTagName("div");
	var iMax = aNodes.length;
	for(var i = 0 ; i < iMax ; i++){
	    var nodeObj = aNodes.item(i);
	    var attrMax = nodeObj.attributes.length;
	    for(var j = 0; j < attrMax; j++){
		if(nodeObj.attributes.item(j).nodeName == 'class'){
		    if(nodeObj.attributes.item(j).nodeValue == sClassName){
			if (isShow){
			    nodeObj.style.display = "block";
			    nodeObj.style.visibility = "visible";
			}else{
			    nodeObj.style.display = "none";
			    nodeObj.style.visibility = "hidden";
			}}}}}}
}


function showElementClass(sElement, sClassName , isShow){
    
    // Shows or hides an element based on its style class
    
    if(d.getElementsByTagName){
	var aNodes = d.getElementsByTagName(sElement);
	var iMax = aNodes.length;
	for(var i = 0 ; i < iMax ; i++){
	    var nodeObj = aNodes.item(i);
	    var attrMax = nodeObj.attributes.length;
	    for(var j = 0; j < attrMax; j++){
		if(nodeObj.attributes.item(j).nodeName == 'class'){
		    if(nodeObj.attributes.item(j).nodeValue == sClassName){
			if (isShow){
			    nodeObj.style.display = "block";
			    nodeObj.style.visibility = "visible";
			}else{
			    nodeObj.style.display = "none";
			    nodeObj.style.visibility = "hidden";
			}}}}}}
}

function showElementsClass(aElement, sClassName , isShow){
    
    // Shows or hides an array of elements based on a style class
    
    if(d.getElementsByTagName){
	for (e = 0; e<aElement.length; e++){
	    var aNodes = d.getElementsByTagName(aElement[e]);
	    var iMax = aNodes.length;
	    for(var i = 0 ; i < iMax ; i++){
		var nodeObj = aNodes.item(i);
		var attrMax = nodeObj.attributes.length;
		for(var j = 0; j < attrMax; j++){
		    if(nodeObj.attributes.item(j).nodeName == 'class'){
			if(nodeObj.attributes.item(j).nodeValue == sClassName){
			    if (isShow){
				nodeObj.style.display = "block";
				nodeObj.style.visibility = "visible";
			    }else{
				nodeObj.style.display = "none";
				nodeObj.style.visibility = "hidden";
			    }}}}}}}
}

// Shows/hides by id (displays as block by default)
function showById (sIdentity, isShow,sDisplayType) {
    if (!sDisplayType) {
	sDisplayType='block';
    }
    if(gId && gId(sIdentity)) {
	if(isShow) {
	    gId(sIdentity).style.visibility='visible';
	    gId(sIdentity).style.display=sDisplayType;
	} else {
	    gId(sIdentity).style.visibility='hidden';
	    gId(sIdentity).style.display='none';
	}
    }
}

// The following function takes the id of a select element and 
//  returns the currently selected Value (the bit which would 
//  get returned to server)

function getSelectedValue(sSelectId){
    if (!gId(sSelectId)){
	alert("Error: The Object with the ID of "+sSelectId +" does not exist on this page.");
	return false;
    }else{
	return gId(sSelectId).options[gId(sSelectId).options.selectedIndex].value;
    }
}

// The following function takes the id of a select element and 
//  returns the currently selected Text (the bit displayed
// in the dropdown)

function getSelectedText(sSelectId){
    if (!gId(sSelectId)){
	alert("Error: The Object with the ID of "+sSelectId +" does not exist on this page.");
	return false;
    }else{
	return gId(sSelectId).options[gId(sSelectId).options.selectedIndex].text;
    }
}

function formatAPR(fAPR){
    fAPR = parseFloat(fAPR);
    sAPR = fAPR.toString();
    return (sAPR.indexOf(".")==-1)?(sAPR + ".0"):sAPR;
}


// Returns the amount formatted as cash
// (comma separated thousands,full-stop,then two digits)
format_money = function( amount, decimal_places, decimal_seperator, thousands_seperator ) {
	decimal_seperator= decimal_seperator || '.';
	thousands_seperator= thousands_seperator || ',';
	return fmtMoney(amount, decimal_places, decimal_seperator, thousands_seperator);
};

// http://www.jsfromhell.com/number/fmt-money
fmtMoney = function(n, c, d, t){
    var m = (c = Math.abs(c) + 1 ? c : 2, d = d || ",", t = t || ".",
        /(\d+)(?:(\.\d+)|)/.exec(n + "")), x = m[1].length > 3 ? m[1].length % 3 : 0;
    return (x ? m[1].substr(0, x) + t : "") + m[1].substr(x).replace(/(\d{3})(?=\d)/g,
        "$1" + t) + (c ? d + (+m[2] || 0).toFixed(c).substr(2) : "");
};

function optionItem_array_to_ul(arrayOptionItems, stringUL_id){

    // Takes a legacy CPEP array optionItem originally designed to populate                             
    //   manager dropdowns.                                                                             
    // The data is now written to a UL as a sequence of LIs                                             
    //   * The "text" value is written to the page as a link                                            
    //   * The "value" value is written to the the id attribute of the LI                               
    //     The id attribute for each LI                                                                 
    //       is given the prefix of the id of the UL (id cannot start with                              
    //       a number and must be unique)                                                               

    for (var y=0; y < arrayOptionItems.length; y++){
	var oLi = d.createElement('li');
	var oA = d.createElement('a');
	oA.appendChild(d.createTextNode(arrayOptionItems[y].text));
	oLi.appendChild(oA);
	oLi.id = stringUL_id + arrayOptionItems[y].value;
	gId(stringUL_id).appendChild(oLi);
    }   
}

function ul_to_row_order(stringUL_id,stringRow_orderID){

    // Takes a CPEP reordeable list and converts and inserts to a                                       
    //   row_order hidden field value.
    
    // Strips the id of the UL from the front of each LI id.

    var aList_items = gId(stringUL_id).getElementsByTagName("li");                                      
    var sList = aList_items[0].id.substr(stringUL_id.length);                                           
    for (i=1; i<aList_items.length; i++){                                                               
        sList += ","+(aList_items[i].id.substr(stringUL_id.length));
    }                                                                                                   
    gId(stringRow_orderID).value = sList;                                                               
}
