	var n=0;
	var ShowSelectedOnly = false;
	var theTableBody = null;
	var theTableLength = 0;
	var nRecordsBeforeUpdate = 97; /* Number of records before next screen update (best if a prime number) */
	var theParsedPattern;
	var IgnoreCaseFlag = false;
	var NOTFlag = false;
	var ANDFlag = false;
	var nMatches = 0;
	var UpdateTimer = null;
	var nRows=0;
	var vStyle;
	var ShowAllButton;
	var ShowAllButtonRevealed = false;
	var SearchBox;
	var BodyLoaded = false;
	
	/* Histogram settings */
	var HistogramBackgroundColor = 'blue';
	var HistogramMinValue = 0;
	var HistogramMaxValue = 100;
	var HistogramLastPercent = 0;
	var HistogramLastValue = 0;
	var HistogramMaxPixels = 500;
	var HistogramHeight = 1;
	var HistogramObject = null;
	var HistogramTextObject = null;
	var HistogramCounter = -1;
	var HistogramDelay = 10;



	function EnclosingRow(theObject)
	{
		for( ThisElement = theObject; ThisElement.nodeName != "TR"; ThisElement = ThisElement.parentNode)
			;
		return(ThisElement);
	}
	
	
	function Setup() /* Set up this page */
	{
		var theTable;
		var i,j;

		theTable = document.getElementById("data");
		j = theTable.childNodes.length;
		for(i=0; i < j; i++)
		{
			if( theTable.childNodes[i].nodeName == "TBODY" )
			{
				theTableBody = theTable.childNodes[i];
				theTableLength = theTableBody.childNodes.length;
			}
		 }
		if( theTable == null )
		{
			alert("Internal initialization error: Cannot find data table");
			return;
		}

		/* Static data for Histogram */
		HistogramObject = document.getElementById("Histogram");
		HistogramTextObject = document.getElementById("HistogramText");
		if( HistogramObject == null || HistogramTextObject == null )
		{
			alert('Initialization error: Cannot find histogram objects');
			return;
		}
		HistogramMaxValue = theTableBody.childNodes.length;
		HistogramMaxPixels = theTable.clientWidth;
	}

	function ShowHideUnselected(thisButton)
	{
	
		theTable = document.getElementById("data");
		if( theTable == null )
		{
			alert("Internal initialization error: Cannot find data table");
			return;
		}

		if( ShowSelectedOnly )
		{
			ShowSelectedOnly = false;
			vStyle.style.display = "";
			thisButton.innerHTML = "Show Search Results Only";
		}else
		{
			ShowSelectedOnly = true;
			vStyle.style.display = "none";
			thisButton.innerHTML = "Show All Records";
		}
	}

	function FindStyle(theStyle)
	{
		var i,j ;

		for(j=0; j < document.styleSheets.length; j++)
		{
			cssRuleObject = document.styleSheets[j].cssRules;
			/* IE Insanity... */
			if( cssRuleObject == null )
			{
				cssRuleObject = document.styleSheets[j].rules;
			}
			
			for(i=0; i < cssRuleObject.length; i++)
			{
				/* IE4 special code */
				if( cssRuleObject[i].selectorText == theStyle || 
					cssRuleObject[i].selectorText == ("*" + theStyle) )		
				{
					return(cssRuleObject[i]);
				}
			}	 
		}
		alert('Error: cannot find CSS style with name: ' + theStyle);
		return(0);
	}  

	function ShowMatches()
	{
		var i;

		nMatches = 0;

		if( !BodyLoaded)
		{
			alert("The page has not finished loading. Please try again when it has.");
			return;
		}

		thePattern = document.getElementById('SearchInput').value;
		if( thePattern == "" )
		{
			alert('You must specify something to search for');
			return(false);
		}
		
		IgnoreCaseFlag = document.getElementById('IgnoreCase').checked;
		REFlag = document.getElementById('RE').checked;
		NOTFlag = document.getElementById('NOT').checked;
		ANDFlag = document.getElementById('AND').checked;
		
		if( ! Histogram_init() )
		{
			alert("Internal Error: Cannot initialize histogram. " + HistogramObject + " - " + HistogramTextObject);
			return(false);
		}

		vStyle.style.display = "none";
		if( REFlag )
		{
			/* Regular expression */
			theParsedPattern = new RegExp(thePattern, IgnoreCaseFlag ? "i": "");
			SearchRE(1);
		}else
		{
			/* internet search */
			theParsedPattern = ParseInternetSearchString( IgnoreCaseFlag ? thePattern.toLowerCase() : thePattern );
			
			SearchInternet(1);
		}
		return(true);
	}

	function Histogram_init()
	{
		window.clearTimeout(UpdateTimer);
		
		if( HistogramObject == null || HistogramTextObject == null )
		{
			return(false);
		}

		HistogramObject.style.backgroundColor = "blue";
		HistogramObject.style.width="1px";
		
		HistogramTextObject.innerHTML = "Initializing...";
		
		return(true);
	}
	/* Show historgram with data set to 'i' */
	function HistogramUpdate(i)
	{
		if( HistogramObject == null ) return false;
		
		if( i > HistogramMaxValue)
		{
			alert("Truncating histogram position from " + i + " down to " + HistogramMaxValue);
			i = HistogramMaxValue;
		}

		HistogramObject.style.width = parseInt(( (i - HistogramMinValue) / (HistogramMaxValue - HistogramMinValue) ) * HistogramMaxPixels) + 'px';

		if( HistogramTextObject != null) 
			HistogramTextObject.innerHTML = i + ' of ' + HistogramMaxValue;
	}
	function HistogramDump()
	{
		alert("Histogram data:\n" + "color=" + HistogramBackgroundColor + "\nmin value=" + HistogramMinValue + "\nmax=" + HistogramMaxValue + "\nlast %=" + HistogramLastPercent + "\nlast value=" + HistogramLastValue + "\nmax px=" + HistogramMaxPixels + "\nhght=" + HistogramHeight + "\nctr=" + HistogramCounter);
	}
	function HistogramClear()
	{
		HistogramTextObject.innerHTML = "&nbsp;";
		HistogramObject.style.width = "0px";
		HistogramObject.style.backgroundColor = "white";
	}

	/* Continue search for regular expression */
	function SearchRE(i)
	{
		var j, RowMatches;
		
		for(j=0; j < nRecordsBeforeUpdate; )
		{
			if( i >= theTableLength )
			{
				FinishSearch(nMatches);
				return;
			}
			if( theTableBody.childNodes[i].nodeName == "TR" )
			{
				RowMatches = theParsedPattern.test( ExtractText(theTableBody.childNodes[i]) );
				if( (RowMatches && !NOTFlag) || (!RowMatches && NOTFlag) )
				{
					nMatches++;
					theTableBody.childNodes[i].className = 's';
				}else
				{
					theTableBody.childNodes[i].className = 'v';
				}
				j++;
			}

			i++;
		}

		HistogramUpdate(i);
		
		UpdateTimer = window.setTimeout('SearchRE(' + i + ')', 1/*msec*/);
	}

	/* Continue search for internet-style search string */
	function SearchInternet(i)
	{
		var j, k, RowMatches;

		for(j=0; j < nRecordsBeforeUpdate; )
		{
			if( i >= theTableLength )
			{
				FinishSearch(nMatches);
				return;
			}
			if( theTableBody.childNodes[i].nodeName == "TR" )
			{
				if( InternetMatch( ExtractText(theTableBody.childNodes[i]), theParsedPattern, IgnoreCaseFlag, NOTFlag, ANDFlag) )
				{
					nMatches++;
					theTableBody.childNodes[i].className = 's';
				}else
				{
					theTableBody.childNodes[i].className = 'v';
				}
				j++;
			}

			i++;
		}

		HistogramUpdate(i);
		
		UpdateTimer = window.setTimeout('SearchInternet(' + i + ')', 1/*msec*/);
	}

	function InternetMatch(theString, thePattern, IgnoreCaseFlag, NOTFlag, ANDFlag)
	{
		var i, s, thisWordFound, anyWordFound = false, allWordsFound = true;
		
		s = IgnoreCaseFlag ? theString.toLowerCase() : theString ;
		for(i=0; i < thePattern.length; i++)
		{
			thisWordFound = s.indexOf(thePattern[i]) >= 0; /* Failure is -1 */
			if( thisWordFound && !NOTFlag && !ANDFlag)
				return( true );
			else if( thisWordFound )
				anyWordFound = true;
			else if( !thisWordFound )
				allWordsFound = false;
		}
		
		return( NOTFlag ? !anyWordFound : (ANDFlag ? allWordsFound: false) );
	}
	/* Extract all text from an object */
	function ExtractText(theObject)
	{
		var i, s="";
				
		if( theObject.nodeValue != null )
			s += theObject.nodeValue + ' ';

		for(i=0; i < theObject.childNodes.length; i++)
			s += ExtractText(theObject.childNodes[i]);

		return( s.replace(/\n/,"") );
	}
	
	function ParseInternetSearchString(thePattern)
	{
		return( thePattern.split(" ") );
	}
	
	function FinishSearch(nMatches)
	{
		HistogramUpdate(theTableLength);

		if( HistogramTextObject != null) 
		{
			HistogramTextObject.innerHTML = 'Found ' + (nMatches <= 0 ? 'no' : nMatches) + ' record' + (nMatches==1 ? '':'s') + '.';
		}
		
		UpdateTimer = window.setTimeout('HistogramClear()', HistogramDelay * 1000);
		
		ShowAllButton = document.getElementById('ShowAll');
		SearchBox = document.getElementById('SearchBox');
		if( nMatches > 0 )
		{
			vStyle.style.display = "none";
			ShowAllButton.innerHTML = "Show All Records";
			ShowAllButton.style.display = '';
			ShowSelectedOnly = true;
			if( !ShowAllButtonRevealed ) /* Move button into position */
				NudgeShowAllButton(parseInt(SearchBox.offsetWidth) - parseInt(ShowAllButton.offsetWidth));
		}else{
			vStyle.style.display = "";
			ShowAllButton.style.display = 'none';
			ShowSelectedOnly = false;
			ShowAllButtonRevealed = false;
		}
		
	}
	
	function NudgeShowAllButton(CurrPos)
	{
	
		if( CurrPos < parseInt(SearchBox.offsetWidth)+20 )
		{
			CurrPos += 2;
			
			ShowAllButton.style.left = CurrPos + "px";
			
			window.setTimeout("NudgeShowAllButton(" + CurrPos + ")", 1);
		}else
		{
			ShowAllButton.style.left = parseInt(SearchBox.offsetWidth);
			ShowAllButtonRevealed = true;
		}
	}

	function CheckedREBox()
	{
		theREBox = document.getElementById('RE');
		theAllWordsBox = document.getElementById('AND');

		theAllWordsBox.disabled = theREBox.checked;
	}
	
	function EnteredSearchText()
	{
		theSearchButton = document.getElementById('SearchButton');
		theSearchText = document.getElementById('SearchInput');

		if( theSearchText.value == "" )
		{
			theSearchButton.disabled = true;
		}else{
			theSearchButton.disabled = false;
		}
	}
