/************************************************************

  98healthjs
  ==========

  Copyright © 2007 - 2011 by Ed Hohmann

  JavaScript for use with the 98Health website
  Written by Ed Hohmann, Jan 2007

************************************************************/

function  toggleDetails( btnElement, divID )  {

	var ItemDivID = "divItemList-" + divID;
	var BrandDivID = "divBrand-" + divID;
	var divItemList = document.getElementById( ItemDivID );
	var divBrand = document.getElementById( BrandDivID );

	if ( btnElement.value == "Details" )  {
		btnElement.value = "Summary";
		divItemList.style.display = "block";
		divBrand.style.display = "block";
	}
	else  {
		btnElement.value = "Details";
		divItemList.style.display = "none";
		divBrand.style.display = "none";
	}
}


function  toggleAllDetails( btnElement, groupID )  {

	if ( btnElement.value == "Show Product Details" )  {
		btnElement.value = "Show Summary Information";
		ItemBtnValue = "Summary";
		showLevel = "block";
	}
	else  {
		btnElement.value = "Show Product Details";
		ItemBtnValue = "Details";
		showLevel = "none";
	}

	var  i = 0;
	do  {
		var  curElemID = groupID + "[" + ++i + "]";
		var  curItemDivID = "divItemList-" + curElemID;
		var  curBrandDivID = "divBrand-" + curElemID;
		var  curBtnID = "btnDetail-" + curElemID;
		var  curItemDiv = document.getElementById( curItemDivID );
		var  curBrandDiv = document.getElementById( curBrandDivID );
		var  curBtn = document.getElementById( curBtnID );
		if  ( curBtn != null )  {
			curItemDiv.style.display = showLevel;
			curBrandDiv.style.display = showLevel;
			curBtn.value = ItemBtnValue;
		}
	}  while  ( curBtn != null );
}


function  elementVisibility( elemID, eV )  {

	var elem = getElem( elemID );
	if  ( typeof( elem ) != undefined )  {
		if  ( eV == "Toggle" )  {
			switch  ( elem.style.visibility )  {
				case  "hidden":
					eV = "visible";
					break;
				case  "visible":
					eV = "hidden";
					break;
			}
		}
		elem.style.visibility = eV;
	}
}


function  elementDisplay( elemID, eV, eNormal )  {

	var elem = getElem( elemID );
	if  ( typeof( elem ) != undefined )  {
		if  ( eV == "Toggle" )  {
			switch  ( elem.style.display )  {
				case  "none":
					eV = eNormal;
					break;
				case  eNormal:
					eV = "none";
					break;
			}
		}
		elem.style.display = eV;
	}
}


function  getRadioButtonValue( elemName, defValue )  {

	if  ( typeof( defValue ) == "undefined"  ||  defValue == null )
		defValue = "";
	if  ( elemName.indexOf( "[]" ) <= 0 )
		elemName += "[]";
	var ctlRadio = document.getElementsByName( elemName );
	var idx = 0;
	while ( typeof( ctlRadio[idx] ) != "undefined" )  {
		//***/  alert( elemName + "[" + idx + "].value = \"" + ctlRadio[idx].value + "\"" );
		if  ( ctlRadio[idx].checked )
			return  ctlRadio[idx].value;
		idx++;
	};
	return  defValue;
}


function  setRadioButton( elemName, elemValue )  {

	if  ( elemName.indexOf( "[]" ) <= 0 )
		elemName += "[]";
	var ctlRadio = document.getElementsByName( elemName );
	var idx = 0;
	while ( typeof( ctlRadio[idx] ) != "undefined" )  {
		ctlRadio[idx].checked = false;
		if  ( ctlRadio[idx].value == elemValue )
			ctlRadio[idx].checked = true;
		idx++;
	};
	return;
}


function  checkCheckBoxes( chkOp, chkNames, chkPrefixes, chkSuffixes )  {

	var  SelBox, prefSelBox, suffSelBox;
	var  arrNames     = chkNames.split( "," );
	var  arrPrefixes  = chkPrefixes.split( "," );
	var  arrSuffixes  = chkSuffixes.split( "," );
	var  CheckboxList = document.getElementsByTagName( "input" );

	for  ( var  idx = 0;  idx < CheckboxList.length;  idx++ )  {
		ChkBox = CheckboxList[ idx ];
		if  ( ( ChkBox.type == "checkbox" )  &&  ChkBox.name )  {
			//***/  alert( "ChkBox name = \"" + ChkBox.name + "\", type = \"" + ChkBox.type + "\", visibility = \"" + ChkBox.style.visibility + "\"" );
			SelBox = prefSelBox = suffSelBox = false;
			for  ( var  ndx = 0;  ndx < arrNames.length;  ndx++ )  {
				chkName = trimStr( arrNames[ ndx ] );
				if  ( ( chkName == ""  &&  chkPrefixes == ""  &&  chkSuffixes == "" )  ||
							( chkName != ""  &&  ChkBox.name == chkName ) )
					SelBox = true;
			}

			for  ( var  ndx = 0;  ndx < arrPrefixes.length;  ndx++ )  {
				chkPrefix = trimStr( arrPrefixes[ ndx ] );
				if  ( chkPrefix  &&  str_is_left( ChkBox.name, chkPrefix ) )
					prefSelBox = true;
			}

			for  ( var  ndx = 0;  ndx < arrSuffixes.length;  ndx++ )  {
				chkSuffix = trimStr( arrSuffixes[ ndx ] );
				if  ( chkSuffix  &&  str_is_right( ChkBox.name, chkSuffix ) )
					suffSelBox = true;
			}

			if  ( prefSelBox  &&  suffSelBox )
				SelBox = true;

			if  ( prefSelBox  &&  !chkSuffixes )
				SelBox = true;

			if  ( !chkPrefixes  &&  suffSelBox )
				SelBox = true;

			if  ( SelBox )  {
				if  ( chkOp == "Select" )
					ChkBox.checked = true;
				if  ( chkOp == "Clear" )
					ChkBox.checked = false;
				if  ( chkOp == "Invert" )
					ChkBox.checked = !ChkBox.checked;
			}
		}
	}
}


function  showElements( showOp, showTags, showNames, showPrefixes, showSuffixes, showState )  {

	var  TagList, ElemList, SelElem, prefSelElem, suffSelElem;
	var  arrTags      = showTags.split( "," );
	var  arrNames     = showNames.split( "," );
	var  arrPrefixes  = showPrefixes.split( "," );
	var  arrSuffixes  = showSuffixes.split( "," );

	var  TestElem = getElem( "TestRow" );
	//***/  alert( "TestElem id = \"" + TestElem.id + "\", display = \"" + TestElem.style.display + "\"" );
	for  ( var  idx = 0;  idx < arrTags.length;  idx++ )  {
		TagType = trimStr( arrTags[ idx ] );
		TagList = document.getElementsByTagName( TagType );
		for  ( var  tdx = 0;  tdx < TagList.length;  tdx++ )  {
			TagElem = TagList[ tdx ];
			if  ( TagElem.id )  {
				//***/  alert( "TagElem " + TagType + " #" + tdx + " id = \"" + TagElem.id + "\"" );
				//***/  alert( "TagElem " + TagType + " #" + tdx + " id = \"" + TagElem.id + "\", display = \"" + TagElem.style.display + "\"" );
				SelElem = prefSelElem = suffSelElem = false;
				for  ( var  ndx = 0;  ndx < arrNames.length;  ndx++ )  {
					chkName = trimStr( arrNames[ ndx ] );
					if  ( ( chkName == ""  &&  showPrefixes == ""  &&  showSuffixes == "" )  ||
								( chkName != ""  &&  TagElem.id == chkName ) )
						SelElem = true;
				}

				for  ( var  ndx = 0;  ndx < arrPrefixes.length;  ndx++ )  {
					chkPrefix = trimStr( arrPrefixes[ ndx ] );
					if  ( chkPrefix  &&  str_is_left( TagElem.id, chkPrefix ) )
						prefSelElem = true;
				}

				for  ( var  ndx = 0;  ndx < arrSuffixes.length;  ndx++ )  {
					chkSuffix = trimStr( arrSuffixes[ ndx ] );
					if  ( chkSuffix  &&  str_is_right( TagElem.id, chkSuffix ) )
						suffSelElem = true;
				}

				if  ( prefSelElem  &&  suffSelElem )
					SelElem = true;

				if  ( prefSelElem  &&  !showSuffixes )
					SelElem = true;

				if  ( !showPrefixes  &&  suffSelElem )
					SelElem = true;

				if  ( SelElem )  {
					if  ( showOp == "Show" )  {
						TagElem.style.visibility = "visible";
						TagElem.style.display   , "";
						setElemValue( showState, "Show" );
					}
					if  ( showOp == "Hide" )  {
						TagElem.style.visibility = "hidden";
						TagElem.style.display    = "none";
						setElemValue( showState, "Hide" );
					}
					if  ( showOp == "Invert" )  {
						if  ( TagElem.style.visibility == "visible" )  {
							TagElem.style.visibility = "hidden";
							TagElem.style.display    = "none";
							setElemValue( showState, "Hide" );
						}
						else  {
							TagElem.style.visibility = "visible";
							TagElem.style.display    = "";
							setElemValue( showState, "Show" );
						}
					}
				}
			}
			else  {
				//***/  alert( "TagElem.id is undefined" );
			}
		}
	}
}


function  switchStateSwitch( elemSwitch )  {

	var  ctlRadio = null;
	if  ( typeof( elemSwitch ) == "object" )
		elemSwitch = getElemName( elemSwitch );

	ctlRadio = document.getElementsByName( elemSwitch );

	var idx = 0;
	while ( typeof( ctlRadio[idx] ) != "undefined" )  {
		/***/  alert( "ctlRadio[" + idx + "] = \"" + ctlRadio[idx].id + "\"" );
		/***/  alert( "ctlRadio[" + idx + "].parentNode.nodeName = \"" + ctlRadio[idx].parentNode.nodeName + "\"" );
		/***/  alert( "ctlRadio[" + idx + "].parentNode.childNodes.length = \"" + ctlRadio[idx].parentNode.childNodes.length + "\"" );
		var  idxCN = 0;
		while ( typeof( ctlRadio[idx].parentNode.childNodes[idxCN] ) != "undefined" )  {
			/***/  alert( "typeof( ctlRadio[" + idx + "].parentNode.childNodes[" + idxCN + "] ) = " + typeof( ctlRadio[idx].parentNode.childNodes[idxCN] ) );
			if  ( typeof ( ctlRadio[idx].parentNode.childNodes[idxCN].nodeName ) != "undefined" )  {
				/***/  alert( "ctlRadio[" + idx + "].parentNode.childNodes[" + idxCN + "] = " + ctlRadio[idx].parentNode.childNodes[idxCN].nodeName );
				if  ( ctlRadio[idx].parentNode.childNodes[idxCN].nodeType == 3 )  {
					/***/  alert( "ctlRadio[" + idx + "].parentNode.childNodes[" + idxCN + "].nodeValue = \"" + ctlRadio[idx].parentNode.childNodes[idxCN].nodeValue + "\"" );
				}
			}
			//***/  dbgOut( describeDOMObj( ctlRadio[idx].parentNode.childNodes[idxCN] ) );
			idxCN++;
		}
		/***/  dbgOut( describeDOMObj( ctlRadio[idx].parentNode ) );
		idx++;
	};
}


function  loadInputList( elemListID, arrOptions )  {

	var elemList = getElem( elemListID );
	elemList.options.length = 0;

	for  ( var opt  in  arrOptions )  {
		if  ( typeof( ArrayMethods[ opt ] ) == "undefined" )  {
			elemList.options[ elemList.options.length ] = new Option( arrOptions[ opt ], opt );
		}
	}
}


function  setInputListArray( elemListID, elemArray )  {

	var elemList = getElem( elemListID );
	elemList.options.length = 0;
	for  ( var idx = 0;  idx < elemArray.length;  idx++ )  {
		if  ( elemArray[idx].selected )  {
			elemList.options[ elemList.options.length ] = new Option( elemArray[idx].text, elemArray[idx].value );
		}
	}
	return;
}


function  selectInputListValue( elemListID, elemValue )  {

/***
	var  ctlList = null;
	if  ( typeof( elemListID ) == "object" )
		ctlList = elemListID;
	else
		ctlList = getElem( elemListID );
***/

	var  ctlList = getElem( elemListID );

	var  SelectOption;
	var  optSelected = false;
	for  ( var idx = 0;  idx < ctlList.options.length;  idx++ )  {
		SelectOption = ( ctlList.options[idx].value == elemValue );
		ctlList.options[idx].selected = SelectOption;
		if  ( SelectOption )
			optSelected = true;
	}
	return  optSelected;
}


function  selectInputListText( elemListID, elemText )  {

	//***/  dbgStr += "\nselectInputListText";

/***
	var  ctlList = null;
	if  ( typeof( elemListID ) == "object" )
		ctlList = elemListID;
	else
		ctlList = getElem( elemListID );
***/

	var  ctlList = getElem( elemListID );

	//***/  dbgStr += "( " + ctlList.name + ", " + elemText + " )\n";

	var  SelectOption;
	var  optSelected = false;
	for  ( var idx = 0;  idx < ctlList.options.length;  idx++ )  {
		SelectOption = ( ctlList.options[idx].text == elemText );
		//***/  dbgStr += "Option " + idx + " [ " + ctlList.options[idx].value + " ] = " + ctlList.options[idx].text + " = " + ctlList.options[idx].selected + "\n";
		ctlList.options[idx].selected = SelectOption;
		if  ( SelectOption )  {
			//***/  dbgStr += "Selected option " + SelectOption + " ... " + idx + " [ " + ctlList.options[idx].value + " ] = " + ctlList.options[idx].text + "\n";
			optSelected = true;
		}
	}
	return  optSelected;
}


function	addInputListOption( elemListID, optPos, optText, optValue, optSelected )  {

	var  elemList, newOption, optList, idx;

/***
	if  ( typeof( elemListID ) == "object" )
		elemList = elemListID;
	else
		elemList = getElem( elemListID );
***/

	elemList = getElem( elemListID );

	if  ( typeof( optSelected ) == "undefined"  ||  optSelected == null )
		optSelected = false;
	else
		if  ( optSelected == "Select"  ||  optSelected == true )
			optSelected = true;
		else
			optSelected = false;

	newOption = new  Option( optText, optValue );
	optList = elemList.options;

	if  ( optSelected )  {
		newOption.selected = true;
		if  ( optList )  {
			idx = 0;
			while ( typeof( optList[idx] ) != "undefined"  &&  optList.length > idx )  {
				optList[idx].selected = false;
				idx++;
			}
		}
	}

	if  ( optPos < 0 )
		optPos = optList.length;

	try  {
		elemList.add( newOption, optList[ optPos ] );
	}
	catch  ( e )  {
		elemList.add( newOption, optPos );
	}

/***
	elemList.options.length = 0;

	for  ( var key  in  arrValue )  {
		//*** /  dbgOut( "key = " + key + ", value = " + arrValue[ key ] + "\n" );
		if  ( typeof( ArrayMethods[ key ] ) == "undefined" )  {
			idx = elemList.options.length;
			eValue = arrValue[key];
			elemList.options[ idx ] = new Option( eValue, key  );
			if  ( elemValue == key )
				elemList.options[ idx ].selected = true;
		}
	}
***/
	return;
}


function  compareInputLists( elemCheckListID, elemReferenceListID, expIn, expNotIn )  {

/***
	var  chkList;
	if  ( typeof( elemCheckListID ) == "object" )
		chkList = elemCheckListID;
	else
		chkList = getElem( elemCheckListID );
***/

	var  chkList = getElem( elemCheckListID );

/***
	var  refList;
	if  ( typeof( elemReferenceListID ) == "object" )
		refList = elemReferenceListID;
	else
		refList = getElem( elemReferenceListID );
***/

	var  refList = getElem( elemReferenceListID );

	var  chkOption, refOption, idxOpt;

	for  ( var idxChk = 0;  idxChk < chkList.options.length;  idxChk++ )  {
		chkOption = chkList.options[idxChk];
		idxOpt = -1;
		for  ( var idxRef = 0;  idxRef < refList.options.length;  idxRef++ )  {
			refOption = refList.options[idxRef];
			if  ( chkOption.value == refOption.value  &&  chkOption.text == refOption.text )  {
				idxOpt = idxChk;
				break;
			}
		}
		if  ( idxOpt >= 0 )
			eval( expIn );
		else
			eval( expNotIn );
	}
	return  false;
}


function  clearInputList( elemListID )  {

	var  elemList;

	if  ( ( elemList = getElem( elemListID ) ) )
		elemList.options.length = 0;
	return;
}


function  clearInputListValue( elemListID )  {

	var  elemList;

	if  ( ( elemList = getElem( elemListID ) ) )  {
		var  idx = elemList.options.length;
		elemList.options[idx] = new Option( "", "" );
		elemList.options[idx].selected = true;
	}
	return;
}


function  getInputListValue( elemListID, defValue )  {

	if  ( typeof( defValue ) == "undefined"  ||  defValue == null )
		defValue = "";

	//***/  dbgOut( "\nelemListID = " + elemListID + "\n" );

/***
	var  ctlList = null;
	if  ( typeof( elemListID ) == "object" )
		ctlList = elemListID;
	else
		ctlList = getElem( elemListID );
***/

	var  ctlList = getElem( elemListID );

	/***/  if  ( ctlList == null )
	/***/  	dbgOut( "\nelemListID " + elemListID + " is null!!!\n" );

	var idx = 0;

	if  ( ctlList )  {
		if  ( ctlList.multiple )  {
			//***/  dbgOut( "\nMultiple\n" );
			var  elemValue = new Array();
			var  odx = 0;
			while ( typeof( ctlList.options[idx] ) != "undefined"  &&  ctlList.options.length > idx )  {
				if  ( ctlList.options[idx].selected )  {
					elemValue[odx] = ctlList.options[idx].value;
					odx++;
				}
				idx++;
			}
			return  elemValue;
		}
		else  {
			//***/  dbgOut( "\nSingle\n" );
			if  ( ctlList.options )
			while ( typeof( ctlList.options[idx] ) != "undefined"  &&  ctlList.options.length > idx )  {
				if  ( ctlList.options[idx].selected )
					return  ctlList.options[idx].value;
				idx++;
			}
		}
	}

	return  defValue;
}


function  getInputListText( elemListID, defValue )  {

	if  ( typeof( defValue ) == "undefined"  ||  defValue == null )
		defValue = "";

/***
	var  ctlList = null;
	if  ( typeof( elemListID ) == "object" )
		ctlList = elemListID;
	else
		ctlList = getElem( elemListID );

	if  ( ctlList  &&  ctlList.options )  {
		for  ( var idx = 0;  idx < ctlList.options.length;  idx++ )  {
			if  ( ctlList.options[idx].selected )
				return  ctlList.options[idx].text;
		}
	}
***/

	var  ctlList = getElem( elemListID );
	var  idx = 0;

	if  ( ctlList )  {
		if  ( ctlList.multiple )  {
			//***/  dbgOut( "\nMultiple\n" );
			var  elemValue = new Array();
			var  odx = 0;
			while ( typeof( ctlList.options[idx] ) != "undefined"  &&  ctlList.options.length > idx )  {
				if  ( ctlList.options[idx].selected )  {
					elemValue[odx] = ctlList.options[idx].text;
					odx++;
				}
				idx++;
			}
			return  elemValue;
		}
		else  {
			//***/  dbgOut( "\nSingle\n" );
			if  ( ctlList.options )
			while ( typeof( ctlList.options[idx] ) != "undefined"  &&  ctlList.options.length > idx )  {
				if  ( ctlList.options[idx].selected )
					return  ctlList.options[idx].text;
				idx++;
			}
		}
	}

	return  defValue;
}


function  setInputListText( elemListID, newValue )  {

	if  ( typeof( newValue ) == "undefined"  ||  newValue == null )
		newValue = "";

/***
	var  ctlList = null;
	if  ( typeof( elemListID ) == "object" )
		ctlList = elemListID;
	else
		ctlList = getElem( elemListID );
***/

	var  ctlList = getElem( elemListID );

	if  ( ctlList  &&  ctlList.options )  {
		for  ( var idx = 0;  idx < ctlList.options.length;  idx++ )  {
			if  ( ctlList.options[idx].selected )  {
				ctlList.options[idx].text = newValue;
				return
			}
		}
	}
	return;
}


