Still got some quirks to work out, but it's pretty effective. I hate that I had to use innerHTML ("considered harmful!") but it does get the job on. Any suggestions?


Assumes this document extension:
Code:
document.getElement = function (anElementID) {
   return document.getElementById ? document.getElementById(anElementID) : document.all ? document.all[anElementID] : document.layers ? document.layers[anElementID] : 'undefined';
}
here's the meat of it:
Code:
// constructor
function FindInText() {
   if (arguments.length) {
      // set up properties
      this.originalSource = null; // must be filled with document.innerHTML later, on first search
      this.formVar = arguments[0];
      this.highlightBackColor = arguments[1] ? arguments[1] : "#ffff66";
      this.highlightTextColor = arguments[2] ? arguments[2] : "#000000";
      this.caseSensitive = arguments[3] ? arguments[3] : false;
      this.completeWord = arguments[4] ? arguments[4] : false;
      this.searchStringLength = 0;
      this.stringComponents = {
         startHighlight: "<span style='background-color: " + this.highlightBackColor + ";color=" + this.highlightTextColor + "'>",
         endHighlight: "</span>"
      }
      if (document.getElement('DOT_findTextInPageForm') == null) {
         // draw form
         document.write('<form id="DOT_findTextInPageForm" action="#" onsubmit="' + this.formVar + '.runSearch(this.elements.searchFormText.value);return false;">' +
            'Search Text: <input type="text" name="searchFormText" id="searchFormText">' +
            '<input type="submit" value="Search"><br>' +
            '<font size=-1>' +
            '<input type="checkbox" onclick="' + this.formVar + '.setCaseSensitivity(this.checked)"');
         if (this.caseSensitive) document.write(" checked");
         document.write('>Match Case?' +
            '<input type="checkbox" onclick="' + this.formVar + '.setCompleteWord(this.checked)"');
         if (this.completeWord) document.write(" checked");
         document.write('>Match Complete Word?' +
            '</font>' +
            '<input type="reset" onclick="' + this.formVar + '.clearResults()" value="Clear">' +
            '</form>');
      }
   } else return;   // if no arguments are passed, we're just setting up the prototype
}
new FindInText();

// FindInText methods
FindInText.prototype.validate = function (toValidate) {
   if (toValidate.length == 0) return false;
   toValidate.replace(/&/g, "&amp;");
   toValidate.replace(/"/g, "&quot;");
   toValidate.replace(/</g, "&lt;");
   toValidate.replace(/>/g, "&gt;");
   toValidate.replace(/\\/g, "\\");
   toValidate.replace(/\+/g, "\+");
   toValidate.replace(/\*/g, "\*");
   toValidate.replace(/\?/g, "\?");
   toValidate.replace(/\./g, "\.");
   toValidate.replace(/\[/g, "\[");
   toValidate.replace(/\]/g, "\]");
   toValidate.replace(/\^/g, "\^");
   toValidate.replace(/\$/g, "\$");
   toValidate.replace(/\(/g, "\(");
   toValidate.replace(/\)/g, "\)");
   toValidate.replace(/\{/g, "\{");
   toValidate.replace(/\}/g, "\}");
   toValidate.replace(/\|/g, "\|");
   toValidate.replace(/\&/g, "\&");
   return toValidate;
}

FindInText.prototype.setCaseSensitivity = function (bool) {
   if (bool && bool == true || bool == false)
      this.caseSensitive = bool;
   return;
}

FindInText.prototype.setCompleteWord = function (bool) {
   if (bool && bool == true || bool == false)
      this.completeWord = bool;
   return;
}

FindInText.prototype.clearResults = function () {
   document.body.innerHTML = this.originalSource;
   return;
}

FindInText.prototype.runSearch = function (argTextToFind) {
   var highlightedText, j, k;
   var results = new Array();
   if (typeof this.originalSource == 'undefined' || this.originalSource == null) {
      this.originalSource = document.body.innerHTML;
   } else {
      this.clearResults();
   }
   var highlightedText = textToSearch = this.originalSource;
   textToFind = this.validate(argTextToFind);
   if (!textToFind) return false;
   this.searchStringLength = textToFind.length;
   var atts = "g";
   if (this.completeWord) 
      textToFind = "(!| )" + textToFind + "( |$)";   // avoid text inside tags
   if (!this.caseSensitive) 
      atts += "i";
   var regexToFind = new RegExp(textToFind, atts);
   while ((result = regexToFind.exec(textToSearch)) != null) {   //> IDE parsing bug
      if (result.index > textToSearch.indexOf(">", textToSearch.lastIndexOf("<", result.index)) && result.index < textToSearch.indexOf("<", textToSearch.lastIndexOf(">", result.index))) {
         results[results.length] = result.index;
      }
   }
   k = results.length;
   if (!k) {
      var msg = "term '" + argTextToFind + "' was not found in the text.";
      if (this.completeWord) msg = "complete " + msg;
      if (this.caseSensitive) msg = "case-sensitive " + msg;
      msg = "The " + msg;
      alert(msg);
      return false;
   }
   while (k--) {   // this loop only works right with DECREMENTS not INCREMENTS to the iterator
      thisPosition = results[k];
      // close highlight
      tmpHighlight = highlightedText.substring(thisPosition + this.searchStringLength);
      highlightedText = textToSearch.substring(0, thisPosition + this.searchStringLength) + this.stringComponents.endHighlight + tmpHighlight;
      // open highlight
      tmpHighlight = highlightedText.substring(thisPosition);
      highlightedText = textToSearch.substring(0, thisPosition) + this.stringComponents.startHighlight + tmpHighlight;
   }
   document.body.innerHTML = highlightedText;
   return;
}
here's the super-easy implementation.
Code:
<body>
<script type="text/javascript">
	ECD_findInPage = new FindInText('ECD_findInPage');
</script>
<noscript>Please use CTRL+F to find text in this page.</noscript>...</body>
script src="" it, or just paste it in the header, no matter.

arguments:
0. Variable name you're using when you call the constructor. Required.
1. Highlight background color, defaults to #ffff66
2. Highlight foreground color, defaults to #000000
3. Case sensitive, defaults to false
4. Complete word, defaults to false

I'll check up on this here thread periodically, hopefully some suggestions will be made!

edited to turn those tabs into 3 spaces