 /*****************************
    HIGHLIGHTER.JS
	HTML Document text higlighter.
			
	Created for MedLink corporation by Bright9 LLC
	revised 1/14/2003
	www.bright9.com
	
	Copyright © 2002 MedLink corporation
	All rights reserved.
 *******************************/
// ------------------------------
function Highlighter(Document, SearchTerms){
// -------------------------------
	this.Terms = Highlighter.processUserTerms(SearchTerms);
	this.DocNodes = Document;
	this.notSupported = ! (Document.childNodes);
	this.TermExp = Highlighter.createSearchTermsRegExp(this.Terms);
	this.hitCount = 0;
}
// -----------------------------
Highlighter.START_REPLACE = "«Y";
Highlighter.END_REPLACE = "Z»";
Highlighter.ESC_PUNCTUATION = /\.|\/|\*|\+|\?|\\|\(|\)|\[|\]|\{|\}/ig;
Highlighter.TEXT_NODE = 3;
Highlighter.SEARCH_HIT_CLASS_NAME = "SearchWord";
Highlighter.HIT_ANCHOR = "Highlight";
Highlighter.NoiseWords = "AND OR NOT";
// -----------------------------
Highlighter.isPunctuation = function(Char){
// Return TRUE if leftmost character in
// CHAR is a punctuation character.
// -----------------------------
	var ASCVal = Char.charCodeAt(0);
	if ((ASCVal > 47) && (ASCVal < 58)) return false;
	if ((ASCVal > 64) && (ASCVal < 91)) return false;
	if ((ASCVal > 96) && (ASCVal < 123)) return false;
	return true;
}
// -----------------------------
Highlighter.isNoiseWord = function(Word){
// -----------------------------
	return (Highlighter.NoiseWords.indexOf(Word.toUpperCase()) >= 0);
}
// -----------------------------
Highlighter.processUserTerms = function(Terms){
// Conver the user-supplied terms to highlight to
// a string that can be used as a Regular Expression.
// -----------------------------
	var ProcessedPhrases = Highlighter.extractPhrases(Terms);
	var ProcessedTerms = ProcessedPhrases.ProcessedText;
	ProcessedTerms = Highlighter.processTerms(ProcessedTerms);
	for (Item in ProcessedPhrases.Phrases){	
		var Phrase = ProcessedPhrases.Phrases[Item];
		var IsPunctuation = Highlighter.isPunctuation(Phrase)
		Phrase =  Highlighter.escapeChars(Phrase);		
		if (! IsPunctuation) Phrase = "\\b" + Phrase;
		if (ProcessedTerms != "") ProcessedTerms = ProcessedTerms + "|";
		ProcessedTerms = ProcessedTerms + Phrase;			
	}
	return ProcessedTerms;
}
// -----------------------------
Highlighter.extractPhrases = function(Text){
// Extract any phrases (inside quotes) from TEXT.
	var EndPos = 0;
// -----------------------------
	var PhraseOBJ = new Object;
	var StartPos = 0;
	var i = 0;
	var ProcessedText;
	while (StartPos > -1) {
		StartPos = Text.indexOf("\"");
		EndPos = Text.indexOf("\"", StartPos + 1);
		if (EndPos == -1) break;
		else {
			var Phrase = Text.substr(StartPos, EndPos - StartPos + 1);
			Text = Text.replace(Phrase, "");
			Phrase = Phrase.replace(/\"/g, "");
			Phrase = Highlighter.trim(Phrase);
			if (Phrase != ""){	
				PhraseOBJ[i] = Phrase;
				i++;
			}				
			StartPos = Text.indexOf("\"");
		}		
	}
	return {ProcessedText:Text,Phrases:PhraseOBJ};
}
// -----------------------------
Highlighter.walkNodes = function(Node, ObjRef){
// -----------------------------		ObjRef.recursionDepth ++;		
	if (Node.hasChildNodes()){		var NodeIndex;	
		for (NodeIndex = 0; NodeIndex < Node.childNodes.length; NodeIndex++) {
			Highlighter.walkNodes(Node.childNodes[NodeIndex], ObjRef);
		}		
	}	if (Node.nodeType == Highlighter.TEXT_NODE) Highlighter.highlightWords(Node, ObjRef);		}
// -----------------------------
Highlighter.unHighlight = function(Document, Node){
// -----------------------------
	try {
		if (Node.hasChildNodes()){
			for (var NodeIndex = 0; NodeIndex < Node.childNodes.length; NodeIndex++) {
				Highlighter.unHighlight(Document, Node.childNodes[NodeIndex]);
			}		
		}	
		var Parent = Node.parentNode;		if (Node.className == Highlighter.SEARCH_HIT_CLASS_NAME){
			var TextNode = Document.createTextNode(Node.innerHTML);	
			Node.swapNode(TextNode);	
		//	Parent.insertBefore(TextNode, Node);
		//	Parent.removeChild(Node);
		//	Node.className = "";
			return;
		}
		if (Node.nodeName == "A"){
			if (Node.name.indexOf(Highlighter.HIT_ANCHOR) >= 0){ 
				var TextNode = Document.createTextNode("");
				Node.swapNode(TextNode);
		//		Node.parentNode.insertBefore(TextNode, Node);
		//		Node.parentNode.removeChild(Node);
		//		Node.name = "";	
			}
		}
	}
	catch (err) {}	
}
// ------------------------------
Highlighter.createSearchTermsRegExp = function(SearchTerms){
// ------------------------------
	var RegExpText;	
	NewRegExp = new RegExp(SearchTerms, "i");
	return NewRegExp;
}
// ------------------------------
Highlighter.gotoHit = function(Doc, HitID, AvailableHits){
// ------------------------------
	if (HitID + 1 <= AvailableHits) {
		var Loc = "#" + Highlighter.HIT_ANCHOR.toString() + HitID.toString();
		var URL = Doc.URL;
		var StartPos = URL.indexOf("#");
		if (StartPos >= 0) {
			URL = URL.slice(0, StartPos)
		}
		URL = URL + Loc;
		Doc.location = URL;	
	}
}
// ------------------------------
Highlighter.escapeChars = function(Term){
// Returns TERM with any punctuation characters
// escaped.
// ------------------------------
	var ProcessedText = Term;
	var StartPos = 0;
	if (Highlighter.hasEscapeChars(ProcessedText)){	
		var TestRegExp = new RegExp(Highlighter.ESC_PUNCTUATION);
		var Matches = Term.match(TestRegExp);
		for (var i = 0; i < Matches.length; i++){
			var StartPos = ProcessedText.indexOf(Matches[i], StartPos);
			ProcessedText = ProcessedText.slice(0, StartPos) + "\\" + ProcessedText.slice(StartPos);
			StartPos = StartPos + 2;
		}
	}
	return ProcessedText;
}
// ------------------------------
Highlighter.trim = function(Text){
// ------------------------------
	while (Text.substr(0, 1) == " ") Text = Text.slice(1);		
	while (Text.substr(Text.length - 1, 1) == " ") Text = Text.slice(0, Text.length - 1);
	return Text;		
}
// ------------------------------
Highlighter.hasEscapeChars = function(Text){
// Return TRUE if TEXT has punctuation characters in 
// it.
// ------------------------------
	var TestRegExp = new RegExp(Highlighter.ESC_PUNCTUATION);
	if (Text.length == 0) return false;		
	else return TestRegExp.test(Text);		
}
// ----------------------------- 
Highlighter.processTerms = function(Terms){
// Convert TERMS to a string that can be used
// in a regular expression.
// ----------------------------- 	
	var ProcessedTerm = "";	
	var TermArray = Terms.split(/\s+/);
	for (var i = 0; i < TermArray.length; i ++){	
		var Item = TermArray[i];
		if ((Item.length > 1) && (! Highlighter.isNoiseWord(Item))){
			if (ProcessedTerm != "") ProcessedTerm = ProcessedTerm + "|";
			var IsPunctuation = Highlighter.isPunctuation(Item);		
			Item = Highlighter.escapeChars(Item);			
			if  (! IsPunctuation) Item = "\\b" + Item;
			ProcessedTerm = ProcessedTerm + Item;		
		}			
	}
	return ProcessedTerm;
}
// -----------------------------
Highlighter.tokenizeNodeText = function(Text, TermExp){
// -----------------------------
	var Item;
	var Matches = Text.match(TermExp);
	var IsPunctation;	
	if (Matches != null){
		for (var j = 0; j < Matches.length; j++){
			IsPunctuation = Highlighter.isPunctuation(Matches[j]);
			Escaped = Highlighter.escapeChars(Matches[j]);	
			if (! IsPunctuation) Escaped = "\\b" + Escaped;				
			var Exp = new RegExp(Escaped, "i");							
			var LookedFor = Highlighter.START_REPLACE + Matches[j] + Highlighter.END_REPLACE;	
			Text = Text.replace(Exp, LookedFor);				
		}								
	}
	return Text;
}
// ----------------------------- 
Highlighter.highlightWords = function(Node, ObjRef){
// ----------------------------- 	
	var Text;
	var TextNode;
	var PreNodeValue = Highlighter.tokenizeNodeText(Node.nodeValue, ObjRef.TermExp);
	var StartPos = 0;
	var EndPos = 0;
	var WasChanged = false;	
	while (Node.parentNode.className != Highlighter.SEARCH_HIT_CLASS_NAME){
		StartPos = PreNodeValue.search(Highlighter.START_REPLACE);
		EndPos = PreNodeValue.search(Highlighter.END_REPLACE);
		if (StartPos == -1) break;			
		if (StartPos > 0){
			Text = PreNodeValue.slice(0, StartPos);
			TextNode = ObjRef.DocNodes.createTextNode(Text);
			Node.parentNode.insertBefore(TextNode, Node);
		}												
		StartPos = StartPos + Highlighter.START_REPLACE.length;	
		Text = PreNodeValue.substr(StartPos, EndPos - StartPos);		
		TextNode = ObjRef.DocNodes.createTextNode(Text);		
		var SpanElement = ObjRef.DocNodes.createElement("span");	
		SpanElement.className = Highlighter.SEARCH_HIT_CLASS_NAME;			
		SpanElement.appendChild(TextNode);
		var AnchorElement = ObjRef.DocNodes.createElement("<A NAME='" + Highlighter.HIT_ANCHOR + ObjRef.hitCount.toString() + "'>");
		Node.parentNode.insertBefore(AnchorElement, Node);				
		Node.parentNode.insertBefore(SpanElement, Node);			
		PreNodeValue = PreNodeValue.slice(EndPos + Highlighter.END_REPLACE.length);
		WasChanged = true;
		ObjRef.hitCount++;				
	}								
	if (WasChanged){
		if (PreNodeValue != ""){
			TextNode = ObjRef.DocNodes.createTextNode(PreNodeValue);
			Node.parentNode.insertBefore(TextNode, Node);		
		}					
		Node.parentNode.removeChild(Node);
	}		
}
// ----------------------------
Highlighter.prototype.highlightText = function(){
// ----------------------------
	this.hitCount = 0;		
	if (this.Terms != "") this.parseNodes();
}
// ----------------------------
Highlighter.prototype.parseNodes = function(){
// ----------------------------
	Highlighter.walkNodes(this.DocNodes, this);
}
// ----------------------------
Highlighter.prototype.removeHighlighting = function(){
// --------------------------
	Highlighter.unHighlight(this.DocNodes, this.DocNodes);
}	
// ----------------------------
Highlighter.prototype.hitCount = this.hitCount;
Highlighter.prototype.highlightClassName = this.SEARCH_HIT_CLASS_NAME;
Highlighter.notSupported = this.notSupported;
// ----------------------------
Highlighter.prototype.goToHighlight = function(HighlightID){
// ----------------------------
	Highlighter.gotoHit(this.DocNodes, HighlightID, this.hitCount);
} 