function  getInputList( elemListID )  {

	var  outList = [];

/***
	var  ctlList = null;
	if  ( typeof( elemListID ) == "object" )
		ctlList = elemListID;
	else
		ctlList = getElem( elemListID );
***/

	var  ctlList = getElem( elemListID );

	if  ( ctlList  &&  ctlList.options )
		return  ctlList.options;
	else
		return  outList;
}


function  loadInputListValues( elemListID, arrValue, elemValue, maxMultipleLength )  {

	var  elemList, idx, eValue, ListLength, maxListLength;

	elemList = getElem( elemListID );

	//***/  alert( "\nloadInputListValues( "+ elemListID + ", arrValue, " + elemValue + " )\n" );
	//***/  alert( "elemList.options.length = \"" + elemList.options.length + "\"" );

	if  ( elemList.multiple )  {
		maxMultipleLength = getArg( maxMultipleLength, 0 );
		if  ( maxMultipleLength != 0 )  {
			if  ( maxMultipleLength < 0 )  {
				maxListLength = getArg( elemList.maxListLength, 0 );
			}
			else  {
				maxListLength = maxMultipleLength;
			}
			if  ( maxListLength > 0 )  {
				ListLength = ( maxListLength > arrValue.length  ?  arrValue.length  :  maxListLength );
				elemList.size = ListLength;
			}
		}
	}

	elemList.options.length = 0;

/***/
	for  ( var key  in  arrValue )  {
		//***/  dbgOut( "key = " + key + ", value = " + arrValue[ key ] + "\n" );
		if  ( typeof( ArrayMethods[ key ] ) == "undefined" )  {
			idx = elemList.options.length;
			eValue = arrValue[key];
			elemList.options[ idx ] = new Option( eValue, key  );
			if  ( elemValue == key )
				elemList.options[ idx ].selected = true;
		}
	}
/***/

/*** /
	for  ( var key  in  arrValue )  {
		//*** /  dbgOut( "key = " + key + ", value = " + arrValue[ key ] + "\n" );
		if  ( typeof( ArrayMethods[ key ] ) == "undefined" )  {
			idx = elemList.options.length;
			eValue = arrValue[key];
			elemList.options[ idx ] = new Option( eValue, key  );
			if  ( elemValue == key )
				elemList.options[ idx ].selected = true;
		}
	}
/***/

	return;

}


function  SwapFieldValue( objField )  {
	if  ( typeof( objField.oldValue ) == "undefined" )  {
		objField.oldValue = objField.value;
		objField.value = "";
	}
	else  {
		var  curValue = objField.value;
		objField.value = objField.oldValue;
		objField.oldValue = curValue;
	}
}


function  setTreeVisibility  ( fieldName, idx, toggle )  {

	var  flagToggle = ( typeof( toggle ) != "undefined"  &&  toggle == "toggle" );
	var  valBranchID = "f" + fieldName + "[]";
	var  valBranch = document.getElementsByName( valBranchID );
	var  dot = "-";

	var	 fIdx = fieldName + dot + idx;

	var  topBranchID = "div" + fIdx;
	var  subBranchID = "sub" + fIdx;
	var  expBranchID = "a"   + fIdx;

	var  topBranch = getElem( topBranchID );
	var  subBranch = getElem( subBranchID );
	var  expBranch = getElem( expBranchID );

	/***
	//var  sBranch = subBranch.getElementsByName( valBranchID );
	var  debugTree = getElem( "debugTree" );
	debugTree.innerHTML = topBranchID + ", " + subBranchID + ", " + valBranchID + ", " + valBranch[idx].form.name + ", " + subBranch + "\n";
	//debugTree.innerHTML += "valBranch.length = " + valBranch.length + ", sBranch.length = " + sBranch.length;
	***/

	if  ( subBranch != null )  {
		if  ( ( flagToggle  ?  subBranch.style.display == "block"  :  valBranch[idx].checked ) )
			subBranch.style.display = "none";
		else
			subBranch.style.display = "block";

		if  ( expBranch != null )
			if  ( subBranch.style.display == "none" )
				expBranch.innerHTML = "+";
			else
				expBranch.innerHTML = "-";
	}

	return;
}


function  toggleTreeVisibility( fieldName, idx )  {

	setTreeVisibility  ( fieldName, idx, "toggle" );
}



function  clickDropdownList( strFieldName, maxFieldLength, onCollapse )  {

	var  objElem = getElem( strFieldName );
	var  objCtrl = objElem.nextSibling;
	var  FieldLength = ( objElem.options.length < maxFieldLength  ?  objElem.options.length  :  maxFieldLength );
	//***/  alert( "objElem Name = \"" + objElem.name + "\"" );
	//***/  alert( strASCII2Binary( objCtrl.value ) );
	//***/  alert( "objElem: zIndex = \"" + objElem.parentNode.style.zIndex + "\"" );
	//***/  alert( objElem.name + " size = \"" + objElem.size + "\"" );
	//***/  alert( objElem.name + ": " + describeDOMObj( objElem ) );
	//***/  alert( objElem.name + " options: " + describeDOMObj( objElem.options ) );

	switch  ( objCtrl.value )  {

		case  DropdownIconCollapse:
			//***/  alert( "Collapse: " + objElem.name + " size = " + objElem.size );
			objCtrl.value = DropdownIconExpand;
			objElem.focus();
			objElem.size = 1;
			//objElem.parentNode.style.zIndex = objElem.parentNode.parentNode.style.zIndex;
			//objElem.style.zIndex = objElem.parentNode.style.zIndex;
			if  ( onCollapse )  {
				switch  ( typeofObject( onCollapse ) )  {
					case  "function":
						onCollapse();
						break;
					case  "string":
						//***/  alert( "clickDropdownList( \"" + strFieldName + "\", \"" + maxFieldLength + "\", \"" + onCollapse + "\" )" );
						eval( onCollapse );
						break;
				}
			}
			break;

		case  DropdownIconExpand:
			//***/  alert( "Expand: " + objElem.name + " size = " + objElem.size );
			objCtrl.value = DropdownIconCollapse;
			objElem.parentNode.style.position = "absolute";
			//objElem.parentNode.style.visibility = "visible";
			//objElem.parentNode.style.zIndex = objElem.parentNode.parentNode.style.zIndex + 1;
			//objElem.style.zIndex = objElem.parentNode.style.zIndex + 1;
			objElem.focus();
			objElem.size = FieldLength;
			objElem.maxListLength = maxFieldLength;
			//objElem.style.visibility = "visible";
			break;
	}
}



function  resetDropdownList( strFieldName )  {

	var  objElem = getElem( strFieldName );
	var  objCtrl = objElem.nextSibling;

	objCtrl.value = DropdownIconExpand;
	objElem.size = 1;
}



function  clickDropdownButton( strFieldName )  {

	var  objElem = getElem( strFieldName );
	var  objCtrl = objElem.nextSibling;

	if  ( !clickButton( objCtrl ) )
		alert( "clickButton error!" );
}



function  showElementAttributes( elemTestName, fieldDisplay )  {

	var elemTest = getElem( elemTestName );
	var elemDisp = getElem( fieldDisplay );
	for  ( var  idx  in  elemTest )  {
		elemDisp.value += ", " + idx;
	}
/* or: */
	elemDisp.value = elemTest.className;
	return;
}



function  calcMSRPFactor( MSRPfType, RoundingType )  {

	var  MSRP = getElemDataValue( "fMSRP", 0.0 );
	var  fldFactor = getElem( "fMSRPf" + MSRPfType );
	var  fldResult = getElem( "f" + MSRPfType );
	var  Factor = getElemDataValue( fldFactor );
	var  Result = getElemDataValue( fldResult );

	var  Rf, Rfs, Rs, DP, Fr;

	if  ( Factor != 0 )  {
		Rf = MSRP * Factor;

		if  ( RoundingType == "NONE" )
			Rf = Math.round( Rf * 100 ) / 100;
		else
			Rf = Math.round( Rf * 20 ) / 20;
		setElemDataValue( fldResult, Rf );
	}
	else if  ( Result != 0  &&  MSRP != 0 )  {
		Fr = Result / MSRP;
		setElemDataValue( fldFactor, Fr.toPrecision( 6 ) );
	}
}
/**********
function  calcMSRPFactor( MSRPfType, RoundingType )  {

	var fldMSRP   = getElem( "fMSRP" );
	var fldFactor = getElem( "fMSRPf" + MSRPfType );
	var fldResult = getElem( "f" + MSRPfType );

	var Rf;
	var Rfs;

	if  ( fldFactor.value != ""  &&  fldFactor.value != 0 )  {
		Rf = fldMSRP.value * fldFactor.value;

		if  ( RoundingType == "NONE" )
			Rfs = " " + Math.round( Rf * 100 ) / 100;
		else
			Rfs = " " + Math.round( Rf * 20 ) / 20;
		var DP = Rfs.indexOf( "." );
		var Rs = Rfs;
		if  ( DP < 0 )  {
			Rs = Rfs + ".00"
		}
		else  {
			if  ( Rfs.length < DP + 3 )  {
				Rs = Rfs + "0";
			}
		}

	fldResult.value = Rs.replace( " ", "" );
	}
}
***********/


function  InitProductCode( BCode )  {

	if  ( BCode != 0 )  {
		var  newPCode = BCode + "-";
		var  fPCode = getElem( "fPCode" );
		var  fReqFields = getElem( "RequiredFields" );

		fPCode.focus();
		fPCode.value = fPCode.value.replace( /(^[^\-]*-)|^/, newPCode );
		fReqFields.value = fReqFields.value.replace( /fPCode\s*=\s*[^ ;]*\s*;?/, "fPCode=" + newPCode + ";" );
	}
	EnforceRequiredFields();
}



function  InitPItemCode( PCode )  {

	if  ( PCode != 0 )  {
		var  newICode = PCode + "-";
		var  fICode  = getElem( "fICode" );
		var  fVPCode = getElem( "fVPCode" );
		var  fReqFields = getElem( "RequiredFields" );
		var  isIPCode  = fICode.value.match( /^[^\-]*-[^\-]*-/ );
		var  isVPPCode = fVPCode.value.match( /^[^\-]*-[^\-]*-/ );
		//alert( "isIPCode = \"" + isIPCode + "\"\nisVPPCode = \"" + isVPPCode + "\"\ndescribeObj( isIPCode ) = " + describeObj( isIPCode ) + "\ndescribeObj( isVPPCode ) = " + describeObj( isVPPCode ) );
		var  isCommonPCode = ( ( isIPCode == isVPPCode )  ||  ( ( typeofObject( isIPCode ) == "Array" )  &&  ( typeofObject( isVPPCode ) == "Array" )  &&  ( isIPCode[ 0 ] == isVPPCode[ 0 ] ) ) );

		fICode.focus();
		fICode.value = fICode.value.replace( /(^[^\-]*-[^\-]*-)|^/, newICode );
		fReqFields.value = fReqFields.value.replace( /fICode\s*=\s*[^ ;]*\s*;?/, "fICode=" + newICode + ";" );

		if  ( isCommonPCode )  {
			fVPCode.value = fVPCode.value.replace( /(^[^\-]*-[^\-]*-)|^/, newICode );
			fReqFields.value = fReqFields.value.replace( /fVPCode\s*=\s*[^ ;]*\s*;?/, "fVPCode=" + newICode + ";" );
		}
	}
	EnforceRequiredFields();
}



function  xxxchkInitVPCode( fICode )  {  // Replaced by duplicateInitialValue.  EAH June 17, 2009

	var  fVPCode = getElem( "fVPCode" );
	var  VPCode = fVPCode.value;

	if  ( fICode.value == VPCode )  {
		fICode.onkeyup =
			function anonymous()  {
				fVPCode.value = fICode.value;
				EnforceRequiredFields();
				/***/
				fICode.onkeyup =
					function anonymous()  {
						EnforceRequiredFields();
					};
				/***/
			};
	}
	/***
	else  {
		fICode.onkeydown = null;
		fICode.onkeyup =
			function anonymous()  {
				EnforceRequiredFields();
			};
	}
	***/
}



/******************************************************************************
  duplicateInitialValue
    EAH - June 17, 2009

    Duplicates data entry from one field to another if the initial values
    are identical.

******************************************************************************/

function  duplicateInitialValue( fldMaster, fldSlave )  {

	var  fMaster = getElem( fldMaster );
	var  fSlave  = getElem( fldSlave  );

	if  ( fMaster.value == fSlave.value )  {
		fMaster.onkeyup =
			function anonymous()  {
				fSlave.value = fMaster.value;
				EnforceRequiredFields();
				/*** /
				fMaster.onkeyup =
					function anonymous()  {
						EnforceRequiredFields();
					};
				/***/
			};
	}
	/***/
	else  {
		fMaster.onkeyup =
			function anonymous()  {
				EnforceRequiredFields();
			};
	}
	/***/
}



/******************************************************************************
  setItemName
    EAH - November 12, 2007

    Sets the ItemName field to the Name of the ItemData selection.
    Clears the ItemLink field.

******************************************************************************/

function  setItemName( elemItemData )  {

	var  ItemDataName = getInputListText( elemItemData );
	var  ItemDataID = elemItemData.name;
	var  arrItemIX = ItemDataID.split( FieldIndexDelimiter );
	var  ItemIX = arrItemIX[ 1 ];
	var  ItemName = getElem( "fIName" + FieldIndexDelimiter + ItemIX );
	var  ItemLink = getElem( "fILink" + FieldIndexDelimiter + ItemIX );
	if  ( ItemDataName )
		ItemName.value = ItemDataName;
	ItemLink.value = "";
}




/******************************************************************************
  setLinkList
    EAH - September 24, 2007

    Sets the Topics Link List selection options when one of the Link List
    controls is changed.

    When changing between the Link and Load modes (changedID == "fLinkMode[]"):
    -- Set the changedList item to fTTypes[] and fall through to the TopicTypes
       processing section so that the showTopicLinks function will set the
       TopicLinks controls to the correct values for the new mode.
    -- Enable/Disable the Link buttons according to the Link Mode.

******************************************************************************/

function  setLinkList( changedListElement )  {

	/***/  dbgStr += "setLinkList:\n";

	var  EditMode = getElemValue( "EditMode" );
	var  LinkMode = getTopicLinkMode();
	var  TTypes = getInputListValue( "fTTypes[]", "" );
	var  SType = getElemValue( "fSType", "" );
	var  GType = getElemValue( "fGType", "" );
	var  TCode, SNTag, GNTag, INTag;
	TCode = SNTag = GNTag = INTag = null;
	TCode = getInputListValue( "fTLinks", null );
	SNTag = getInputListValue( "fSLinks", null );
	GNTag = getInputListValue( "fGLinks", null );
	INTag = getInputListValue( "fILinks", null );

	var  changedID = changedListElement.name;
	var  changedValue = changedListElement.value;

	/***/  dbgStr += "changedListElement: " +  changedID + " = \"" + changedValue + "\"; LinkMode = \"" + LinkMode + "\", " + "EditMode = \"" + EditMode + "\"; ";
	/***/  dbgStr += "SType = \"" + SType + "\", GType = \"" + GType + "\"\n";


	if  ( changedID == "fLinkMode[]" )  {
		SCode = getLinkListCode( "fSLinks" );
		GCode = getLinkListCode( "fGLinks" );
		ICode = getLinkListCode( "fILinks" );
		if  ( LinkMode == "Load" )  {
			SNTag = SCode;
			GNTag = GCode;
			INTag = ICode;
		}
		else  {
			if  ( SCode == SNTag )
				SNTag = getLinkListNTag( "fSLinks" );
			if  ( GCode == GNTag )
				GNTag = getLinkListNTag( "fGLinks" );
			if  ( ICode == INTag )
				INTag = getLinkListNTag( "fILinks" );
		}
		changedID = "fTTypes[]";
		changedListElement = getElem( changedID );
	}

	switch  ( changedID )  {

		case  "fTTypes[]":
			elementVisibility( "fldTLinks", "hidden" );
			elementVisibility( "fldSLinks", "hidden" );
			elementVisibility( "fldGLinks", "hidden" );
			elementVisibility( "fldILinks", "hidden" );
			clearInputList( "fTLinks" );
			clearInputList( "fSLinks" );
			clearInputList( "fGLinks" );
			clearInputList( "fILinks" );
			xajax_showTopicLinks( changedID, LinkMode, EditMode, TTypes, TCode, SType, SNTag, GType, GNTag, INTag );
			break;

		case  "fTLinks":
			TCode = getInputListValue( "fTLinks" );
			/***/  dbgStr += "TCode = \"" + TCode + "\"\n";
			elementVisibility( "fldSLinks", "hidden" );
			elementVisibility( "fldGLinks", "hidden" );
			elementVisibility( "fldILinks", "hidden" );
			clearInputList( "fSLinks" );
			clearInputList( "fGLinks" );
			clearInputList( "fILinks" );
			//  xajax_showTopicLinks( changedID, LinkMode, EditMode, TTypes, TCode, SType );  // Reset the lower-level selection lists.
			xajax_showTopicLinks( changedID, LinkMode, EditMode, TTypes, TCode, SType, SNTag, GType, GNTag, INTag );  // Remember the previous selection values.
			break;

		case  "fSLinks":
			if  ( EditMode == "Group"  ||  EditMode == "Item"  ||  LinkMode == "HyperLink" )  {
			  TCode = getInputListValue( "fTLinks" );
				SNTag = getInputListValue( "fSLinks" );
				/***/  dbgStr += "SNTag = \"" + SNTag + "\"\n";
				elementVisibility( "fldGLinks", "hidden" );
				elementVisibility( "fldILinks", "hidden" );
				clearInputList( "fGLinks" );
				clearInputList( "fILinks" );
				//  xajax_showTopicLinks( changedID, LinkMode, EditMode, TTypes, TCode, SType, SNTag, GType ); // Reset the lower-level selection lists.
				xajax_showTopicLinks( changedID, LinkMode, EditMode, TTypes, TCode, SType, SNTag, GType, GNTag, INTag );  // Remember the previous selection values.
			}
			else
				enableLinkButtons( LinkMode, EditMode, "98Health.js - setLinkList: 1" );
				enableInsertButtons( LinkMode, TCode, SNTag, GNTag, INTag );
				enableMacroButtons();
			break;

		case  "fGLinks":
			if  ( EditMode == "Item"  ||  LinkMode == "HyperLink" )  {
				elementVisibility( "fldILinks", "hidden" );
				clearInputList( "fILinks" );
			  TCode = getInputListValue( "fTLinks" );
			  SNTag = getInputListValue( "fSLinks" );
				GNTag = getInputListValue( "fGLinks" );
				/***/  dbgStr += "GNTag = \"" + changedValue + "\"\n";
				//  xajax_showTopicLinks( changedID, LinkMode, EditMode, TTypes, TCode, SType, SNTag, GType, GNTag ); // Reset the lower-level selection lists.
				xajax_showTopicLinks( changedID, LinkMode, EditMode, TTypes, TCode, SType, SNTag, GType, GNTag, INTag );  // Remember the previous selection values.
			}
			else
				enableLinkButtons( LinkMode, EditMode, "98Health.js - setLinkList: 2" );
				enableInsertButtons( LinkMode, TCode, SNTag, GNTag, INTag );
				enableMacroButtons();
			break;

		case  "fILinks":
		  TCode = getInputListValue( "fTLinks" );
		  SNTag = getInputListValue( "fSLinks" );
		  GNTag = getInputListValue( "fGLinks" );
			INTag = getInputListValue( "fILinks" );
			/***/  dbgStr += "INTag = \"" + changedValue + "\"\n";
			xajax_showTopicLinks( changedID, LinkMode, EditMode, TTypes, TCode, SType, SNTag, GType, GNTag, INTag );
			break;

		case  "fbtnRecall":
			if  ( changedValue != "" )
				xajax_setTopicLinks( LinkMode, EditMode, changedValue, 1, TTypes, SType, GType );
				selectInputListValue( "fRecallList", 1 );
			break;

		case  "fRecallList":
			if  ( changedValue != "" )
				xajax_setTopicLinks( LinkMode, EditMode, "RecallList", changedValue, TTypes, SType, GType );
			break;

		case  "fRecentTopicsLink":
			/***/  dbgStr += "\nfRecentTopicsLink: ";
			if  ( changedValue != "" )  {
				var  RecentTopic = getInputListText( changedID );
				/***/  dbgStr += "RecentTopic = \"" + RecentTopic + "\" ";
				if  ( !selectInputListText( "fTLinks", RecentTopic ) )  {
					LinkMode = "HyperLink";
					setTopicLinkMode( LinkMode );
					/***/  dbgStr += "Not Found in TopicLinkList; setting LinkMode to \"" + LinkMode + "\" ";
				}
				xajax_setTopicLinks( LinkMode, EditMode, changedValue, 1, TTypes, SType, GType );
			}
			break;

		/***  If not a LinkList field or Recall selection, then set the LinkList to this value:  ***/
		default:
			if  ( changedValue != "" )  {
				if  ( changedID.indexOf( "HRef" + FieldIndexDelimiter ) >= 0 )  {
					LinkMode = "HyperLink";
					setTopicLinkMode( LinkMode );
				}
				if  ( changedID.indexOf( "Link" + FieldIndexDelimiter ) >= 0 )  {
					LinkMode = "Link";
					setTopicLinkMode( LinkMode );
				}
				xajax_setTopicLinks( LinkMode, EditMode, changedValue, 1, TTypes, SType, GType );
			}
			break;

	}

	/***/  dbgStr += "End of setLinkList.\n";
	/***/  dbgOut();

}



