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 s(ThisElement) /* Select */
{
	ThisElement = EnclosingRow(ThisElement);
	/* Select row if currently unselected, deselect otherwise */
	if( ThisElement.className == "hs" )
	{
		ThisElement.className = "v";
	}else{
		ThisElement.className = "hs";
	}
}
function h(ThisElement) /* Hover */
{
	ThisElement = EnclosingRow(ThisElement);
	if( ThisElement.className == "s" )
		ThisElement.className = "hs";
	else
		ThisElement.className = "h";
}
function u(ThisElement) /* Unhover */
{
	ThisElement = EnclosingRow(ThisElement);
	if( ThisElement.className == "hs" || ThisElement.className == "s")
		ThisElement.className = "s";
	else
		ThisElement.className = "v";
}

function Setup() /* Set up this page */
{
	var theTable;
	var i,j;

	theTable = document.getElementById("data");
	if( !theTable )
	{
		alert("Cannot find table with id 'data'. Search function will not work.");
		return;
	}
	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;
	}
}

/* Regular Expression Box is Checked. Suppress 'all words must match' search */
function CheckedREBox()
{
	theREBox = document.getElementById('RE');
	theAllWordsBox = document.getElementById('AND');

	theAllWordsBox.disabled = (theREBox.value == "on");
	
}

/* Search text entered, check to see if button should be suppressed or not */
function EnteredSearchText()
{
	theSearchButton = document.getElementById('SearchButton');
	theSearchText = document.getElementById('SearchInput');

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

function Debug(s)
{
	if( (theDebug = document.getElementById('debug')) )
	{
		theDebug.innerHTML = s;
	}
}