/******************************************************************************
  enableLinkButtons
    EAH - November 2, 2007

    Enables or Disables the Link buttons, depending upon the Link Mode.
    The EditMode determines the Code field to look for when only a single
    Section, Group, or Item is being edited (as in the Add mode).

******************************************************************************/

function  enableLinkButtons( LinkMode, EditMode, Src )  {

	/***/  dbgOut( "enableLinkButtons( " + LinkMode + ", " + EditMode + ", " + Src + " )" );

  var  TCode, SCode, GCode, ICode, TLCode, SLCode, GLCode, ILCode, SLNTag, GLNTag, ILNTag;
  var  LinkField, LinkCode, USNTagField, MovedField;
  var  flgSameSet, flgLinkable;
  var  btnLink, btnHyperLink, btnLoad, btnMove, btnInsert, btnInclude, btnPointer, btnLoadItem, btnLoadTerms;
  var  DisableLinkButton, DisableHyperLinkButton, DisableLoadButton, DisableMoveButton, DisableInsertButton, DisableIncludeButton, DisablePointerButton;
	var  DisableReferenceButtons, DisableProcessButton, ProcessButtonDisabled;

  TCode = SCode = GCode = ICode = TLCode = SLCode = GLCode = ILCode = SLNTag = GLNTag = ILNTag = "";
  LinkField = LinkCode = USNTagField = MovedField = "";
  flgSameSet = flgLinkable = false;
  btnLink = btnHyperLink = btnLoad = btnMove = btnInsert = btnInclude = btnPointer = btnLoadItem = btnLoadTerms = null;
  DisableLinkButton = DisableHyperLinkButton = DisableLoadButton = DisableMoveButton = DisableInsertButton = DisableIncludeButton = DisablePointerButton = true;
	DisableReferenceButtons = DisableProcessButton = ProcessButtonDisabled = true;

	var  LFIX = LinkTargetLine;  //getElemValue( "LinkTargetLine" );
	var  AdminScreen = getElemValue( "AdminScreen" );

	if  ( LFIX > 0  ||  LFIX == null )  {

		TCode = getElemValue( "fTCode" );
		SCode = getElemValue( "fSCode" );
		GCode = getElemValue( "fGCode" );
		ICode = getElemValue( "fICode" );

		TLCode = getInputListValue( "fTLinks" );
		SLCode = getInputListValue( "fSLinks" );
		GLCode = getInputListValue( "fGLinks" );
		ILCode = getInputListValue( "fILinks" );

		SLNTag = getLinkListNTag( "fSLinks" );
		GLNTag = getLinkListNTag( "fGLinks" );
		ILNTag = getLinkListNTag( "fILinks" );

		switch  ( EditMode )  {

			case  "Section":
				LinkField   = "fSLinks";
				USNTagField = "fSUSNT";
				MovedField  = "fSMovd";
				flgSameSet  = ( TCode == TLCode );
				flgLinkable = ( SLNTag != "" );
				break;

			case  "Group":
				LinkField   = "fGLinks";
				USNTagField = "fGUSNT";
				MovedField  = "fGMovd";
				flgSameSet  = ( TCode == TLCode  &&  SCode == SLCode );
				flgLinkable = ( SLNTag != ""  &&  GLNTag != "" );
				break;

			case  "Item":
				LinkField   = "fILinks";
				USNTagField = "fIUSNT";
				MovedField  = "fIMovd";
				flgSameSet  = ( TCode == TLCode  &&  SCode == SLCode  &&  GCode == GLCode );
				flgLinkable = ( SLNTag != ""  &&  GLNTag != ""  &&  ILNTag != "" );
				break;
		}

		if  ( AdminScreen == "Reference" )  {
			var  btnProcess = getElem( "fbtnProcess" );
			ProcessButtonDisabled = btnProcess.disabled;
		}

		LinkCode = getInputListValue( LinkField );

		var  fldUsedSubNTag = USNTagField + FieldIndexDelimiter + LFIX;
		var  fldMoved       = MovedField  + FieldIndexDelimiter + LFIX;
		var  flgUsedSubNTag = getElemValue( fldUsedSubNTag, false );
		var  flgMoved       = getElemValue( fldMoved,       false );

		//***/  dbgStr += "LinkMode  = \"" + LinkMode  + "\", " + "EditMode = \"" + EditMode + "\"\n";
		//***/  dbgStr += "LinkField = \"" + LinkField + "\", LinkCode  = \"" + LinkCode + "\"\n";
		//***/  dbgStr += "SLNTag = \"" + SLNTag + "\", GLNTag  = \"" + GLNTag + "\", ILNTag  = \"" + ILNTag + "\"\n";
		//***/  dbgStr += fldUsedSubNTag + "  = \"" + flgUsedSubNTag + "\", " + fldMoved + "  = \"" + flgMoved + "\", flgLinkable = \"" + flgLinkable + "\"\n";

		var  DisableLink = ( ( LinkMode != "Link"  &&  !( LinkMode == "HyperLink"  &&  EditMode != "Section" )  &&  !flgLinkable )  ||  LinkCode == null  ||  LinkCode == 0 );
		var  DisableLoad = ( ( LinkMode != "Load"  &&  LinkMode != "Link"  &&  LinkMode != "HyperLink" )  ||  LinkCode == null  ||  LinkCode == 0 );

		DisableHyperLinkButton  = ( ( LinkMode != "Link"  &&  LinkMode != "HyperLink" )  ||  LinkCode == null  ||  LinkCode == 0 );
		DisableLinkButton       = DisableLink  ||  flgUsedSubNTag  ||  flgMoved  ||  flgSameSet;
		DisableLoadButton       = DisableLoad  ||  flgUsedSubNTag  ||  flgMoved;
		DisableMoveButton       = DisableLoadButton  ||  flgSameSet;
		DisableInsertButton     = DisableLoad  ||  EditMode != "Item";
		DisableIncludeButton    = DisableLink  ||  EditMode != "Item";
		DisablePointerButton    = DisableIncludeButton;
		DisableReferenceButtons = ( LinkMode == "Load" );
		DisableProcessButton    = true;
	}
	/***/  dbgStr += "DisableProcessButton = \"" + DisableProcessButton + "\"\n";
	//***/  dbgStr += "DisableLink = \"" + DisableLink + "\", DisableLoad = \"" + DisableLoad + "\"\n";

	disableButton( "fbtnLink",      DisableLinkButton       );
	disableButton( "fbtnHyperLink", DisableHyperLinkButton  );
	disableButton( "fbtnLoad",      DisableLoadButton       );
	disableButton( "fbtnMove",      DisableMoveButton       );
	disableButton( "fbtnInsert",    DisableInsertButton     );
	disableButton( "fbtnInclude",   DisableIncludeButton    );
	disableButton( "fbtnPointer",   DisablePointerButton    );
	disableButton( "fbtnLoadItem",  DisableReferenceButtons );
	disableButton( "fbtnWhereUsed", DisableReferenceButtons );
	disableButton( "fbtnLoadTerms", DisableReferenceButtons );
	disableButton( "fbtnProcess",   DisableProcessButton    );

	/***/ dbgOut( "End of enableLinkButtons." );
}



function  disableLinkButtons()  {

	//***/ dbgOut( "disableLinkButtons()\n" );
	disableButton( "fbtnLink",      true );
	disableButton( "fbtnHyperLink", true );
	disableButton( "fbtnLoad",      true );
	disableButton( "fbtnMove",      true );
	disableButton( "fbtnInsert",    true );
	disableButton( "fbtnInclude",   true );
	disableButton( "fbtnPointer",   true );
}



function  disableButton( btnName, flagDisable )  {

	var btn;
	//***/ dbgOut( "disableButton( \"" + btnName + "\", " + ( flagDisable  ?  "Disable"  :  "Enable" ) + " );" );
	if  ( ( btn = getElem( btnName ) ) )
		btn.disabled = flagDisable;
}



function  isButtonDisabled( btnName )  {

	var btn;
	//***/ dbgOut( "disableButton( \"" + btnName + "\", " + ( flagDisable  ?  "Disable"  :  "Enable" ) + " );" );
	if  ( ( btn = getElem( btnName ) ) )
		return  btn.disabled;
	else
		return  false;
}



function  enableMacroButtons()  {

	var MacroButtonEnabling, arrMBtns, arrMBtn, arrBtns, curMBtnLine, curMBtn, curBtn = "";

	if  ( ( MacroButtonEnabling = getElemValue( "MacroButtonEnabling" ) ) )  {
		arrMBtns = MacroButtonEnabling.replace( /\r/g, "" ).split( "\n" );
		for  ( var b = 0;  b < arrMBtns.length;  b++ )  {
			curMBtnLine = trimStr( arrMBtns[ b ] );
			if  ( curMBtnLine.indexOf( ":" ) > -1 )  {
				arrMBtn = curMBtnLine.split( ":" );
				//***/  alert( "enableMacroButtons: curMBtnLine = \"" + curMBtnLine + "\"" );
				curMBtn = trimStr( arrMBtn[ 0 ] );
				arrBtns = trimStr( arrMBtn[ 1 ] ).split( "," );
				disableMacroButton( curMBtn, false );
				for  ( var c = 0;  c < arrBtns.length;  c++ )  {
					curBtn = getButtonElemName( trimStr( arrBtns[ c ] ) );
					if  ( isButtonDisabled( curBtn ) )
						disableMacroButton( curMBtn, true );
				}
			}
		}
	}
}



function  disableMacroButton( MacroName, flagDisable )  {

	var  MBtn;

	if  ( ( MBtn = getElem( MacroName ) ) )  {
		//***/  alert( ( flagDisable  ?  "Disabling "  :  "Enabling " ) + MacroName + " ( previously " + MBtn.disabled + " )" );
		if  ( MBtn.tagName == "BUTTON" )  {
			MBtn.disabled = flagDisable;
		}
		else  {
			if  ( typeof( MBtn.disabled ) == "undefined"  ||  MBtn.tagName == "A" )  {
				if  ( flagDisable )  {
					if  ( MBtn.className != ( MBtn.oldClass + "Disabled" ) )  {
						MBtn.oldClass = MBtn.className;
						MBtn.className = MBtn.oldClass + "Disabled";
						MBtn.oldOnClick = MBtn.onclick;
						MBtn.onclick = null;
						MBtn.oldHRef = MBtn.href;
						MBtn.href = "JavaScript:";
					}
				}
				else  {
					if  ( typeof( MBtn.oldClass ) != "undefined"  &&  MBtn.oldClass != null )  {
						MBtn.className = MBtn.oldClass;
						MBtn.oldClass = null;
						MBtn.onclick = MBtn.oldOnClick;
						MBtn.href = MBtn.oldHRef;
					}
				}
				//***/  alert( MacroName + ".onClick = \"" + MBtn.onclick + "\"" );
				//***/  alert( MacroName + ".href = \"" + MBtn.href + "\"" );
			}
			if  ( typeof( MBtn.disabled ) != "undefined" )
				MBtn.disabled = flagDisable;
		}
		//***/  alert( "MBtn.className = " + MBtn.className + "\nTag = " + MBtn.tagName );
	}
}



/******************************************************************************
  RolloverTopicLine
    EAH - August 21, 2008

    Special function to reduce the amount of HTML page code sent to the browser
    for the main Admin Topics page.
    This function highlights the current cursor line in red and sets the
    onmouseout and onclick events for that line.
    It also displays an InfoWindow for the Topic.

******************************************************************************/

function  RolloverTopicLine( TRLine, TCode, ClickAction )  {

	//***/  dbgOut( "RolloverTopicLine: \"" + TCode + "\"" );
	if  ( typeof( ClickAction ) == "undefined" )
		ClickAction = "Submit";
	if  ( ClickAction == "Submit" )  {
		TRLine.style.color = "red";
		var  strTest = "RolloverTopicLine: \"" + TCode + "\"";
		//addElemEvent( TRLine, "onmouseover", function () { RolloverTopicLine( TRLine, TCode, ClickAction ); } );
		//TRLine.onmouseover = "";
		addElemEvent( TRLine, "onclick", function () { setScreenAction( "Select", TCode, "", "Submit" ); } );
		//addElemEvent( TRLine, "onmouseover", function () { dbgOut( "RolloverTopicLine: \"" + TCode + "\"" );} );
		//***/  dbgOut( 'RolloverTopicLine: ' + TCode );
		addElemEvent( TRLine, "onmouseover", "dbgOut( 'RolloverTopicLine: " + TCode + "' );" );
		//addElemEvent( TRLine, "onmouseover", function () { dbgOut( "RolloverTopicLine" );} );
		//addElemEvent( TRLine, "onmouseover", "dbgOut( 'RolloverTopicLine' )" );
		//addElemEvent( TRLine, "onmouseout", function () { dbgOut( "RolloffTopicLine" );} );
		//addElemEvent( TRLine, "onmouseout", function () { dbgOut( "RolloffTopicLine: \"" + TCode + "\"" );} );
		//TRLine.onmouseover = "dbgOut( 'RolloverTopicLine: \"' + TCode + '\"' );} );";
	}
	//addElemEvent( TRLine, "onmouseout", RolloffTopicLine( TRLine ) );
	addElemEvent( TRLine, "onmouseout", function () { ajaxHide(); TRLine.style.color = ""; } );
	var  TopicIWType = getRadioButtonValue( "fTopicIWType[]", "TopicTOC" );
	if  ( TopicIWType != "None" )  {
		try  {
			if  ( TopicIWType == "DisplayHTML" )
				ajaxInfoWindow( TopicIWType, TRLine.firstChild.innerHTML, 3 );
			else
				ajaxInfoWindow( TopicIWType, TCode, 3 );
		}
		catch( err ) {
			/***/  alert( "RolloverTopicLine Error, TCode = \"" + TCode + "\", TopicIWType = \"" + TopicIWType + "\"\n" + err.description );
		};
	}
	//***/  dbgOut( "Done Rolling over Topic Line.", "NoClear" );
}


function  RolloffTopicLine( TRLine )  {

	//***/  dbgOut( "RolloffTopicLine..." );
	ajaxHide();
	TRLine.style.color = "";
	//deleteElemEvent( TRLine, "onmouseout", RolloffTopicLine( TRLine ) );
	//***/  dbgOut( "Done Rolling off Topic Line." );
}


function  RolloverTopicItemLine( evt, TRLine, LinkData, KeyMode, SearchField, SearchString, SearchType, ClickAction )  {

	//***/  dbgOut( "RolloverTopicItemLine( " + LinkData, KeyMode + " ):" );

	var  RolloverEvent = evt  ||  window.event;
	var  arrLink = LinkData.split( "|" );
	var  TCode = arrLink[ 0 ];

	if  ( typeof( KeyMode ) == "undefined" )
		KeyMode = "";
	if  ( typeof( SearchType ) == "undefined" )
		SearchType = "String";
	if  ( typeof( ClickAction ) == "undefined" )
		ClickAction = "";
	if  ( ClickAction == "Edit" )  {
		TRLine.style.color = "red";
		addElemEvent( TRLine, "onclick", function () { curForm.action = "admin_topics.php"; setScreenAction( "Select", TCode, "", "Submit" ); } );
	}
	//addElemEvent( TRLine, "onmouseout", RolloffTopicLine( TRLine ) );
	addElemEvent( TRLine, "onmouseout", function () { ajaxHide(); TRLine.style.color = ""; } );

	var  InfoCode = new  Array();
	InfoCode[ "LinkData"     ] = LinkData;
	InfoCode[ "KeyMode"      ] = KeyMode;
	InfoCode[ "SearchField"  ] = SearchField;
	InfoCode[ "SearchString" ] = SearchString;
	InfoCode[ "SearchType"   ] = SearchType;
	InfoCode[ "DisplayMode"  ] = ( RolloverEvent.shiftKey  ?  "HTML"  :  "Text" );
	InfoCode[ "OtherInfo"    ] = ""; //describeDOMObj( TRLine );
	//***/  alert( "\"" + SearchString + "\"" );
	try  {
		ajaxInfoWindow( "TopicItemText", InfoCode, 3 );
	}
	catch( err ) {
		/***/  alert( "RolloverTopicItemLine Error, TCode = " + TCode + "\n" + err.description );
	};
	//***/  dbgOut( "Done Rolling over Topic Line.", "NoClear" );
}


function  RolloverTopicLink( evt, LinkField, LinkData )  {

	var  RolloverEvent = evt  ||  window.event;

	var  arrLink = LinkData.split( "|" );

	switch  ( arrLink.length )  {

		case 4:
				TOCType = ( RolloverEvent.shiftKey  ?  "TopicItemTOCHTML"  :  "TopicItemTOCText" );
				break;

		case 3:
				TOCType = "TopicGroupTOC";
				break;

		case 2:
				TOCType = "TopicSectionTOC";
				break;

		case 1:
		default:
				TOCType = "TopicTOC";
			break;
	}

	//***/  alert( "LinkData = \"" + LinkData + "\", TOCType = \"" + TOCType + "\"" );

	addElemEvent( LinkField, "onmouseout", function () { LinkField.onmouseout=null; ajaxHide(); } );
	try  {
		ajaxInfoWindow( TOCType, "NTag:" + LinkData, 3 );
	}
	catch( e ) {};
}


function  RolloverTopicHRef( evt, LinkField, LinkData )  {

	RolloverTopicLink( evt, LinkField, LinkData );
}


function  RolloverLinkList( evt, ListField )  {

	//***/  dbgOut( "RolloverLinkList: " + TCode, "NoClear" );

	var  RolloverEvent = evt  ||  window.event;

	if  ( ListField.value != "0" )  {

		var  fName, TOCType, TOCMode;

		fName = ListField.name;
		TOCType = TOCMode = "";

		switch  ( fName )  {

			case  "fTLinks":
				TOCType = "TopicTOC";
				TOCMode = "Topic";
				break;

			case  "fSLinks":
				TOCType = "TopicSectionTOC";
				TOCMode = "Section";
				break;

			case  "fGLinks":
				TOCType = "TopicGroupTOC";
				TOCMode = "Group";
				break;

			case  "fILinks":
				TOCType = ( RolloverEvent.shiftKey  ?  "TopicItemTOCHTML"  :  "TopicItemTOCText" );
				TOCMode = "Item";
				break;
		}

	  var  strLinkCodes = getLinkListCodes( TOCMode );

		addElemEvent( ListField, "onmouseout", function () { ListField.onmouseout=null; ajaxHide(); } );

		try  {
			ajaxInfoWindow( TOCType, strLinkCodes, 3 );
		}
		catch( e ) {};
	}
	//***/  dbgOut( "Done Rolling over Link List Field.", "NoClear" );
}


function  RolloverProductHeader( HeaderLine, ProductCode, ItemCode )  {

	var  ProductName, AddItem;

	for  ( i in HeaderLine.childNodes )  {
		if  ( HeaderLine.childNodes[ i ].className == "ProductHeader" )
			ProductName = HeaderLine.childNodes[ i ];
		if  ( HeaderLine.childNodes[ i ].className == "AddItemButton" )
			AddItem     = HeaderLine.childNodes[ i ];
	}

	//***/  alert( "HeaderLine = " + HeaderLine.childNodes.length + ", ProductName = " + ProductName.className + ", AddItem = " + AddItem.className  );

	if  ( ProductName.style.color == "" )  {
		addElemEvent( HeaderLine,  "onmouseout",  function () { ajaxHide(); ProductName.style.color = "white"; } );
		addElemEvent( ProductName, "onclick",     function () { goSelect( ItemCode, ProductCode ); return false; } );
		addElemEvent( ProductName, "ondblclick",  function () { selectInputListValue( "fProducts", "All" ); setScreenAction( "Display", ItemCode, "", "Submit" ); } );
		//addElemEvent( AddItem,     "onmouseover", function () { AddItem.style.color = "red"; } );
		addElemEvent( AddItem,     "onmouseout",  function () { AddItem.style.color = "white"; } );
		addElemEvent( AddItem,     "onclick",     function () { selectInputListValue( "fProducts", ProductCode ); setScreenAction( "Add", "" ); } );
	}

	ProductName.style.color = "red";

	try  {
		ajaxInfoWindow( "Product", ProductCode, 3 );
	}
	catch( err ) {
		/***/  alert( "RolloverProductHeader Error: ProductCode = " + ProductCode + ", ItemCode = " + ItemCode + "\n" + err.description );
	};
}


function  RolloverUserLine( UserLine, UID )  {

	//***/  dbgOut( "RolloverUserLine: " + TCode, "Clear" );
	UserLine.style.color = "red";
	addElemEvent( UserLine, "onmouseout", function () { ajaxHide(); UserLine.style.color = ""; } );
	addElemEvent( UserLine, "onclick", function () { setScreenAction( "Select", UID, "", "Submit" ); } );
	try  {
		ajaxInfoWindow( "User", UID, 3 );
	}
	catch( err ) {
		/***/  alert( "RolloverUserLine Error, UID = " + UID + "\n" + err.description );
	};
	//***/  dbgOut( "Done Rolling over User Line.", "NoClear" );
}


function  RolloverTableLine( TableLine, InfoType, InfoCode )  {

	TableLine.style.color = "red";
	addElemEvent( TableLine, "onmouseout", function () { ajaxHide(); TableLine.style.color = ""; } );
	addElemEvent( TableLine, "onclick", function () { setScreenAction( "Select", InfoCode, "", "Submit" ); } );
	try  {
		ajaxInfoWindow( InfoType, InfoCode, 3 );
	}
	catch( err ) {
		/***/  alert( "RolloverTableLine Error, InfoType = " + InfoType + ", InfoCode = " + InfoCode + "\n" + err.description );
	};
	//***/  dbgOut( "Done Rolling over Table Line.", "NoClear" );
}


function  RolloverInfoLine( InfoLine, InfoType, InfoCode )  {

	InfoLine.style.color = "red";
	addElemEvent( InfoLine, "onmouseout", function () { ajaxHide(); InfoLine.style.color = ""; } );
	try  {
		ajaxInfoWindow( InfoType, InfoCode, 3 );
	}
	catch( err ) {
		/***/  alert( "RolloverInfoLine Error, InfoType = " + InfoType + ", InfoCode = " + InfoCode + "\n" + err.description );
	};
	//***/  dbgOut( "Done Rolling over Info Line.", "NoClear" );
}


function  RolloverPMID( fPMID )  {

	var  PMID = getElemValue( fPMID, "" );
	var  InfoType = "AbstractInfo";
	var  InfoCode = trimStr( PMID );

	var  fCursorIO = new  CursorIO( fPMID );
	var  CursorText = fCursorIO.getText();

	if  ( !InfoCode  ||  PMID == CursorText )
		return  true;

	if  ( InfoCode )  {
		fPMID.style.color = "red";
		addElemEvent( fPMID, "onmouseout", function () { ajaxHide(); fPMID.style.color = ""; } );
		try  {
			ajaxInfoWindow( InfoType, InfoCode, 3 );
		}
		catch( err ) {
			/***/  alert( "RolloverPMID Error, fPMID = " + fPMID.id + "\n" + err.description );
		}
	}
	return  false;
}


function  RolloverMacroButton( MacroButton, MacroCommand )  {

	var  oldClass = MacroButton.className;
	var  MacroIW = "<div class=\"MacroCommandIW\">" + MacroCommand.replace( / /g, "&nbsp;" ) + "<div/>";

	addElemEvent( MacroButton,
	              "onmouseout",
	              function() {
	                MacroButton.onmouseout = null;
	                MacroButton.className  = oldClass;
	                ajaxHide();
	              } );
	try  {
		//***/  alert( "MacroButton.tagName = " + MacroButton.tagName );
		if  ( MacroButton.tagName == "DIV" )  {
			MacroButton.className = oldClass + "Hover";
		}
		//***/  alert( "MacroButton.className = " + MacroButton.className );
		InfoTableStyle( MacroButton.innerHTML, MacroIW, 3 );
	}
	catch( e ) {};
}



/******************************************************************************
  initTopicNameField
    EAH - September 2, 2008

    Special function to initialize the TopicName field from the TopicCode.

******************************************************************************/

function  initTopicNameField( TName )  {

	if  ( trimStr( TName ) != "" )  {

		var  fTName = getElem( "fTName" );

		if  ( fTName.value == ""  ||  fTName.value == "-" )  {
			fTName.value = TName;
		}
	}

	EnforceRequiredFields();
}



/******************************************************************************
  enableInsertButtons
    EAH - November 21, 2007

    Enables or Disables the Insert Link buttons so that only a valid link from
    the Link Selection List can be inserted into the ItemText field.

******************************************************************************/

function  enableInsertButtons( LinkMode, TCode, SNTag, GNTag, INTag )  {

	//***/  dbgOut( "enableInsertButtons: LinkMode = " + LinkMode + "\n" );


	//**!!!!!!!!!  Add an "isLinkable" function !!!!!!!!!!!

	enableInsertButton( "fbtnInsTLink", TCode, "Link"   );    //  Enable Topic button for Load, Link, and HyperLink.
	enableInsertButton( "fbtnInsSLink", SNTag, LinkMode );
	enableInsertButton( "fbtnInsGLink", GNTag, LinkMode );
	enableInsertButton( "fbtnInsILink", INTag, LinkMode );

}


function enableInsertButton( fbtnInsLink, LinkCode, LinkMode )  {

	var  btnInsLink;

	if  ( ( btnInsLink = getElem( fbtnInsLink ) ) )
		btnInsLink.disabled = ( ( LinkMode != "Link"  &&  LinkMode != "HyperLink" )  ||  LinkCode == null  ||  LinkCode == 0  ||  LinkTargetLine == 0 );

  //***/ dbgOut( "enableInsertButton( " + fbtnInsLink + ", " + LinkCode + ", " + LinkMode + " ) = \"" + btnInsLink.disabled + "\"" );

}



/******************************************************************************
  getLinkListValue
    EAH - October 10, 2007

    Gets the Link List values and formats the appropriate Link Field value.

******************************************************************************/

function  getLinkListValue( EditMode )  {

	  var  TCode = getElemValue( "fTLinks" );
	  var  SNTag = getElemValue( "fSLinks" );
	  var  GNTag = getElemValue( "fGLinks" );
	  var  INTag = getElemValue( "fILinks" );

	  var  strLinkField = TCode;

	  if  ( EditMode == "Section"  ||  EditMode == "Group"  ||  EditMode == "Item" )
			strLinkField += "|" + SNTag;

	  if  ( EditMode == "Group"  ||  EditMode == "Item" )
			strLinkField += "|" + GNTag;

	  if  ( EditMode == "Item" )
			strLinkField += "|" + INTag;

		return  strLinkField;
}



function  getLinkListText( EditMode )  {

	  var  TText = getInputListText( "fTLinks" );
	  var  SText = getInputListText( "fSLinks" );
	  var  GText = getInputListText( "fGLinks" );
	  var  IText = getInputListText( "fILinks" );

	  var  strLinkField = TText;

	  if  ( EditMode == "Section"  ||  EditMode == "Group"  ||  EditMode == "Item" )
			strLinkField += "|" + SText;

	  if  ( EditMode == "Group"  ||  EditMode == "Item" )
			strLinkField += "|" + GText;

	  if  ( EditMode == "Item" )
			strLinkField += "|" + IText;

		return  strLinkField;
}



function  getLinkListCodes( EditMode )  {

	  var  TCode = getLinkListCode( "fTLinks" );
	  var  SCode = getLinkListCode( "fSLinks" );
	  var  GCode = getLinkListCode( "fGLinks" );
	  var  ICode = getLinkListCode( "fILinks" );

	  var  strLinkField = TCode;

	  if  ( EditMode == "Section"  ||  EditMode == "Group"  ||  EditMode == "Item" )
			strLinkField += "|" + SCode;

	  if  ( EditMode == "Group"  ||  EditMode == "Item" )
			strLinkField += "|" + GCode;

	  if  ( EditMode == "Item" )
			strLinkField += "|" + ICode;

		return  strLinkField;
}



/******************************************************************************
  getLinkListCode
    EAH - May 16, 2008

    Gets the Topic Section, Group, or Item Code from the given LinkListElement.

    The List Title is in the format:
    	< Code > - < Title | NTag >

******************************************************************************/

function  getLinkListCode( LinkListElement )  {

	if  ( LinkListElement == "fTLinks" )
		return  getInputListValue( LinkListElement );
	else  {
		var  ListTitle = getInputListText( LinkListElement );
		var  arrListTitle = ListTitle.split( " - " );
		return  arrListTitle[ 0 ];
	}
}



function  getLinkListNTags( EditMode )  {

	var  TCode = getLinkListCode( "fTLinks" );
	var  SNTag = getLinkListNTag( "fSLinks" );
	var  GNTag = getLinkListNTag( "fGLinks" );
	var  INTag = getLinkListNTag( "fILinks" );

	var  strLinkField = TCode;

	if  ( EditMode == "Section"  ||  EditMode == "Group"  ||  EditMode == "Item" )
		if  ( SNTag != "" )
			strLinkField += "|" + SNTag;
		else
			strLinkField = "";

	if  ( EditMode == "Group"  ||  EditMode == "Item" )
		if  ( GNTag != ""  &&  strLinkField != "" )
			strLinkField += "|" + GNTag;

	if  ( EditMode == "Item" )
		if  ( INTag != ""  &&  strLinkField != "" )
			strLinkField += "|" + INTag;

	/***/  dbgStr += "\nstrLinkField = \"" + strLinkField + "\"\n";
	return  strLinkField;
}



/******************************************************************************
  getLinkListNTag
    EAH - May 16, 2008

    Gets the Topic Section, Group, or Item NTag from the given LinkListElement.

    The List Title is in the format:
    	< Code > - < Title | NTag >
    or:
    	< Code > - [< NTag >] < Title >

******************************************************************************/

function  getLinkListNTag( LinkListElement )  {

	//***/  dbgStr += "\ngetLinkListNTag\n";

	var  UseNTagBrackets = true;
	var  ListTitle = getInputListText( LinkListElement );
	var  arrListTitle = ListTitle.split( " - " );

	//***/  dbgStr += LinkListElement + " = \"" + ListTitle + "\"\n";

	if  ( arrListTitle.length <= 1 )
		return  "";

	if  ( UseNTagBrackets  &&  arrListTitle[ 1 ].indexOf( "[" ) == 0 )  {
		//***/  dbgStr += "NTag = " + getBracketedText( arrListTitle[ 1 ] ) + "\n";
		return  ( getBracketedText( arrListTitle[ 1 ] ) );
	}
	else  {
		if  ( arrListTitle[ 1 ].indexOf( " " ) > 0 )  {
			return  "";
		}
		else  {
			return  arrListTitle[ 1 ];
		}
	}
}



function  getLinkListNames( EditMode )  {

	var  TName = getLinkListText( "fTLinks" );
	var  SName = getLinkListName( "fSLinks" );
	var  GName = getLinkListName( "fGLinks" );
	var  IName = getLinkListName( "fILinks" );

	var  strLinkField = ( TName.substr( 0, 10 ) != "-- Select "  ?  TName  :  "" );

	if  ( EditMode == "Section"  ||  EditMode == "Group"  ||  EditMode == "Item" )
		if  ( SName != ""  &&  SName.substr( 0, 10 ) != "-- Select "  &&  strLinkField != "" )
			strLinkField += "|" + SName;
		/***
		else
			strLinkField = "";
		***/

	if  ( EditMode == "Group"  ||  EditMode == "Item" )
		if  ( GName != ""  &&  GName.substr( 0, 10 ) != "-- Select "  &&  strLinkField != "" )
			strLinkField += "|" + GName;

	if  ( EditMode == "Item" )
		if  ( IName != ""  &&  IName.substr( 0, 10 ) != "-- Select "  &&  strLinkField != "" )
			strLinkField += "|" + IName;

	/***/  dbgStr += "\nstrLinkField = \"" + strLinkField + "\"\n";
	return  strLinkField;
}



/******************************************************************************
  getLinkListName
    EAH - May 16, 2008

    Gets the Topic Section, Group, or Item Name from the given LinkListElement.

    The List Title is in the format:
    	< Code > - < Title | NTag >
    or:
    	< Code > - [< NTag >] < Title >

******************************************************************************/

function  getLinkListName( LinkListElement )  {

	/***/  dbgStr += "\ngetLinkListName\n";

	var  UseNTagBrackets = true;
	var  ListTitle = getInputListText( LinkListElement );

	if  ( LinkListElement == "fTLinks" )
		return  ListTitle;

	var  arrListTitle = ListTitle.split( " - " );

	/***/  dbgStr += LinkListElement + " = \"" + ListTitle + "\"\n";

	if  ( arrListTitle.length <= 1 )
		return  "";

	if  ( UseNTagBrackets  &&  arrListTitle[ 1 ].indexOf( "[" ) == 0 )  {
		/***/  dbgStr += "NTag = " + getBracketedText( arrListTitle[ 1 ] ) + "\n";
		/***/  dbgOut();
		var  posSpace = arrListTitle[ 1 ].indexOf( "] " );
		if  ( posSpace > 0 )  {
			return  arrListTitle[ 1 ].substr( posSpace + 2 );
		}
	}
	return  arrListTitle[ 1 ];
}



/******************************************************************************
  createCurDataLinkList
    EAH - February 4, 2009

    Creates a LinkList string from the current Topic, Section, Group, and Item
    data according to the current EditMode.

******************************************************************************/

function  createCurDataLinkList( EditMode, LinkMode )  {

	//***/  dbgOut( "createCurDataLinkList( " + EditMode + ", " + LinkMode + " )" );

	var  strLinkValue = getElemValue( "fTCode" );
	var  strLinkTitle = getElemValue( "fTName" );

	var  ContinueBuildingLink = true;

	var  LValue, LTitle;


	function  getLevelLinkData( Level )  {

		var  LFID = "f" + Level.substr( 0, 1 );

		if  ( Level == EditMode )  {
			fLinkTargetLine = getElem( "LinkTargetLine" );
			LinkTargetLine = fLinkTargetLine.value;
			var  LFIX = FieldIndexDelimiter + LinkTargetLine;
		}
		else  {
			var  LFIX = "";
		}

		var  LCode = trimStr( getElemValue( LFID + "Code" + LFIX ) );
		var  LNTag = trimStr( getElemValue( LFID + "NTag" + LFIX ) );
		var  LName = trimStr( getElemValue( LFID + "Name" + LFIX ) );

		LValue = ( LinkMode == "Load"  ?  LCode  :  LNTag );
		LTitle = formatLinkListTitle( LCode, LNTag, LName );
		ContinueBuildingLink = ( ContinueBuildingLink  &&  ( LValue != "" ) );
	}


	if  ( EditMode == "Section"  ||  EditMode == "Group"  ||  EditMode == "Item" )  {
		getLevelLinkData( "Section" );
		if  ( ContinueBuildingLink )  {
			strLinkValue += "|" + LValue;
			strLinkTitle += "|" + LTitle;
		}
	}

	if  ( EditMode == "Group"  ||  EditMode == "Item" )  {
		getLevelLinkData( "Group" );
		if  ( ContinueBuildingLink )  {
			strLinkValue += "|" + LValue;
			strLinkTitle += "|" + LTitle;
		}
	}

	if  ( EditMode == "Item" )  {
		getLevelLinkData( "Item" );
		if  ( ContinueBuildingLink )  {
			strLinkValue += "|" + LValue;
			strLinkTitle += "|" + LTitle;
		}
	}

	/***/  dbgStr += "\nstrLinkValue = \"" + strLinkValue + "\", strLinkTitle = \"" + strLinkTitle + "\"\n";

	return  new  Array( strLinkValue, strLinkTitle );

}



function  formatLinkListTitle( LCode, LNTag, LName )  {

	var  UseNTagBrackets = true;

	if  ( UseNTagBrackets )
		return  LCode + " - [" + LNTag + "] " + LName;
	else
		return   ( LName != ""  ?  LCode + " - " + LName  :  ( LNTag != ""  ?  LCode + " - " + LNTag  :  LCode ) );
}



/******************************************************************************
  getBracketedText
    EAH - September 29, 2008

    Returns text that is enclosed in square brackets inside the strIn parameter.

    Example:
    	"2 - [folicacid] Folic Acid"
    returns:
    	"folicacid"

******************************************************************************/

function  getBracketedText( strIn )  {

	var  BL = strIn.indexOf( "[" );
	var  BR = strIn.indexOf( "]" );
	var  strOut = strIn.substr( BL + 1, BR - ( BL + 1 ) );
	//***/  dbgStr += "getBracketedText( " + strIn + " ):\n[pos = \"" + BL + "\", ]pos = \"" + BR + "\", strOut = \"" + strOut + "\"\n";
	return  ( strOut );
}



/******************************************************************************
  extractLinkListName
    EAH - August 23, 2008

    Gets the Topic Section, Group, or Item Name from the given LinkList Element
    Title.

    The List Title is in the format:
    	< Code > - < Title | NTag >

******************************************************************************/

function  extractLinkListName( ListTitle )  {

	var  arrListTitle = ListTitle.split( " - " );

	if  ( arrListTitle.length <= 1 )
		return  "";
	else
		return  arrListTitle[ 1 ];
}



/******************************************************************************
  getHyperLinkListValue
    EAH - February 6, 2008

    Gets the Link List values and formats the appropriate HyperLink Field value.

******************************************************************************/

function  getHyperLinkListValue( EditMode )  {

	  var  TCode = getElemValue( "fTLinks" );
	  var  SNTag = getElemValue( "fSLinks" );
	  var  GNTag = getElemValue( "fGLinks" );
	  var  INTag = getElemValue( "fILinks" );

	  strLinkField = "/topics.php?Topic=" + TCode + "#" + SNTag;

	  if  ( EditMode == "Group"  ||  EditMode == "Item" )
			strLinkField += "-" + GNTag;

	  if  ( EditMode == "Item" )
			strLinkField += "-" + INTag;

		return  strLinkField;
}



/******************************************************************************
  getTopicLinkMode
  setTopicLinkMode
    EAH - October 30, 2007

    Gets/Sets the Topic Link Mode from the fLinkMode[] radio buttons.

******************************************************************************/

function  getTopicLinkMode()  {

	return  getRadioButtonValue( "fLinkMode[]", "Link" );

}


function  setTopicLinkMode( LinkMode )  {

	return  setRadioButton( "fLinkMode[]", LinkMode );

}



/******************************************************************************
  nextLinkTarget
    EAH - November 19, 2008

    Advances the Target line number to the next Section or Group for the Link,
    Load, and Insert buttons.

    This function was written especially for use with the EditFieldFormat
    feature.

******************************************************************************/

function  nextLinkTarget()  {

  var  fldTarget;

	var  EditMode = getElemValue( "EditMode" );
	var  fLinkTargetLine = getElem( "LinkTargetLine" );

	switch  ( EditMode )  {

		case  "Section":
			TFID = "fS";
			break;

		case  "Group":
			TFID = "fG";
			break;

		case  "Item":
			TFID = "fI";
			break;

		default:
			return;
			break;
	}

	/***/  dbgStr += "\nnextLinkTarget:\n";
	/***/  dbgStr += "LinkTargetLine = \"" + LinkTargetLine + "\", fLinkTargetLine.value = \"" + fLinkTargetLine.value + "\"\n";

	if  ( fLinkTargetLine.value > 0 ) {
		fLinkTargetLine.value++;

	 	if  ( ( fldTarget = getElem( TFID + "Code" + FieldIndexDelimiter + fLinkTargetLine.value ) ) )
	 		setLinkTarget( fldTarget );
		else  {
			/***/  dbgStr += "Unsetting the LinkTargetLine...\n";
			fLinkTargetLine.value--;
		 	if  ( ( fldTarget = getElem( TFID + "Code" + FieldIndexDelimiter + fLinkTargetLine.value ) ) )
		 		setLinkTarget( fldTarget, true );
		}
	}
	/***/  dbgStr += "LinkTargetLine = \"" + LinkTargetLine + "\", fLinkTargetLine.value = \"" + fLinkTargetLine.value + "\"\n";
	/***/  dbgStr += "End nextLinkTarget:\n\n";
	/***/  dbgOut();
}




/******************************************************************************
  setLinkTarget
    EAH - February 1, 2008

    Sets the Target line number of the Section or Group for the Link, Load,
    and Insert buttons.
    If the optional flgUnset flag is true, then the Background Color of the
    current Target line is reset and the Target line number is set to 0.

******************************************************************************/

function  setLinkTarget( fldTarget, flgUnset )  {

	var  CodeField, NameField, NTagField, LinkField, HRefField, UsedNTag, MovedFlag,
	     TFID, TName, targetName, targetNTag;

	targetName = targetNTag = "";

	var  LinkMode = getTopicLinkMode();
	var  EditMode = getElemValue( "EditMode" );

	var  fldID           = fldTarget.name;
	var  arrTFIX         = fldID.split( FieldIndexDelimiter );
	var  TFIX            = arrTFIX[ 1 ];
	var  flgUnsetTarget  = ( typeof( flgUnset ) != "undefined"  &&  flgUnset == true );
	var  fLinkTargetLine = getElem( "LinkTargetLine" );
	var  flgClearTarget  = ( LinkTargetLine == TFIX );

	LinkTargetLine = fLinkTargetLine.value = TFIX;

	/***/  dbgStr += "\nsetLinkTarget( " + fldID + ", flgUnset = \"" + flgUnsetTarget + "\"\n";

	var  TCode = getInputListValue( "fTLinks", null );
	var  SNTag = getInputListValue( "fSLinks", null );
	var  GNTag = getInputListValue( "fGLinks", null );
	var  INTag = getInputListValue( "fILinks", null );

	switch  ( EditMode )  {

		case  "Section":
			TFID = "fS";
			break;

		case  "Group":
			TFID = "fG";
			break;

		case  "Item":
			TFID = "fI";
			break;

		default:
			return;
			break;
	}


	/***  Highlight the selected entry line:  ***/

	var  bgColor = "lightblue";
	var  idx = 1;

	while  ( ( CodeField = getElem( TFID + "Code" + FieldIndexDelimiter + idx ) )  ||  idx < TFIX )  {
		if  ( CodeField )  {
			NameField = getElem( TFID + "Name" + FieldIndexDelimiter + idx );
			NTagField = getElem( TFID + "NTag" + FieldIndexDelimiter + idx );
			LinkField = getElem( TFID + "Link" + FieldIndexDelimiter + idx );
			HRefField = getElem( TFID + "HRef" + FieldIndexDelimiter + idx );
			UsedNTag  = getElem( TFID + "UNTg" + FieldIndexDelimiter + idx );
			MovedFlag = getElem( TFID + "Movd" + FieldIndexDelimiter + idx );

			if  ( idx == TFIX  &&  !flgUnsetTarget )  {
				if  ( flgClearTarget  &&  !MovedFlag.value )  {
					SwapFieldValue( NameField );
					SwapFieldValue( NTagField );
				}
				bgColor = ( UsedNTag.value  ||  MovedFlag.value  ?  "#FFCC66"  :  "lightblue" );
				targetName = NameField.value;
				targetNTag = NTagField.value;
			}
			else
				bgColor = "";

			//***/  dbgStr += TFID + FieldIndexDelimiter + idx + " bgColor = \"" + bgColor + "\"\n";
			//***/  dbgStr += "CodeField.style.cssText = \"" + CodeField.style.cssText + "\"\n";
			CodeField.style.backgroundColor =
			NameField.style.backgroundColor =
			NTagField.style.backgroundColor =
			LinkField.style.backgroundColor =
			HRefField.style.backgroundColor = bgColor;
		}
		idx++;
	}

	/***  Set the LinkList Topic to the NameField value:  ***/

	if  ( flgUnsetTarget )  {
		LinkTargetLine = fLinkTargetLine.value = 0;
	}
	else  {
		if  ( targetName != ""  ||  targetNTag != "" )  {
			var  fTLinks = getElem( "fTLinks" );
			var  TLinks = getInputList( fTLinks );
			for  ( var idx = 0;  idx < TLinks.length;  idx++ )  {
				if  ( TLinks[idx].value == targetNTag  ||  TLinks[idx].text == targetName )  {
					TCode = TLinks[idx].value;
					TName = TLinks[idx].text;
				}
			}
			if  ( TCode != "" )  {
				selectInputListValue( fTLinks, TCode );
				setLinkList( fTLinks );
			}
		}

	enableLinkButtons( LinkMode, EditMode, "setLinkTarget" );
	enableMacroButtons();
	}
	/***/  dbgStr += "End setLinkTarget:\n\n";
}



/******************************************************************************
  setCursorField
    EAH - February 6, 2008

    Sets the CurrentCursorField.

******************************************************************************/

function  setCursorField( fldCursor )  {

	var  fldID = ( typeof( fldCursor ) == "string"  ?  fldCursor  :  fldCursor.name );
	var  CurrentCursorField = getElem( "CurrentCursorField" );

	CurrentCursorField.value = fldID;
}



/******************************************************************************
  setSecurityList
    EAH - March 17, 2010

    Sets the Security Values List Field to the values specified by
    the Security Type Field.

******************************************************************************/

function  setSecurityList( fldSecType )  {

	xajax_setSecurityList( getElemValue( fldSecType ) );
}



/******************************************************************************
  setTableFieldList
    EAH - May 18, 2010

    Sets the Table Field drop-down list element to the field names for the
    table specified by the Table drop-down list.

******************************************************************************/

function  setTableFieldList( elemTables, fldFields )  {

	var  curTable = getInputListValue( elemTables ) + ".";

	if  ( curTable != 0 )  {
		var  arrFields = document.getElementsByName( "TableFields[]" );
		//***/  alert( "setTableFieldList: arrFields =\n" + describeDOMObj( arrFields ) );

		var  fFields = getElem( fldFields );
		fFields.disabled = false;
		fFields.options.length = 0;
		fFields.options[ 0 ] = new Option( "--  Select Field  --", 0 );

		var  curField;
		for  ( var  idx = 0;  idx < arrFields.length;  idx++ )  {
			curField = arrFields[ idx ];
			//***/  alert( "setTableFieldList: curField =\n" + describeObj( curField ) );
			//***/  alert( "setTableFieldList: curField =\n" + curField.value );
			if  ( curField.value.startsWith( curTable ) )  {
				fFields.options[ fFields.options.length ] = new Option( curField.value.substr( curTable.length ), curField.value );
			}
		}
		//***/  alert( "setTableFieldList: tblFields =\n" + describeObj( tblFields ) );
	}
}



/******************************************************************************
  setLinkField
    EAH - October 5, 2007

    Sets the given Link or HyperLink Field to the Topics Link List selection.

******************************************************************************/

function  ReferenceUtility( evt, btnElem )  {

	var  btnEvent, btnID, btnAction;

	btnEvent  = evt  ||  window.event;
	//btnID     = btnElem.name;
	btnAction = btnElem.value;

	switch  ( btnAction )  {

		case  "Find":
			var  FindText = getCursorText();
			if  ( FindText == "" )
				FindText = "Existing Terms";
			xajax_loadReferenceTerms( "Find", FindText );
			break;

		case  "Unwanted":
			var  UnwantedText = getCursorText( "Cut" );
			if  ( UnwantedText )  {
				var  NewUnwanted = getElemValue( "NewUnwanted" ) + "\n" + UnwantedText;
				setElemValue( "NewUnwanted", NewUnwanted );
				//alert( NewUnwanted );
				var  SourceWords = getElemValue( "save_fWords" );
				xajax_loadReferenceTerms( "Unwanted", SourceWords, NewUnwanted );
			}
			break;

		case  "Show References":
			var  RefText = getCursorText();
			ajaxInfoWindow( "References", RefText, 3 );
			addElemEvent( btnElem, "onmouseout", function () { ajaxHide(); } );
			break;

		case  "Show Abstracts":
			var  RefText = getCursorText();
			ajaxInfoWindow( "AbstractList", RefText, 3 );
			addElemEvent( btnElem, "onmouseout", function () { ajaxHide(); } );
			break;

		case  "Show Topic":
			var  RefText = getCursorText();
			var  InfoCode = [];
			InfoCode[ "DisplayMode" ] = ( btnEvent.shiftKey  ?  "HTML"  :  "Text" );
			InfoCode[ "TopicName"   ] = RefText;
			ajaxInfoWindow( "ViewReferenceTopic", InfoCode, 3 );
			addElemEvent( btnElem, "onmouseout", function () { ajaxHide(); } );
			break;

		case  "Diagram":
			var  RefText = getCursorText();

			var  TestIO = new CursorIO( "fSourceText" );
			var  tmpText = TestIO.getText();
			alert( "TextIO.getText() =\"" + tmpText + "\"" );
			TestIO.putText( "!New Text!", "Select", " #1 ^", "^ #2 " );
			//TestIO.putText( "!New Text!", "Select" );
			//TestIO.putText( "%Clipboard%", "Select", " #1 ^", "^ #2 " );

			//xajax_diagramRelatedTerms( RefText );
			break;

	}
}



/******************************************************************************
  setLinkField
    EAH - October 5, 2007

    Sets the given Link or HyperLink Field to the Topics Link List selection.

******************************************************************************/

function  setLinkField( btnElem )  {

	var  btnID, LinkAction, LFIX, LFID, EditMode, LinkMode;

	if  ( btnElem == "Macro"  ||  btnElem == "SaveLinkList" )  {
		btnID = LinkAction = btnElem;
	}
	else  {
		btnID = btnElem.name;
		LinkAction = btnElem.value;
	}

	/***/  dbgStr += "setLinkField( " + btnID + " ):\n\n";
	//***/  dbgOut();

	LFIX = getElemValue( "LinkTargetLine" );
	if  ( LFIX == 0 )
		return;

	disableLinkButtons();

	EditMode = getElemValue( "EditMode" );
  LinkMode = getTopicLinkMode();

	switch  ( EditMode )  {

		case  "Section":
			LFID = "fS";
			break;

		case  "Group":
			LFID = "fG";
			break;

		case  "Item":
			LFID = "fI";
			break;

		default:
			return;
			break;
	}

	//***/  dbgOut( "LFID = " + LFID + ", LFIX = " + LFIX );
	//***/  dbgOut( "LinkAction = \"" + LinkAction + "\", LinkMode = \"" + LinkMode + "\", EditMode = \"" + EditMode + "\"" );

	var  strLinkList  = getLinkListValue( EditMode );
	var  strLinkText  = getLinkListText ( EditMode );
	var  strLinkNames = getLinkListNames( EditMode );
  var  strLinkCodes = getLinkListCodes( EditMode );
  var  strLinkNTags = getLinkListNTags( EditMode );

	//***/  dbgOut( "strLinkList = \"" + strLinkList + "\", strLinkText = \"" + strLinkText + "\", strLinkCodes = \"" + strLinkCodes + "\", strLinkNTags = \"" + strLinkNTags + "\"" );

  var  TTypes = getInputListValue( "fTTypes[]" );

	var  NameFieldName = LFID + "Name" + FieldIndexDelimiter + LFIX;
	var  NTagFieldName = LFID + "NTag" + FieldIndexDelimiter + LFIX;
	var  HRefFieldName = LFID + "HRef" + FieldIndexDelimiter + LFIX;

	var  flgOverwriteSubItems = true;


	switch  ( LinkAction )  {

		case  "Link":
		case  "Load":
		case  "Move":

			var  NSubItems = getElemValue( LFID + "NSub" + FieldIndexDelimiter + LFIX, 0 );

			var  strConfirm = "This " + EditMode + " contains " + NSubItems + " existing " + ( EditMode == "Section"  ?  "Groups"  :  "Items" ) + ".\n" +
			                  "Are you sure you want to delete them?";

			flgOverwriteSubItems = ( ( NSubItems == 0 )  ||  ( NSubItems > 0)  &&  confirm( strConfirm ) );
			break;
	}


	switch  ( LinkAction )  {

		/***
		 *    Admin Topics Actions:
		 *    =====================
		***/

		case  "Load":
		case  "Move":
		case  "Insert":
		case  "Include":
		case  "Pointer":

			if  ( flgOverwriteSubItems )  {
			  var  TCode = getElemValue( "fTCode", "" );
			  var  SCode = getElemValue( "fSCode", "" );
			  var  GCode = getElemValue( "fGCode", "" );

			  //***/  dbgOut( "TCode = \"" + TCode + "\", SCode = \"" + SCode + "\", GCode = \"" + GCode + "\"" );
			  /***/  dbgOut( "LinkAction = \"" + LinkAction + "\"" );

				xajax_loadTopicLinkedData( LinkMode, EditMode, LinkAction, LFIX, strLinkList, strLinkText, strLinkNames, strLinkCodes, strLinkNTags, TTypes, TCode, SCode, GCode, isMacroRunning );
			}
			break;


		case  "HyperLink":

			/***/  alert( "Tell Ed that you saw this message!\n(It's for debugging purposes, so please let me know what you did.)" );

			var  HRefField = getElem( LFID + "HRef" + FieldIndexDelimiter + LFIX );

			if  ( typeof( HRefField ) != "undefined" )
			  HRefField.value = convertLink2HyperLink( strLinkList );

			xajax_saveLinkData( LinkMode, strLinkList, TTypes, strLinkText );
			break;


		case  "Link":

			if  ( flgOverwriteSubItems )  {
				var  NTagField = getElem( LFID + "NTag" + FieldIndexDelimiter + LFIX );
				var  LinkField = getElem( LFID + "Link" + FieldIndexDelimiter + LFIX );
				var  TypeField = getElem( LFID + "Type" + FieldIndexDelimiter + LFIX );
				var  TextField = getElem( LFID + "Text" + FieldIndexDelimiter + LFIX );
				var  DataField = getElem( LFID + "Data" + FieldIndexDelimiter + LFIX );
				var  SctyField = getElem( LFID + "Scty" + FieldIndexDelimiter + LFIX );

				if  ( LinkField  &&  typeof( LinkField ) != "undefined" )  {

				  LinkField.value = ( LinkMode == "Load"  ?  strLinkNTags  :  strLinkList );

					if  ( TypeField  &&  typeof( TypeField ) != "undefined" )
						selectInputListValue( TypeField, "Link" );

					if  ( NTagField  &&  typeof( NTagField ) != "undefined" )
						NTagField.value = "";

					if  ( TextField  &&  typeof( TextField ) != "undefined" )
						TextField.value = "";

					if  ( DataField  &&  typeof( DataField ) != "undefined" )
						DataField.value = "";

					if  ( SctyField  &&  typeof( SctyField ) != "undefined" )
						SctyField.value = "";
				}
				enableEditFieldSetting( EditMode, LinkAction, LFID, LFIX, strLinkNames, strLinkCodes, strLinkNTags );
				enableNTagSetting( NTagField, strLinkNTags, ( EditMode == "Item"  ?  3  :  0 ) );
				xajax_saveLinkData( LinkMode, strLinkList, TTypes, strLinkText );
			}
			break;


		case  "Macro":
			enableEditFieldSetting( EditMode, LinkAction, LFID, LFIX, strLinkNames, strLinkCodes, strLinkNTags );
			break;


		/***
		 *    Admin References Actions:
		 *    =========================
		***/

		case  "Load Item":

			setElemValue( "fResults", "Loading Item..." );
			var  NewUnwanted = getElemValue( "NewUnwanted" );
			xajax_getTopicItemText( LinkMode, strLinkList, strLinkText, TTypes, NewUnwanted );
			break;


		case  "Load Terms":

			setElemValue( "fResults", "Loading Terms..." );
			var  SourceText = getElemValue( "fSourceText" );
			var  NewUnwanted = getElemValue( "NewUnwanted" );
			xajax_loadReferenceTerms( "Load", SourceText, NewUnwanted, strLinkList );
			break;


		case  "Where Used":

			ajaxInfoWindow( "WhereLinkUsed", strLinkList, 3 );
			addElemEvent( btnElem, "onmouseout", function () { ajaxHide(); } );
			break;


		case  "Process":

			setElemValue( "fResults", "Processing..." );
			var  References = getElemValue( "fReferences" );
			var  NewUnwanted = getElemValue( "NewUnwanted" );
			setElemValue( "NewUnwanted", "" );
			if  ( NewUnwanted  &&  !confirm( "Permanently mark these words as Unwanted?\n" + NewUnwanted ) )
				NewUnwanted = "";
			xajax_loadReferenceTerms( "Process", References, NewUnwanted, strLinkList );
			break;


		case  "Add These New Topics":

			setElemValue( "fResults", "Adding New Topics..." );
			var  AddTopics = getNewTopicsData();
			if  ( AddTopics )  {
				xajax_loadReferenceTerms( "Add Topics", AddTopics );
			}
			break;


		case  "SaveLinkList":
			xajax_saveLinkData( LinkMode, strLinkList, TTypes, strLinkText );
			break;

	}
	/***/  dbgStr += "\nEnd of setLinkField.\n";
	/***/  dbgOut();
}



/******************************************************************************
  getNewTopicsData
    EAH - April 15, 2009

    Returns an array of the New Topics table data from the Admin References
    screen.

******************************************************************************/

function getNewTopicsData()  {

	var  NewTopics = NewTopic = [];

	var  idx = 1;

	while  ( ( NewTopic = getNewTopicData( idx ) ) )  {
		NewTopics[ NewTopic[ "TopicCode" ] ] = NewTopic;
		idx++;
	}

	return  NewTopics;
}



function getNewTopicData( idx )  {

	var  NewTopic = [];

	if  ( ( NewTopic[ "TopicCode"   ] = getElemValue( "fTCode" + FieldIndexDelimiter + idx ) )  &&
		    ( NewTopic[ "TopicName"   ] = getElemValue( "fTName" + FieldIndexDelimiter + idx ) ) )  {
		      NewTopic[ "TopicType"   ] = getElemValue( "fTType" + FieldIndexDelimiter + idx );
		      NewTopic[ "TopicStatus" ] = getElemValue( "fTStat" + FieldIndexDelimiter + idx );
		      NewTopic[ "TopicIndex"  ] = getElemValue( "fTIndx" + FieldIndexDelimiter + idx );
		      NewTopic[ "TopicScty"   ] = getElemValue( "fTScty" + FieldIndexDelimiter + idx );
		return  NewTopic;
	}
	else
		return  null;
}



/******************************************************************************
  deParenthesize
    EAH - December 29, 2008

    Returns part of a string that may or may not contain parentheses.

    Usage:
      deParenthesize( <String> [, <Part> ] );

    Where:
      String = a string that may or may not contain parentheses.
      Part   = optional parameter:
               - if 0 or not given: return part before the parentheses.
               - if 1:              return part within the parentheses.

******************************************************************************/

function deParenthesize( s, part ) {
	var  p0 = 0;
	var  p1 = s.indexOf( "(" );
	var  p2 = s.length;
	if  ( typeof( part ) == "undefined"  ||  part == "" )
		part = 0;
	if  ( part == 0 )
		return  trimStr( s.substr( p0, ( p1 > p0  ?  p1  :  p2 ) ) );
	else  {
		p0 = p1 + 1;
		p1 = s.indexOf( ")" );
		return  trimStr( s.substr( p0, ( p1 > p0  ?  p1 - p0  :  p2 ) ) );
	}
}



/******************************************************************************
  enableEditFieldSetting
    EAH - December 29, 2008

    Allows the user to control the setting of the Name, NTag, and HRef fields
    when performing Link, Load, or Move operations.

    Usage:
      enableEditFieldSetting( EditMode, LinkAction, FieldNamePrefix, FieldNameIndex, LinkNames, LinkCodes, LinkNTags );

    Where:
      FieldNamePrefix = fS, fG, or fI.
      FieldNameIndex  = the Index number of the current field.
      LinkNames, LinkCodes, LinkNTags = pipe-delimited values containing the
                                        LinkList Names, Codes, and NTags.

    User accessable variables:

      LinkList variables:
      - TLName, SLName, GLName, ILName
      - TLCode, SLCode, GLCode, ILCode
      - TLNTag, SLNTag, GLNTag, ILNTag

      Current entry field values:
      - NameFieldValue
      - NTagFieldValue
      - LinkFieldValue
      - HRefFieldValue

      Variables used to set new entry field values:
      - Name
      - NTag
      - HRef

******************************************************************************/

function  enableEditFieldSetting( EditMode, LinkAction, FieldNamePrefix, FieldNameIndex, LinkNames, LinkCodes, LinkNTags )  {

	/***/  dbgStr += "enableEditFieldSetting( " + EditMode + ", " + LinkAction + ", " + FieldNamePrefix + " " + FieldNameIndex + " ):\n\n";
	//***/  dbgStr += "\nenableEditFieldSetting\nisMacroRunning = \"" + isMacroRunning + "\"\ntypeof( EditFieldCommand ) = \"" + typeof( EditFieldCommand ) + "\"\nEditFieldCommand:\n" + EditFieldCommand.toString() + "\n\n";

	var  strEditFieldCommand;

	if  ( isMacroRunning  &&  typeof( EditFieldCommand ) == "function" )
		strEditFieldCommand = Function2String( EditFieldCommand );
	else
		strEditFieldCommand = getEditFieldFormat();

	//***/  alert( "enableEditFieldSetting\nisMacroRunning = \"" + isMacroRunning + "\"\ntypeof( EditFieldCommand ) = \"" + typeof( EditFieldCommand ) + "\"\nstrEditFieldCommand:\n" + strEditFieldCommand );
	//***/  dbgStr += "strEditFieldCommand = \"" + strEditFieldCommand + "\"\n\n";

	if  ( strEditFieldCommand != "" )  {

		var  NameField = getElem( FieldNamePrefix + "Name" + FieldIndexDelimiter + FieldNameIndex );
		var  TypeField = getElem( FieldNamePrefix + "Type" + FieldIndexDelimiter + FieldNameIndex );
		var  NTagField = getElem( FieldNamePrefix + "NTag" + FieldIndexDelimiter + FieldNameIndex );
		var  LinkField = getElem( FieldNamePrefix + "Link" + FieldIndexDelimiter + FieldNameIndex );
		var  HRefField = getElem( FieldNamePrefix + "HRef" + FieldIndexDelimiter + FieldNameIndex );
		var  SctyField = getElem( FieldNamePrefix + "Scty" + FieldIndexDelimiter + FieldNameIndex );

		var  NameFieldValue = NameField.value;
		var  TypeFieldValue = getInputListValue( TypeField );
		var  NTagFieldValue = NTagField.value;
		var  LinkFieldValue = LinkField.value;
		var  HRefFieldValue = HRefField.value;
		var  SctyFieldValue = ( SctyField  ?  SctyField.value  :  "" );

		var  TName = getElemValue( "fTName" );
		var  TCode = getElemValue( "fTCode" );
		var  TType = getElemValue( "fTType" );

		var  SName = getElemValue( "fSName" );
		var  SCode = getElemValue( "fSCode" );
		var  SNTag = getElemValue( "fSNTag" );
		var  SType = getElemValue( "fSType" );

		var  GName = getElemValue( "fGName" );
		var  GCode = getElemValue( "fGCode" );
		var  GNTag = getElemValue( "fGNTag" );
		var  GType = getElemValue( "fGType" );

		var  IName = getElemValue( "fIName" );
		var  ICode = getElemValue( "fICode" );
		var  INTag = getElemValue( "fINTag" );

		var  arrNames = LinkNames.split( "|" );
		var  arrCodes = LinkCodes.split( "|" );
		var  arrNTags = LinkNTags.split( "|" );

		var  TLName = SLName = GLName = ILName = "";
		var  TLCode = SLCode = GLCode = ILCode = "";
		var  TLNTag = SLNTag = GLNTag = ILNTag = "";

		switch  ( arrNames.length )  {
			case  4:
			ILName = arrNames[ 3 ];
			ILCode = arrCodes[ 3 ];
			ILNTag = arrNTags[ 3 ];
			case  3:
			GLName = arrNames[ 2 ];
			GLCode = arrCodes[ 2 ];
			GLNTag = arrNTags[ 2 ];
			case  2:
			SLName = arrNames[ 1 ];
			SLCode = arrCodes[ 1 ];
			SLNTag = arrNTags[ 1 ];
			case  1:
			TLName = arrNames[ 0 ];
			TLCode = arrCodes[ 0 ];
			TLNTag = arrNTags[ 0 ];
		}

		var  Link, Load, Move, HyperLink = false;

		switch  ( LinkAction )  {
			case  "Link":
				Link = true;
				break;
			case  "Load":
				Load = true;
				break;
			case  "Move":
				Move = true;
				break;
			case  "Topic":
			case  "Section":
			case  "Group":
			case  "Item":
				HyperLink = true;
				break;
		}

		var  TopicsURL    = "/topics.php?Topic=";
		var  ProductsURL  = "/products.php?Topic=";
		var  ChangedColor = "aqua";

		var  Name, Type, NTag, HRef, Scty;

		//***/  alert( "Before eval:\n" + strEditFieldCommand );
		eval( strEditFieldCommand );

		if  ( typeof( Name ) != "undefined"  &&  Name != null )  {
			if  ( NameField.value != Name )
				NameField.style.backgroundColor = ChangedColor;
			NameField.value = Name;
		}

		if  ( typeof( Type ) != "undefined"  &&  Type != null )  {
			if  ( TypeFieldValue != Type )
				TypeField.style.backgroundColor = ChangedColor;
			selectInputListValue( TypeField, Type );
		}

		if  ( typeof( NTag ) != "undefined"  &&  NTag != null )  {
			if  ( NTagField.value != NTag )
				NTagField.style.backgroundColor = ChangedColor;
			NTagField.value = NTag;
		}

		if  ( typeof( HRef ) != "undefined"  &&  HRef != null )  {
			if  ( HRefField.value != HRef )
				HRefField.style.backgroundColor = ChangedColor;
			HRefField.value = HRef;
		}

		if  ( typeof( Scty ) != "undefined"  &&  Scty != null )  {
			if  ( SctyField.value != Scty )
				SctyField.style.backgroundColor = ChangedColor;
			SctyField.value = Scty;
		}
		EnforceRequiredFields();
	}
	/***/  dbgStr += "\nEnd of enableEditFieldSetting.\n\n";
	/***/  dbgOut();
}



function  runTopicMacro( strMacro )  {
	isMacroRunning = true;
	//***/  dbgStr += "\nrunTopicMacro BEFORE eval\nisMacroRunning = \"" + isMacroRunning + "\"\ntypeof( EditFieldCommand ) = \"" + typeof( EditFieldCommand ) + "\"\nstrMacro:\n" + strMacro + "\n\n";
	eval( strMacro );
	//***/  alert( "runTopicMacro AFTER eval\nisMacroRunning = \"" + isMacroRunning + "\"\ntypeof( EditFieldCommand ) = \"" + typeof( EditFieldCommand ) + "\"\nstrMacro:\n" + strMacro );
	//***/  dbgStr += "\nrunTopicMacro AFTER eval\nisMacroRunning = \"" + isMacroRunning + "\"\ntypeof( EditFieldCommand ) = \"" + typeof( EditFieldCommand ) + "\"\nstrMacro:\n" + strMacro + "\n\n";
	isMacroRunning = false;
}



function  enableNTagSetting( NTagField, LinkData, LinkPartNo )  {

	if  ( NTagField.value == ""  /*&&  NTagField.onclick == null*/ )  {
		var  arrLinkData = LinkData.split( "|" );
		var  idxNTag = ( typeof( LinkPartNo ) != "undefined"  ?  LinkPartNo  :  arrLinkData.length - 1 );
		var  NTagValue = arrLinkData[ idxNTag ].replace( "-", "" );
		var  strOnClick = "var NTagField = getElem(\"" + NTagField.id + "\"); NTagField.value = \"" + NTagValue + "\"";
		//var  strOnClick = "this.value = \"" + NTagValue + "\"";
		//var  fncOnClick = function() { this.value = NTagValue; };
		addElemEvent( NTagField, "onclick", strOnClick, "Set" )
	}

}



/******************************************************************************
  convertLink2HyperLink
    EAH - December 29, 2008

    Creates a properly formed Topics HyperLink:
			/topics.php?TCode#SNTag-GNTag-INTag

    Usage:
      convertLink2HyperLink( LinkData );

    Where:
      LinkData = a pipe-delimited Link.

******************************************************************************/

function  convertLink2HyperLink( LinkData )  {

	var  HLinkData = "";
	var  arrLink = LinkData.split( "|" );
	switch  ( arrLink.length )  {
		case 4:
			HLinkData = "-" + arrLink[ 3 ];
		case 3:
			HLinkData = "-" + arrLink[ 2 ] + HLinkData;
		case 2:
			HLinkData = "#" + arrLink[ 1 ] + HLinkData;
		case 1:
		default:
			HLinkData = "/topics.php?Topic=" + arrLink[ 0 ] + HLinkData;
			break;
	}

	return  HLinkData;
}



/******************************************************************************
  createTopicLink
    EAH - December 29, 2008

    Creates a properly formed Topics Link:
			TCode|SNTag|GNTag|INTag

    Usage:
      createTopicLink( <TCode> [, <SNTag> [, <GNTag> [, <INTag> ] ] ] );

    Where:
      TCode = The Link TopicCode.
      SNTag, GNTag, and INTag = the optional Section, Group, and Item NTags.

******************************************************************************/

function  createTopicLink( TCode, SCode, GCode, ICode )  {

	var  LinkData = "";
	if  ( typeof( TCode ) != "undefined"  &&  TCode  &&  TCode != "" )  {
		LinkData = TCode;
		if  ( typeof( SCode ) != "undefined"  &&  SCode  &&  SCode!= "" )  {
			LinkData += "|" + SCode;
			if  ( typeof( GCode ) != "undefined"  &&  GCode  &&  GCode!= "" )  {
				LinkData += "|" + GCode;
				if  ( typeof( ICode ) != "undefined"  &&  ICode  &&  ICode!= "" )  {
					LinkData += "|" + ICode;
				}
			}
		}
	}

	return  LinkData;
}



/******************************************************************************
  createTopicHyperLink
    EAH - December 29, 2008

    Creates a properly formed Topics HyperLink:
			/topics.php?TCode#SNTag-GNTag-INTag

    Usage:
      createTopicHyperLink( <TCode> [, <SNTag> [, <GNTag> [, <INTag> ] ] ] );

    Where:
      TCode = The HyperLink TopicCode.
      SNTag, GNTag, and INTag = the optional Section, Group, and Item NTags
      or Codes.

******************************************************************************/

function  createTopicHyperLink( TCode, SCode, GCode, ICode )  {

	return  convertLink2HyperLink( createTopicLink( TCode, SCode, GCode, ICode ) );
}



/******************************************************************************
  extractTopicLinkPart
    EAH - December 29, 2008

    Extracts part of a pipe-delimited Link.

    Usage:
      extractTopicLinkPart( <LinkData>, <PartName> );

    Where:
      LinkData = a pipe-delimited Link.
      PartName = Topic, Section, Group, or Item.

******************************************************************************/

function  extractTopicLinkPart( LinkData, PartName )  {

	var  PartCode = TCode = SCode = GCode = ICode = "";
	var  arrLink = LinkData.split( "|" );
	switch  ( arrLink.length )  {
		case 4:
			ICode = arrLink[ 3 ];
		case 3:
			GCode = arrLink[ 2 ];
		case 2:
			SCode = arrLink[ 1 ];
		case 1:
			TCode = arrLink[ 0 ];
		default:
			break;
	}

		switch  ( PartName )  {
			case  "Topic":
				PartCode = TCode;
				break;
			case  "Section":
				PartCode = SCode;
				break;
			case  "Group":
				PartCode = GCode;
				break;
			case  "Item":
				PartCode = ICode;
				break;
			default:
				break;
		}

	return  PartCode;
}



/******************************************************************************
  processSelectedText
    EAH - May 2, 2009

    Performs a specific operation on the currently selected text.

    Allowed operations are:

    - Title Case  --  Sets the selected text to Title Case.
    - Format References
    - Change Category
    - Edit Categories
    - Swap Relationship
    - Delete Relationship
    - Remove Relationship
    - Variant Terms

******************************************************************************/

function  processSelectedText( Op )  {

	var  OpMessage, Options, SelectedText;

	OpMessage = Options = "";
	SelectedText = getCursorText();

	switch  ( Op )  {

		case  "Format JS String":
			var  FormattedText = SelectedText.replace( /\n|\r\n/g, " " );

			/***  Only reformat the string if it has not already been formatted:  ***/
			if  ( FormattedText.match( /&(?!amp;)/ ) )  {
				FormattedText = FormattedText.replace( /&/g, "&amp;" );
			}

			if  ( FormattedText.match( /'|^"|([^\\]")/ ) )  {
				FormattedText = EscapeQuotesJS( FormattedText );
			}

			insertText( FormattedText, "Select" );
			break;


		case  "Change Category":
			if  ( !OpMessage )
				OpMessage = "Changing Term Category:";
		case  "Edit Categories":
			if  ( !OpMessage )  {
				OpMessage = "Editing Categories:";
				Options = getElemValue( "CurrentCursorField" );
			}
		case  "Swap Relationship":
			if  ( !OpMessage )
				OpMessage = "Swapping Relationship:";
		case  "Delete Relationship":
			if  ( !OpMessage )
				OpMessage = "Deleting Relationship:";
		case  "Remove Relationship":
			if  ( !OpMessage )  {
				OpMessage = "Removing Relationship:";
				Options = getLinkListNTags( "Item" );
			}

			setElemValue( "fResults", OpMessage + "\n" + SelectedText );

			if  ( ErrorIW.IWL.visibility != "hidden" )  {
				ErrorIW.InfoTableStyle( "Status Message", "<b>" + OpMessage + "</b><br/>" + FormatForHTML( SelectedText ) + "<br/>...", 8 );
			}

			xajax_processSelectedText( Op, SelectedText, Options );
			break;


		case  "Format References":
			/***  Always select the entire Link References field:  ***/
			var  fTarget = getElem( "fReferences" );
			if  ( fTarget )  {
				fTarget.select();
				SelectedText = fTarget.value;
			}
		case  "Title Case":
		case  "Variant Terms":
		default:
			xajax_processSelectedText( Op, SelectedText );
			break;
	}
}



/******************************************************************************
  setTextBoxValue
    EAH - October 5, 2007

    Loads or Inserts text into the given TextBox Field.

******************************************************************************/

function  setTextBoxValue( fieldID, LinkAction, ItemText )  {

	var  fldText = getElem( fieldID );

	switch  ( LinkAction )  {
		case  "Load":
		case  "Move":
			fldText.value = ItemText;
			break;
		case  "Insert":
		case  "Include":
		case  "Pointer":
			//insertAtCaret( fldText, ItemText );
			var  fldTextIO = new  CursorIO( fldText );
			fldTextIO.putText( ItemText );
			break;
	}

}



/******************************************************************************
  insertText
    EAH - March 20, 2009

    Inserts text into the ItemText field.

    If the insText is an array, then insert the array as multiple lines.


******************************************************************************/

function  insertText( insText, cmdCursor, sPrefix, sSuffix )  {

	//***/  alert( "insertText: insText.constructor = \"" + insText.constructor.toString() + "\"" );
	//var  TextMode = ( typeof( flgSelect ) == "undefined"  ||  flgSelect != "Select"  ?  "%Text%"  :  "%TextSelect%" );

	var  IFIX = getElemValue( "LinkTargetLine" );

	if  ( IFIX === 0 )
		return;

	var  EditMode = getElemValue( "EditMode" );
	var  fIText = "fIText" + ( IFIX == null  ?  ""  :  FieldIndexDelimiter + IFIX );
	var  fName = "f" + EditMode.substr( 0, 1 ) + "Name" + ( IFIX == null  ?  ""  :  FieldIndexDelimiter + IFIX );

	var  CursorField = getElemValue( "CurrentCursorField" );

	if  ( CursorField != fIText  &&  CursorField != fName  &&
			  CursorField != "fSourceText"  &&  CursorField != "fResults"  &&
				CursorField != "fReferences"  &&  CursorField != "fAssociatedRefs"  &&  CursorField != "fAllReferences"  &&  CursorField != "fTerms"  &&  CursorField != "fWords" )
		CursorField = fIText;

	//var  fTarget = getElem( CursorField );
	//insertAtCaret( fTarget, insText, TextMode )

	sPrefix = getArg( sPrefix );
	sSuffix = getArg( sSuffix );

	var  TargetIO = new  CursorIO( CursorField );

	if  ( isArray( insText ) )  {
		insText = insText.join( "\n" );
	}

	TargetIO.putText( insText, cmdCursor, sPrefix, sSuffix )

}


/******************************************************************************
  insertListText
    EAH - January 4, 2008

    Inserts text from a List field into the ItemText field.


******************************************************************************/

function  insertListText( btnIns, cmdCursor, sPrefix, sSuffix, flgReset )  {

	if  ( getInputListValue( btnIns ) != "0" )  {
		var  insText = getInputListText( btnIns )

		sPrefix   = getArg( sPrefix );
		sSuffix   = getArg( sSuffix );
		cmdCursor = getArg( cmdCursor );
		flgReset  = getArg( flgReset, "Reset" );
		insertText( insText, cmdCursor, sPrefix, sSuffix );
		if  ( flgReset == "Reset" )
			selectInputListValue( btnIns, "0" );
	}
}



/******************************************************************************
  insertStructuredText
    EAH - January 3, 2008

    Inserts HTML formatting tags into the ItemText field.

    The HTMLTypes are:
    - HTML
    - HTMLMultiLine
    - HTMLStructure
    - Text
    - TextMultiple

******************************************************************************/

function  insertStructuredText( btnIns )  {

	var  btnID = btnIns.name;
	var  IFIX = getElemValue( "LinkTargetLine" );

	if  ( IFIX === 0 )
		return;

	var  InsertText, HTMLType, PrefixText, SuffixText;
	InsertText = HTMLType = PrefixText = SuffixText = "";

	var  fTargetName = "fIText" + ( IFIX == null  ?  ""  :  FieldIndexDelimiter + IFIX );
	var  fTarget = getElem( fTargetName );
	var  CursorField = getElemValue( "CurrentCursorField" );

	if  ( typeof( fTarget ) == "undefined"  &&  typeof( CursorField ) != "undefined" )
		fTarget = getElem( CursorField );

	var  TargetIO = new  CursorIO( fTarget );

	//***/  dbgStr += "insertStructuredText btnIns: btnID = " + btnID + ", fTarget = \"" + fTarget.name + "\"\n";
	//***/  alert( "insertStructuredText( " + btnID + " )" );

	switch  ( btnIns.value )  {

		case  "Bold":
			InsertText = "b";
			HTMLType = "HTML";
			insertHTML( TargetIO, InsertText, HTMLType )
			break;

		case  "Italic":
			InsertText = "i";
			HTMLType = "HTML";
			insertHTML( TargetIO, InsertText, HTMLType )
			break;

		case  "P":
			InsertText = "p";
			HTMLType = "HTMLMultiLine";
			insertHTML( TargetIO, InsertText, HTMLType )
			break;

		case  "Span":
			InsertText = "span";
			HTMLType = "HTML";
			insertHTML( TargetIO, InsertText, HTMLType )
			break;

		case  "BlockQuote":
			InsertText = "blockquote";
			/***
			HTMLType = "HTMLStructure";
			insertHTML( TargetIO, InsertText, HTMLType )
			InsertText = "p";
			/***/
			HTMLType = "HTML";
			insertHTML( TargetIO, InsertText, HTMLType )
			break;

		case  "OL":
			InsertText = "ol";
			HTMLType = "HTMLStructure";
			insertHTML( TargetIO, InsertText, HTMLType )
			InsertText = "li";
			HTMLType = "HTMLMultiLine";
			insertHTML( TargetIO, InsertText, HTMLType )
			break;

		case  "UL":
			InsertText = "ul";
			HTMLType = "HTMLStructure";
			insertHTML( TargetIO, InsertText, HTMLType )
			InsertText = "li";
			HTMLType = "HTMLMultiLine";
			insertHTML( TargetIO, InsertText, HTMLType )
			break;

		case  "LI":
			InsertText = "li";
			HTMLType = "HTMLMultiLine";
			insertHTML( TargetIO, InsertText, HTMLType )
			break;

		case  "Table":
			InsertText = "table";
			HTMLType = "HTMLStructure";
			insertHTML( TargetIO, InsertText, HTMLType )
		case  "TR":
			InsertText = "tr";
			HTMLType = "HTMLStructure";
			insertHTML( TargetIO, InsertText, HTMLType )
		case  "TD":
			InsertText = "td";
			HTMLType = "HTMLMultiLine";
			insertHTML( TargetIO, InsertText, HTMLType )
			break;

		case  "BR":
			InsertText = "<br/>\n";
			TargetIO.putText( InsertText );
			break;

		case  "SplitP":
			InsertText = "</p>\n\n<p>";
			TargetIO.putText( InsertText );
			break;

		case  "Quotes":
			InsertText = "\"";
			TargetIO.putText( TargetIO.getText(), "", InsertText, InsertText );
			break;

		case  "PubMed URL":
			InsertText = TargetIO.getText();
			PrefixText = "<a href=\"" + PubMedURL + InsertText + "\">";
			SuffixText = "</a>";
			TargetIO.putText( InsertText, "Select", PrefixText, SuffixText );
			break;


		case  "PubMed":
		case  "Load PubMed Item":
		case  "Add PubMed Item":
			var  fClipText = getElem( "fClipText" );
			var  ClipText = trimStr( fClipText.value );

			if  ( btnID == "fBtnFmtPubMed" )  {     //***  Admin Topics
				var  EditMode = getElemValue( "EditMode" );
				var  IFIX = getElemValue( "LinkTargetLine" );
				var  fIText = "fIText" + FieldIndexDelimiter + IFIX;
				var  fHRef = "f" + EditMode.substr( 0, 1 ) + "HRef" + FieldIndexDelimiter + IFIX;
				var  fName = "f" + EditMode.substr( 0, 1 ) + "Name" + FieldIndexDelimiter + IFIX;
				var  fNTag = "f" + EditMode.substr( 0, 1 ) + "NTag" + FieldIndexDelimiter + IFIX;
				var  elemName = getElem( fName );
				var  elemNTag = getElem( fNTag );
				var  curName = elemName.value;
				var  curNTag = elemNTag.value;

				if  ( !ClipText  &&  ( CursorField == fIText ) )  {
					ClipText = fClipText.value = chkPubMedItemNo( fIText );
				}
			}

			if  ( btnID == "fBtnViewPubMed"  ||  btnID == "fBtnLoadPubMed"  ||  btnID == "fBtnAddPubMed" )  {       //***  Admin References
				var  NewUnwanted = getElemValue( "NewUnwanted" );
			}

			if  ( !ClipText )  {
				var  rClipText, sClipText;

				if  ( fClipText.createTextRange )
					rClipText = fClipText.createTextRange();
				else if  ( document.createRange )  {
					fClipText.focus();
					fClipText.select();
					sClipText = window.getSelection();
					rClipText = sClipText.getRangeAt(0);
				}

				if  ( rClipText )  {
					try  {
						rClipText.execCommand( "Paste" );
						ClipText = fClipText.value = trimStr( fClipText.value );
					}
					catch( e )  {};
				}
			}

			if  ( ClipText )  {
				if  ( btnID == "fBtnFmtPubMed" )        //***  Admin Topics
					xajax_formatPubMedItem( ClipText, IFIX, CursorField );
				if  ( btnID == "fBtnViewPubMed" )  {    //***  Admin References
					setElemValue( "fResults", "Requesting: Retrieve Abstract #" + ClipText + " from PubMed..." );
					xajax_getPubMedTerms( "View", ClipText, NewUnwanted );
					setElemValue( "fResults", "Retrieving Abstract #" + ClipText + " from PubMed..." );
				}
				if  ( btnID == "fBtnLoadPubMed" )  {     //***  Admin References
					setElemValue( "fResults", "Requesting: Load PubMed Abstract #" + ClipText + "..." );
					xajax_getPubMedTerms( "Load", ClipText, NewUnwanted );
					setElemValue( "fResults", "Loading PubMed Abstract #" + ClipText + "..." );
				}
				if  ( btnID == "fBtnAddPubMed" )  {     //***  Admin References
					setElemValue( "fResults", "Requesting: Add New PubMed Abstract #" + ClipText + "..." );
					xajax_getPubMedTerms( "Add", ClipText, NewUnwanted );
					setElemValue( "fResults", "Adding New PubMed Abstract #" + ClipText + "..." );
				}
			}
			break;


		case  "InfoWindow":
			InsertText = "Message Pointer";

			PrefixText = "\n<span class=\"InfoLink\" onmouseover='InfoTableStyle(\n" +
			             "\"Reference\",\n\"<?= quotePointerText( \"";

			SuffixText = "\" ); ?>\",\n5 );'\nonmouseout='hide();'>\n</span>";

			TargetIO.putText( InsertText, "Select", PrefixText, SuffixText );
			break;


		case  "Citation":
			/***  Make the ItemLink a Pointer so that it can be updated by admin_topics:  ***/
			var  PrefixText  = "<?= Citation( \"" + LINK_POINTER_BEGIN;
			var  strLinkList = getLinkListValue( "Item" );
			var  SuffixText  = LINK_POINTER_END + "\" ); ?>";

			TargetIO.putText( strLinkList, "Select", PrefixText, SuffixText );
			break;


		default:
			return;
			break;

	}

	/***/  dbgOut( dbgStr);

}



function  insertHTML( TargetIO, sHTML, sType )  {

	var  saveText = TargetIO.getText();
	var  HTMLTagBegin = HTMLTagEnd = "";

	if  ( sType == "HTML"  ||  sType == "HTMLMultiLine" )  {
		HTMLTagOpen = "<" + sHTML + ">";
		HTMLTagClose = "</" + sHTML + ">";
		if  ( sType == "HTMLMultiLine" )  {
			var  emptyTag = new RegExp( HTMLTagOpen + HTMLTagClose, "g" );
			saveText = saveText.replace( /\r\n|\n/g, HTMLTagClose + "\n" + HTMLTagOpen ).replace( emptyTag, "" );
		}
	}
	if  ( sType == "HTMLStructure" )  {
		HTMLTagOpen = "<" + sHTML + ">\n  ";
		HTMLTagClose = "\n</" + sHTML + ">";
	}

	TargetIO.putText( saveText, "Select", HTMLTagOpen, HTMLTagClose );
}



/******************************************************************************
  getCursorText
    EAH - April 3, 2009

    Copies or Extracts text from the current cursor position.

    Optional parameters:
    - GetMode
      . Copy (default if no Replacement Text)
      . Cut  (default if Replacement Text is given)
    - ReplacementText


******************************************************************************/

function  getCursorText( GetMode, ReplacementText )  {

	var  repText = getArg( ReplacementText );
	var  getMode = getArg( GetMode, ( repText  ?  "Cut"  :  "Copy" ) );

	var  TargetIO = new  CursorIO( getElemValue( "CurrentCursorField" ) );

	if  ( TargetIO )  {

		switch  ( getMode )  {

			case  "Cut":
				return  TargetIO.putText( ReplacementText );
				break;

			case  "Copy":
				default:
				return  TargetIO.getText();
				break;
		}

	}

	return  "";
}



/******************************************************************************
  chkPubMedItemNo
    EAH - August 12, 2008

    Checks for an imbedded PubMed ID Number in a Topic Item text field.


******************************************************************************/

function  chkPubMedItemNo( FieldName )  {

	var  PubMedIDN;
	var  strItemText = getElemValue( FieldName );
	var  regexpIDN  = /http:\/\/www\.ncbi\.nlm\.nih\.gov\/pubmed\/([\d]*)/;
	var  arrMatchIDN = regexpIDN.exec( strItemText );

	if  ( arrMatchIDN )  {
		//***/  alert( "chkPubMedItemNo match: \"" + arrMatchIDN[ 1 ] + "\"" );
		PubMedIDN = arrMatchIDN[ 1 ];
	}
	else  {
		//***/  alert( "chkPubMedItemNo No Match: \"" + strItemText + "\"" );
		PubMedIDN = "";
	}

	return  PubMedIDN;
}



/******************************************************************************
  insertSecurityText
    EAH - March 16, 2010

    Sets the given Link or HyperLink Field to the Topics Link List selection.

******************************************************************************/

function  insertSecurityText( btnElem )  {

	var  insText;
	var  btnID     = btnElem.name;
	var  btnAction = ( btnID == "fRecentSecurity"  ?  "Recent"  :  btnElem.value.Trim() );
	var  EditMode  = getElemValue( "EditMode" );

	//***/  dbgStr += "insertSecurityText( " + btnID + " ):\n\n";

	//***/  alert( "insertSecurityText( " + btnID + " );" );

	var  SctyFieldName, LFIX, TargetIO, insText;

	switch  ( EditMode )  {

		case  "Topic":
			SctyFieldName = "fTScty";
			break;

		case  "Section":
			LFIX = getElemValue( "LinkTargetLine" );
			if  ( LFIX == 0 )  {
				if  ( ( TargetIO = new  CursorIO( getElemValue( "CurrentCursorField" ) ) )  &&  ( SctyFieldName = TargetIO.objTextBox.attributes.name.value ) )  {
					//***/  alert( "SctyFieldName = " + SctyFieldName );  //alert( "TargetIO.objTextBox = " + describeDOMObj( TargetIO.objTextBox ) );
				}
				else  {
					return;
				}
			}
			else  {
				SctyFieldName = "fSScty" + FieldIndexDelimiter + LFIX;
			}
			break;

		default:
			return;
			break;
	}

	//***/  alert( "insertSecurityText: Current value of " + SctyFieldName + " = \"" + getElemValue( SctyFieldName ) + "\"" );

	TargetIO = new  CursorIO( SctyFieldName );

	switch  ( btnAction )  {

		case  "Recent":
			insText = getInputListText( btnID, "" );
			break;

		case  "Set":
			var  SecType, SecInvert, Invert, arrSecValues, SecValues;

			SecType   = getInputListValue( "fSecType", "" );
		  SecInvert = getRadioButtonValue( "fSecInvert[]", "" );

			if  ( SecInvert )
				Invert = "!";
			else
				Invert = "";
		  arrSecValues = getInputListValue( "fSecValues[]" );
			SecValues = arrSecValues.join( ", " );

			if  ( !SecValues )
				return;

			insText = SecType + ": " + Invert + SecValues + "; ";
			//InfoTableStyle( "fLinkMode[]", FormatForHTML( describeDOMObj( getElem( "fLinkMode[]" ) ) ), 3 )
			break;

		case  "&":
		case  "&amp;":
			insText = " & ";
			break;

		case  "|":
			insText = " | ";
			break;

		default:
			insText = "";
			break;
	}

	//***/  alert( "insertSecurityText: btnAction = \"" + btnAction + "\", insText = \"" + insText + "\"" );

	//***/  dbgStr += "btnAction = \"" + btnAction + "\", insText = \"" + insText + "\"\n";

	if  ( btnAction == "Recent" )
		setElemValue( SctyFieldName, insText );
	else
		TargetIO.putText( insText );

	if  ( btnAction == "Set"  ||  btnAction == "Recent" )
		xajax_addRecentSecurity( getElemValue( SctyFieldName ) );

	//***/  alert( getElemValue( SctyFieldName ) );

	//***/  dbgOut();
}



/******************************************************************************
  insertTopicLink
    EAH - November 19, 2007

    Inserts a hyperlink to a Topic in the HRef field, or in the TopicItem
    ItemText field when in the ItemText mode.
    The hyperlink can also reference NTagged Sections, Groups, and Items.
    The hidden LinkTargetLine contains the index of the field in which the
    hyperlink will be inserted.
    The hidden CurrentCursorField contains the ID of the field in which the
    hyperlink will be inserted in the Item mode.


******************************************************************************/

function  insertTopicLink( btnIns )  {

	/***/  dbgOut( "\ninsertTopicLink" );

	var  HRefMode = href = ClipText = InsertValue = InsertText = InsertName = InsertURL = AHRef = HTag = AName = "";

	var  btnID = btnIns.name;
	var  EditMode = getElemValue( "EditMode" );
	var  ScreenState = getElemValue( "ScreenState" );
	var  CursorField = getElemValue( "CurrentCursorField" );
	var  IFIX = getElemValue( "LinkTargetLine" );
	var  IFID = "f" + EditMode.substr( 0, 1 );
	var  fHRef = IFID + "HRef" + FieldIndexDelimiter + IFIX;
	var  fName = IFID + "Name" + FieldIndexDelimiter + IFIX;
	var  fNTag = IFID + "NTag" + FieldIndexDelimiter + IFIX;
	var  fIText = "fIText" + FieldIndexDelimiter + IFIX;
	var  elemName = getElem( fName );
	var  elemNTag = getElem( fNTag );
	var  curName = elemName.value;
	var  curNTag = elemNTag.value;
	var  HName = HNTag = "";

	if  ( IFIX == 0 )
		return;

	if  ( CursorField == fIText )  {
		HRefMode = "IText";
	}
	else  {
		HRefMode = "HRef";
		CursorField = fHRef;
	}

	/***/  dbgOut( "btnIns: btnID = " + btnID + ", CursorField = " + CursorField + "\n" );

	var  fTarget = getElem( CursorField );
	var  TargetIO = new  CursorIO( fTarget );

	switch  ( btnIns.value )  {

		case  "Item":
			var  fILinks = getElem( "fILinks" );
		  var  INTag = fILinks.value;
		  var  IName = extractLinkListName( getInputListText( fILinks, INTag ) );
		  HTag = ( INTag  ?  "-" + INTag  :  "" );
		  AName = ( IName  ?  " " + IName  :  "" );
		case  "Group":
			var  fGLinks = getElem( "fGLinks" );
		  var  GNTag = fGLinks.value;
		  var  GName = extractLinkListName( getInputListText( fGLinks, GNTag ) );
		  HTag = ( GNTag  ?  "-" + GNTag + HTag  :  "" );
		  AName = ( GName  ?  " " + GName + AName  :  AName );
		  HNTag = GNTag;
		case  "Section":
			var  fSLinks = getElem( "fSLinks" );
		  var  SNTag = fSLinks.value;
		  var  SName = extractLinkListName( getInputListText( fSLinks, SNTag ) );
		  HTag = ( SNTag  ?  "#" + SNTag + HTag  :  "" );
		  AName = ( SName  ?  " " + SName + AName  :  AName );
		  HNTag = SNTag;
		case  "Topic":
			var  fTLinks = getElem( "fTLinks" );
		  var  TCode = fTLinks.value;
		  var  TName = getInputListText( fTLinks, TCode );
		  AName = TName + AName;
		  HNTag = TCode;
		  AHRef = "/topics.php?Topic=" + TCode + HTag;
			InsertURL = AHRef;
			InsertName = AName;
			break;

		case  "Clipboard":
			if  ( ( fClipText = getElem( "fClipText" ) ) )
				ClipText = fClipText.value;
			InsertName = InsertURL =  ( ClipText  ?  ClipText  :  "%Clipboard%" );
			break;

		default:
			return;
			break;

	}

	switch  ( HRefMode )  {

		case  "HRef":
			fTarget.value = "";
			//insertAtCaret( fTarget, InsertURL );
			TargetIO.putText( InsertURL );

			switch  ( btnIns.value )  {

				case  "Topic":
				  HName = TName;
					break;

				case  "Section":
				  HName = SName;
					break;

				case  "Group":
				  HName = GName;
					break;

				case  "Item":
				  HName = IName;
					break;
			}

			var  newName, newNTag;

			if  ( ScreenState == "Enter"  &&  btnIns.value == "Topic" )  {
				newName = HName;
				newNTag = HNTag;
			}
			else  {
				newName = ( curName  ?  curName  :  HName );
				newNTag = ( curNTag  ?  curNTag  :  HNTag );
			}
			if  ( newName != curName )
				elemName.value = newName;
			if  ( newNTag != curNTag )
				elemNTag.value = newNTag;

			/*** /  dbgOut( "HName = \"" + HName + "\", HNTag = \"" + HNTag + "\"\n" +
										 "curName = \"" + curName + "\", curNTag = \"" + curNTag + "\"\n" +
										 "newName = \"" + newName + "\", newNTag = \"" + newNTag + "\"\n"
										);  /***/

			break;

		case  "IText":
			insertATag( TargetIO, InsertURL, InsertName )
			break;
	}

	if  ( btnIns.value != "Clipboard" )  {
		var  strLinkList = getLinkListValue( btnIns.value );
		var  strLinkText = getLinkListText ( btnIns.value );
		var  strLinkNames = getLinkListNames( EditMode );
	  var  strLinkCodes = getLinkListCodes( EditMode );
	  var  strLinkNTags = getLinkListNTags( EditMode );
	  var  TTypes = getInputListValue( "fTTypes[]" );
	  var  LinkMode = getTopicLinkMode();
		enableEditFieldSetting( EditMode, btnIns.value, IFID, IFIX, strLinkNames, strLinkCodes, strLinkNTags );
	  xajax_saveLinkData( LinkMode, strLinkList, TTypes, strLinkText );
		if  ( HRefMode == "HRef"  &&  btnIns.value == "Topic" )  {
		  addRecentTopic( TCode, TName );
			if  ( EditMode == "Group" )  {
				var  GroupTType  = getElemValue( "fTType" );
				var  GroupTTypes = TTypes;
				var  addGroupTType = true;
				for  ( var idx = 0;  idx < GroupTTypes.length;  idx++ )  {
					if  ( GroupTTypes[idx] == "All"  ||  GroupTTypes[idx] == GroupTType )
						addGroupTType = false;
				}
				if  ( addGroupTType )
					GroupTTypes[idx] = GroupTType;
				var  arrGroupLinkList = createCurDataLinkList( EditMode, LinkMode );
				var  strGroupLinkValue = arrGroupLinkList[ 0 ];
				var  strGroupLinkTitle = arrGroupLinkList[ 1 ];
				xajax_saveLinkData( "Link", strGroupLinkValue, GroupTTypes, strGroupLinkTitle );
			}
		}
	}

}



function  insertATag( Target, URL, HyperText ) {

	var  aTagBegin = "<a href=\"";
	var  aTagEnd   = "\">";
	var  aTagClose = "</a>";

	//***/  alert( "typeof( Target ) = \"" + typeof( Target ) + "\"" );

	var  TargetIO = Target;
	TargetIO.putText( URL, "After", aTagBegin );
	TargetIO.putText( HyperText, "Select", aTagEnd, aTagClose );
}



function  addRecentTopic( TCode, TName ) {
	addInputListOption( "fRecentTopicsLink", 1, TName, TCode );
	chkRecentTopicsLink();
  xajax_addRecentTopic( TCode, TName );
}



function  chkRecentTopicsLink() {
	var  expIn    = "";
	var  expNotIn = "if  ( idxChk != 0 )  { chkOption.style.color = \"gray\"; };";
	compareInputLists( "fRecentTopicsLink", "fTLinks", expIn, expNotIn );
}





/******************************************************************************

  Field Format List Editing Functions:
    EAH - November 17, 2008

******************************************************************************/

function  getEditFieldFormat()  {

	var  elemFieldFormatList = getElem( "fFieldFormatList" );

	if  ( getInputListValue( elemFieldFormatList ) == "0" )
		return  "";
	else
		return  getInputListText( elemFieldFormatList );
}


function  chkFFmtEditMode( evt )  {

	var  FFmtEvent           = evt  ||  window.event;
	var  btnEditFFmt         = getElem( "fbtnEditFFmt" );
	var  FFmtEditMode        = btnEditFFmt.value;
	var  elemFieldFormatList = getElem( "fFieldFormatList" );

	if  ( getInputListValue( elemFieldFormatList ) == "0"  &&  FFmtEditMode == "Update" )
		btnEditFFmt.value = btnEditFFmt.innerHTML = "Add";

}


function  editFieldFormatList( evt )  {

	var  FFmtEvent           = evt  ||  window.event;
	var  btnEditFFmt         = getElem( "fbtnEditFFmt" );
	var  FFmtEditMode        = btnEditFFmt.value;
	var  elemFieldFormatList = getElem( "fFieldFormatList" );
	var  curEntry            = getInputListValue( elemFieldFormatList );
	var  fClipText           = getElem( "fClipText" );
	var  ClipText            = fClipText.value;

	switch  ( FFmtEditMode )  {

		case  "Edit":
			FFmtUpdateMode = ( getInputListValue( elemFieldFormatList ) == "0"  ?  "Add"  :  "Update" );
			btnEditFFmt.value = btnEditFFmt.innerHTML = FFmtUpdateMode;
			fClipText.value = getInputListText( elemFieldFormatList );
			break;

		case  "Add":
			curEntry = 0;

		case  "Update":
			btnEditFFmt.value = btnEditFFmt.innerHTML = "Edit";
			if  ( !FFmtEvent.ctrlKey )  {
				updateFFmtList( curEntry, ClipText );
			}
			break;
	}
}


/******************************************************************************

  updateFFmtList
    EAH - November 17, 2008

    Updates the Field Format Definitions List after editing.

    The curValue parameter specifies the array key number of the entry to be
    edited.

    The newText parameter specifies the new value of the entry.

    If the curValue is "0", then a new entry is created at array key "1" and
    the rest of the entries are moved down the list.

    If newText is "", the current entry is deleted.

******************************************************************************/

function  updateFFmtList( curValue, newText )  {

	//***/  dbgOut( "updateFFmtList( " + curValue + ", \"" + newText + "\" )" );

	var  elemFieldFormatList = getElem( "fFieldFormatList" );

	var  newFFmtEditList = new Array();
	var  arrFFmtEditList = getInputList( elemFieldFormatList );
	var  lenFFmtEditList = arrFFmtEditList.length;
	var  newOffset = 1;

	//***/  dbgOut( "arrFFmtEditList[ curValue ].text = \"" + arrFFmtEditList[ curValue ].text + "\"" );

	/***  Retain the special first line prompt:  ***/
	newFFmtEditList[ 0 ] = arrFFmtEditList[ 0 ].text;

	/***  Move the newly edited item to the top of the list:  ***/
	if  ( newText != ""  &&  newText != arrFFmtEditList[ 0 ].text )  {
		newFFmtEditList[ 1 ] = newText;
	}

	/***  Remove the newly edited item from its previous position in the list:  ***/
	arrFFmtEditList[ curValue ].text = "";

	/***  Append all valid items from the original list to the new list:  ***/
	for  ( var  idx = 1;  idx < lenFFmtEditList;  idx++ )  {
		if  ( arrFFmtEditList[ idx ].text == "" )  {
			newOffset--;
		}
		else  {
			newFFmtEditList[ idx + newOffset ] = arrFFmtEditList[ idx ].text;
		}
	}

	loadInputListValues( "fFieldFormatList", newFFmtEditList, 1 );
	xajax_saveFieldFormatList( newFFmtEditList );
}




/******************************************************************************

  chkGroupNamesUpdate

******************************************************************************/

function  chkGroupNamesUpdate( fTName, fCheckboxName, Ch )  {

	var  oldTName  = getElem( "oldTName" );
	var  fCheckbox = getElem( fCheckboxName );
	var  pCheckboxStyle = fCheckbox.parentNode.style;

	if  ( fTName.value != oldTName.value  &&  pCheckboxStyle.visibility != "visible" )  {
		pCheckboxStyle.visibility = "visible";
		pCheckboxStyle.color = "white";
		pCheckboxStyle.backgroundColor = "red";
		//setRadioButton( fCheckboxName, "Update" );
	}
}



/******************************************************************************

  Global JavaScript Ajax Topic List Queue Variables and Functions:

******************************************************************************/


var  AjaxTLHide       = true;
var  curUserTopicCode = "";
var  curDispTopicCode = "";
var  elemTopicIndex, elemTopicLinks;

var  qTLMultiLevel    = false;
var  qTLRepeatReq     = false;

var  TLAjaxQueue = new  AjaxQueue( qAjaxShowTopicList, WriteTopicList, qTLMultiLevel, qTLRepeatReq );


/***  ShowTopicList Request Handler:  ***/

function  ajaxShowTopicList( dispTopicCode, dispTopicType, Visibility, curUserTCode )  {

	elemTopicIndex = getElem( "topic_index" );
	elemTopicLinks = getElem( "topic_links" );

	if  ( curDispTopicCode == dispTopicCode )  {
		//***/  alert( "curDispTopicCode = \"" + curDispTopicCode + "\"" );
		curDispTopicCode = "";
		Visibility = "hidden";
		//ajaxHideTopicList( dispTopicCode, dispTopicType );
	}
	else  {
		curUserTopicCode = curUserTCode;
		curDispTopicCode = dispTopicCode;
	}

	TLAjaxQueue.handleRequest( Array( dispTopicCode, dispTopicType, Visibility ) );
}


function  qAjaxShowTopicList( arrShowTLReq )  {

	dispTopicCode = arrShowTLReq[ 0 ];
	dispTopicType = arrShowTLReq[ 1 ];
	Visibility    = arrShowTLReq[ 2 ];

	AjaxTLHide = false;

	xajax_showTopicList( dispTopicCode, dispTopicType, Visibility, curUserTopicCode );
}


/***  ShowTopicList Response Handler:  ***/

function ajaxWriteTopicList( strTopicIndex, strTopicList )  {

	if  ( AjaxTLHide )  {
		elemTopicLinks.style.display = "none";

		/***  Enable new Queue requests:  ***/
		TLAjaxQueue.QueueBusy = false;
	}
	else  {
		TLAjaxQueue.handleResponse( Array( strTopicIndex, strTopicList ) );
	}
}


/***  ShowTopicList Queue JavaScript Function:  ***/

function WriteTopicList( arrWriteIWData )  {

	strTopicIndex = arrWriteIWData[ 0 ];
	strTopicList  = arrWriteIWData[ 1 ];

	elemTopicIndex.innerHTML = strTopicIndex;
	if  ( strTopicIndex )  {
		elemTopicLinks.style.display = ( FFox  ?  null  :  "block" );
		elemTopicLinks.innerHTML = strTopicList;
	}
	else  {
		elemTopicLinks.style.display = "none";
		AjaxTLHide = true;
	}
}


function ajaxHideTopicList( dispTopicCode, dispTopicType )  {

	xajax_showTopicIndex( dispTopicCode, dispTopicType, curUserTopicCode );
	try  {
		elemTopicLinks.style.display = "none";
	}
	catch( e ) {};
	AjaxTLHide = true;
}



/******************************************************************************

  MenuAction
    EAH - February 19, 2010

    Ajax Menu Action Handler:

******************************************************************************/

function  MenuAction( ActiveButton, MenuName, Menu, Action )  {

	/***  Update selected button class:  ***/
	var  divButton = getElem( ActiveButton );
	var  divButtonList = divButton.parentNode;
	var  classActiveButton = divButton.className;

	if  ( !str_is_right( classActiveButton, "-selected" ) )  {
		var  classNormal = classActiveButton;
		var  classSelected = classNormal + "-selected";
		for  ( var idx = 0;  idx < divButtonList.childNodes.length;  idx++ )  {
			var  curButton = divButtonList.childNodes[ idx ];
			if  ( typeof( curButton.className ) == "string"  &&  curButton.className == classSelected )
				divButtonList.childNodes[ idx ].className = classNormal;
		}
		divButton.className = classSelected;
	}

	/***  Execute the selected Menu Action:  ***/
	xajax_executeMenuAction( MenuName, Menu, Action );
}




//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  Unused Functions to be deleted:  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!





function  xinsertAtCaret( obj, text, URL ) {

	/***  From: Parentnode.org - Working with the Cursor Position             ***/
	/***  http://parentnode.org/javascript/working-with-the-cursor-position/  ***/
	/***  Modified by Ed Hohmann  -  Nov 29, 2007                             ***/
	/***  - Added logic to format and insert URLs.                            ***/
	/***  - Added logic to load from the Clipboard.                           ***/
	/***
				Info on FireFox and Opera at:
				http://weblogs.asp.net/skillet/archive/2005/03/24/395838.aspx

				Info at:
				http://blog.vishalon.net/Post/57.aspx
	***/

	if  ( typeof( obj ) == "undefined"  ||  !obj )
		return  "";


	/***  Convert LF to CRLF in replacement text:  ***/
	text = ConvertLF2CRLF( text );


	var  RangeText;
	var  aTagBegin = "<a href=\"";
	var  aTagEnd   = "\">";
	var  aTagClose = "</a>";
	var  HTMLTagBegin = HTMLTagEnd = "";
	if  ( typeof( URL ) != "undefined" )  {
		if  ( URL == "%HTML%"  ||  URL == "%HTMLMultiple%" )  {
			HTMLTagOpen = "<" + text + ">";
			HTMLTagClose = "</" + text + ">";
			var  emptyTag = new RegExp( HTMLTagOpen + HTMLTagClose, "g" );
		}
		if  ( URL == "%HTMLStructure%" )  {
			//HTMLTagOpen = "\r\n<" + text + ">\r\n  ";
			//HTMLTagClose = "\r\n</" + text + ">\r\n";
			HTMLTagOpen = "<" + text + ">\r\n  ";
			HTMLTagClose = "\r\n</" + text + ">";
		}
		if  ( URL == "%TextMultiple%" )  {
			if  ( typeof( text ) == "object" )  {
				HTMLTagOpen = text[0];
				HTMLTagClose = text[1];
				text = new String( text[1] );
			}
			else  {
				HTMLTagOpen = text;
				HTMLTagClose = text;
			}
		}
	}


	if  ( document.selection ) {
		/***  IE and Opera use the document selection range to manipulate text within elements:  ***/

		/*** Focus the object before retrieving the selection:  ***/
		obj.focus();

		var range = document.selection.createRange();

		/*** Verify that the selected range is in desired object.  ***/
		if  ( range.parentElement() != obj )  {
		    return  "";
		}

		/***  IE workaround to include cr-lf in returned text:  ***/
		if ( MSIE )  {
			/*
			 Internet Explorer does not return trailing CRLF characters within the selection
			 area. However, it does replace them when range.text is set to a new value.
			 If only blank lines (only CRLF) are selected, the end point will equal the start point, and
			 the returned range.text will be empty.
			 Therefore, a non-CRLF delimiter character must be temporarily appended to the selection so
			 that the range.text function will return the trailing CRLF characters of the
			 actual selection.
			 The appended delimiter must be removed before passing the text back to the
			 calling function.
			*/

// Working Code:
if  ( true )  {
			/***  Insert a trailing delimiter after the selection:  ***/
			var  range2 = range.duplicate();
			range2.collapse( false );
			range2.text = " ";

			/***  Retrieve the extended selection:  ***/
			range2.setEndPoint( 'StartToStart', range );
			var  ExtendedText = range2.text;

			/***  Retrieve the actual selection:  ***/
			RangeText = ExtendedText.substr( 0, ExtendedText.length - 1 );

			/***  Remove the trailing delimiter:  ***/
			range2.collapse( false );
			range2.moveStart( "character", -1 );
			range2.text = "";
}


// Test Code:
if  ( false )  {

			/***  Save the selection:  ***/
			//var  BookMark = range.getBookmark();
			//range.select();
			//BookMark = range.getBookmark();

			/***  Insert a trailing delimiter after the selection:  ***/
			var  range2 = range.duplicate();
			/***/  alert( "Check range2 = range.duplicate" );
			range2.collapse( false );
			/***/  alert( "Check range2.collapse" );
			range2.text = "*";
			/***/  alert( "Check range2.text = delimiter" );

			/***  Retrieve the extended selection:  ***/
			range2.setEndPoint( 'StartToStart', range );
			/***/  alert( "Check range2.setEndPoint( 'StartToStart', range )" );
			//range2 = range.duplicate();
			//***/  alert( "Check range2 = range.duplicate" );
			//range2.moveEnd( "character", 1 );
			//***/  alert( "Check range.moveEnd( character, 1 )" );
			var  ExtendedText = range2.text;

			/***  Retrieve the actual selection:  ***/
			RangeText = ExtendedText.substr( 0, ExtendedText.length - 1 );

			/***  Remove the trailing delimiter:  ***/
			range2.collapse( false );
			/***/  alert( "Check range2.collapse" );
			range2.moveStart( "character", -1 );
			/***/  alert( "Check range.moveStart( character, -1 )" );
			range2.text = "";
			/***/  alert( "Check range2.text = \"\"" );
			//range.moveToBookmark( BookMark );
			//***/  alert( "Check range.moveToBookmark" );
			//range2.setEndPoint( 'StartToStart', range );
			//***/  alert( "Check range2.setEndPoint( 'StartToStart', range )" );
			//range = range2.duplicate();
			//***/  alert( "Check range = range2.duplicate" );
			//range.select();
			//***/  alert( "Check range.select" );
}


// Working Test Code with alerts:
if  ( false )  {
			/***  Insert a trailing delimiter after the selection:  ***/
			var  range2 = range.duplicate();
			/***/  alert( "Check range2 = range.duplicate" );
			range2.collapse( false );
			/***/  alert( "Check range2.collapse" );
			range2.text = "*";
			/***/  alert( "Check range2.text = delimiter" );

			/***  Retrieve the extended selection:  ***/
			range2.setEndPoint( 'StartToStart', range );
			/***/  alert( "Check range2.setEndPoint" );
			var  ExtendedText = range2.text;

			/***  Retrieve the actual selection:  ***/
			RangeText = ExtendedText.substr( 0, ExtendedText.length - 1 );

	if ( true )  {
			/***  Remove the trailing delimiter:  ***/
			range2.collapse( false );
			/***/  alert( "Check range2.collapse" );
			range2.moveStart( "character", -1 );
			/***/  alert( "Check range.moveStart( character, -1 )" );
			range2.text = "";
	}
	else  {
			/***  Restore the original selection:  ***/
			range2.text = RangeText;
			/***/  alert( "Check range2.text = RangeText" );
			range2.setEndPoint( 'StartToStart', range );
			/***/  alert( "Check range2.setEndPoint( 'StartToStart', range )" );
			range = range2.duplicate();
			/***/  alert( "Check range = range2.duplicate" );
			range.select();
			/***/  alert( "Check range.select" );
	}
}


////////////////////////////////////////////////////////////////////////////////////
/***  DELETE ALL OF THE FOLLOWING TEST CODE  ***/
/***  This test code is for determining obj.selectionStart and selectionEnd in IE and Opera:  ***/
if  ( false )  {


				// Select all text
				range2.moveToElementText( obj );

				// Now move 'dummy' end point to end point of original range
				range2.setEndPoint( 'EndToEnd', range );

				// Now we can calculate start and end points
				var  rngLength = DisplayedLength( range.text );
				var  rn2Length = DisplayedLength( range2.text );
				var  selStart  = rn2Length - rngLength;

				range.collapse( false );

				range2.moveToElementText( obj );
				range2.setEndPoint( 'StartToEnd', range );
if  ( nTrailingLF > 0 )  {
	range2.text = range2.text + strRepeat( "\n", nTrailingLF ) + "E";
	range2.moveStart( "character", - range2.text.length );
	/***/  alert( "Added E" );
}
				rn2Length = DisplayedLength( range2.text );

range2.select();
/***/  alert( "Selecting Range 2, length = " + rn2Length );

				var  selEnd = objLength - rn2Length;
				var  selLength = selEnd - selStart;


			/***
			obj.selectionStart = range2.text.length - range.text.length;
			obj.selectionEnd = obj.selectionStart + range.text.length;

			alert( "IE Copy:\nobj.selectionStart = " + obj.selectionStart + "\nobj.selectionEnd = " + obj.selectionEnd );
			***/
}
/***  DELETE ALL OF THE ABOVE TEST CODE  ***/
////////////////////////////////////////////////////////////////////////////////////
		}
		else  {
			RangeText = range.text;
		}


		/* Replace the Text */

		if  ( typeof( URL ) == "undefined"  ||  !URL )  {
			if  ( text == "%Clipboard%" )
				range.execCommand( "Paste" );
			else  {
				range.text = text;
				range.moveStart( "character", - DisplayedLength( text ) );
				range.select();
			}
		}
		else  if  ( URL == "%Copy%" )  {
			/* Do not replace the selected text. */
		}
		else  if  ( URL == "%Text%"  ||  URL == "%TextSelect%" )  {

			//***/  alert( "IE " + URL );

			range.text = text;

			if  ( URL == "%TextSelect%" )  {
				range.moveStart( "character", - DisplayedLength( text ) );
				//***/  alert( "Check moveStart( character, " + ( - DisplayedLength( text ) ) + " );" );
			}
			else  {
				range.moveStart( "character", 0 );
				//***/  alert( "Check moveStart( character, 0 );" );
			}

			range.select();
			//***/  alert( "Check range.select();" );
		}
		else  if  ( URL == "%HTML%"  ||  URL == "%HTMLStructure%"  ||  URL == "%HTMLMultiple%"  ||  URL == "%TextMultiple%" )  {
			var  saveText = range.text;
			if  ( URL == "%HTMLMultiple%" )
				saveText = saveText.replace( /\r\n/g, HTMLTagClose + "\r\n" + HTMLTagOpen ).replace( emptyTag, "" );
			var  endText = saveText + HTMLTagClose;
			if ( obj.selectionStart >= 0 )  {
				/***  Opera:  ***/
				var  TagLen = HTMLTagClose.replace( /\r\n/g, "rn" ).length;
				var  TextLen = saveText.replace( /\r\n/g, "rn" ).length;
			}
			else  {
				/***  IE:  ***/
				var  TagLen = HTMLTagClose.replace( /\r\n/g, "n" ).length;
				var  TextLen = saveText.replace( /\r\n/g, "n" ).length;
			}
			range.text = HTMLTagOpen + saveText + HTMLTagClose;

			range.moveEnd( "character", - TagLen );
			range.moveStart( "character", - TextLen );
			range.select();
		}
		else  {
			range.text = aTagBegin;
			if  ( URL == "%Clipboard%" )
				range.execCommand( "Paste" );
			else
				range.text = URL;
			range.text = aTagEnd + text + aTagClose;
			range.moveStart( "character", -( text.length + aTagClose.length ) );
			range.moveEnd( "character", - aTagClose.length );
			range.select();
		}
	}

	else  if ( typeof( obj.selectionStart ) != "undefined"  &&  obj.selectionStart >= 0 )  {
		// Go the Gecko (Firefox) way

		/* Find the Start and End Position */
		var start = obj.selectionStart;
		var end   = obj.selectionEnd;
		var textValue;

		RangeText = obj.value.substr( start, end - start );
		//RangeText = "Start = \"" + start + "\", End = \"" + end + "\"";

		if  ( typeof( URL ) == "undefined" )  {
			textValue = text;
			obj.value = obj.value.substr( 0, start )
			    + textValue
			    + obj.value.substr( end, obj.value.length );

			obj.selectionStart = start;
			obj.selectionEnd   = obj.selectionStart + ( textValue.replace( /\r\n/g, "n" ).length );
		}
		else  if  ( URL == "%Copy%" )  {
			/* Do not replace the selected text. */
		}
		else  if  ( URL == "%Text%"  ||  URL == "%TextSelect%" )  {
			textValue = text;
			obj.value = obj.value.substr( 0, start )
			    + textValue
			    + obj.value.substr( end, obj.value.length );
			if  ( URL == "%TextSelect%" )  {
				obj.selectionStart = start;
				obj.selectionEnd   = obj.selectionStart + ( textValue.replace( /\r\n/g, "n" ).length );
			}
			else  {
				obj.selectionStart = start + ( textValue.replace( /\r\n/g, "n" ).length );
				obj.selectionEnd = obj.selectionStart;
			}
		}
		else  if  ( URL == "%HTML%"  ||  URL == "%HTMLStructure%"  ||  URL == "%HTMLMultiple%"  ||  URL == "%TextMultiple%" )  {
			var  saveText = obj.value.substr( start, end - start );
			if  ( URL == "%HTMLMultiple%" )
				saveText = saveText.replace( /\n/g, HTMLTagClose + "\n" + HTMLTagOpen ).replace( emptyTag, "" );
			textValue = HTMLTagOpen + saveText + HTMLTagClose;
			obj.value = obj.value.substr( 0, start )
			    + textValue
			    + obj.value.substr( end, obj.value.length );

			obj.selectionStart = start + HTMLTagOpen.replace( /\r\n/g, "n" ).length;
			obj.selectionEnd   = obj.selectionStart + ( saveText.length );
		}
		else  {
			textValue = aTagBegin + URL + aTagEnd + text + aTagClose;
			obj.value = obj.value.substr( 0, start )
			    + textValue
			    + obj.value.substr( end, obj.value.length );

			obj.selectionStart = start + textValue.length - ( text.length + aTagClose.length );
			obj.selectionEnd   = obj.selectionStart + ( text.length );
		}

		/* Remember obj is a textarea or input field */
		obj.focus();
	}

	else {
		// Fallback for any other browser
		RangeText = "";
	}

	return  RangeText;
}

