Searching a Web Page

A text range is an expanse of text that has been identified on a Web page for application of special text-range methods. These methods include searching the range to locate matching text, searching and replacing text within the range, or copying found text for use in other scripting applications on the page.

Creating a Text Range

In order to access text on a page, a Text Range object must be created. A Text Range is an identified string of text that can encompasses the entire body of the document down to a single character. It is created with the createTextRange() method of the document object. The general format for creating a Text Range is shown below.

variable = object.createTextRange()
Figure 12-13. General format for Text Range object.

The variable is a reference variable and object is a selected range of text. In a page search operation, the entire document is included in the Text Range with an assignment such as

var SearchRange = document.body.createTextRange()

Searching a Text Range

One of the reasons for creating a Text Range is to permit searching of the range to locate matching text. A matching text string is located with the findText() method of a previously create Text Range object. Therefore, the two statements,

var SearchRange = document.body.createTextRange()
SearchRange.findText("hello")

locate the first occurence of the string "hello" on the page. Of course, once the word is located, something must be done with it. In a search operation, it is customary to highlight the word and scroll the page so it can be viewed. These steps are accomplished with the select() method to highlight the text and the scrollIntoView() method to scroll the page to the found text.

As a simple example, the following button searches for the word "customary" on this page and highlights the text.

Figure 12-14. Searching for a word on the page.
<script type="text/javascript">

function Search()
{
  var SearchRange = document.body.createTextRange();
  SearchRange.findText("customary");
  SearchRange.select();
  SearchRange.scrollIntoView();
}

</script>

<input type="button" value="Find 'customary'" onclick="Search()"/>
Listing 12-12. Code to search for a word on the page.

In this example, a literal string is provided as the search parameter. You can use a textbox entry just as easily. The findText() method would include a reference to the value in the textbox.


Enter text to find:

Figure 12-15. Searching for an entered text string.
<script type="text/javascript">

function Search()
{
  var SearchRange = document.body.createTextRange();
  SearchRange.findText(document.getElementById("SearchText").value);
  SearchRange.select();
  SearchRange.scrollIntoView();
}

</script>

Enter text to find: <input id="SearchText" type="text"/>
<input type="button" value="Find" onclick="Search()"/>
Listing 12-13. Code to search for an entered text string.

Performing Continuing Searches

The search for a word or phrase should not necessarily end with the first match. Click the "Open Search" button below to display a scrolling search box that remains in view as the search scrolls down the page. An example search string is pre-entered in the textbox; you can change it to search for any text on this page. Click the "Find Next" button in the search box to repeatedly highlight subsequent matches on this page.

Figure 12-16. Continuous search for an entered text string.

The scrolling technique works identically to the method for scolling page elements discussed previously under "Document Properties." Layout of the scrolling box and scrolling code is shown below.

<script type="text/javascript">
...
function ScrollSearchBox()
{
  document.getElementById("SearchBox").style.top = document.body.scrollTop +
    (document.body.clientHeight / 2) -
    (parseInt(document.getElementById("SearchBox").style.height) / 2);
}

</script>

<body onscroll="ScrollSearchBox()">

<div id="SearchBox" style="position:absolute; width:400px; height:20px;
left:100px; border:ridge 3px; padding:3px; color:#DC6000; 
background-color:#F0F0F0; visibility:hidden">
  <b>Search:</b>
  <input type="text" id="SearchText" value="text range"/>
  <input type="button" value="Find Next" onclick="FindString()"/>
  <input type="button" value="End Find" onclick="EndSearch()"/>
</div>

<input type="button" value="Open Search" onclick="StartSearch()"/>
Listing 12-14. Code to scroll a search box.

An onScroll="ScrollSearchBox()" event handler is associated with the <body> tag to trap for scroll events surrounding the page. Whenever the page scrolls, the search box follows along in the middle of the browser window.

Complete coding for the search process is shown below.

<script type="text/javascript">

var PageRange;

function StartSearch()
{
  document.getElementById("SearchBox").style.visibility = "visible";
}

function FindString() 
{
  if (document.getElementById("SearchText").value !=  "") {
    
    if (PageRange == null) {
      PageRange = document.body.createTextRange();
    }
    
    if (PageRange.findText(document.getElementById("SearchText").value) != false ) {
      PageRange.select();
      PageRange.scrollIntoView();
      PageRange.moveStart("word");
    } else {
      PageRange = null;
    }
  }
}

function EndSearch()
{
  PageRange = null;
  document.getElementById("SearchBox").style.visibility = "hidden";
}

function ScrollSearchBox()
{
  document.getElementById("SearchBox").style.top = document.body.scrollTop +
    (document.body.clientHeight / 2) - 
    (parseInt(document.getElementById("SearchBox").style.height) / 2);
}

</script>
Listing 12-15. Code for continuous search for text entered into a scrolling search box.

When the "Open Search" button is clicked, the search box is made visible with a call to function StartSearch(). After entering search text into the textbox, the "Find Next" button is clicked to begin searching the page starting at the top. Searching is handled by the FindString() function.

First, the textbox is checked to make sure that a search string has been entered. If so, the search continues.

var PageRange;

function FindString() 
{
  if (document.getElementById("SearchText").value !=  "") {
    
    if (PageRange == null) {
      PageRange = document.body.createTextRange();
    }
    ...
}

In order to search the entire page, a Text Range encompassing the document must exist. If this range has not yet been created it is done so by assigning it to reference variable PageRange. This variable is declared as a global variable for access by all functions.

The search code itself is relatively straight-forward. The findText() method looks for the string appearing in the textbox. When the first occurence is located, the select() method highlights it and the scrollIntoView() method scrolls the page to bring it into view.

function FindString() 
{
    ...
    if (PageRange.findText(document.getElementById("SearchText").value) != false ) {
      PageRange.select();
      PageRange.scrollIntoView();
      PageRange.moveStart("word");
    } else {
      PageRange = null;
    }
  }
}

This, however, is not the end of the search. With another click of the "Find Next" button, this FindString() function is called again to locate the next occurence of the search string. On subsequent calls, though, you should not begin again at the top of the document. The Text Range needs to be narrowed, with its starting point moved past the previous occurence of the found string.

Resetting the starting point of the Text Range is accomplished with the moveStart("word") method. The starting point is moved to the beginning of the next "word" beyond the currently selected string. Each time an occurence of the search string is located, this method is applied so that the next call to the FindString() function picks up where the previous call left off.

The FindString() function is called on each click of the "Find String" button, moving down the page and highlighting the next matched string. Eventually, a matching string is not found and the PageRange variable is cleared. Therefore, on the next call to the function, a new document-length range is created and searching begins again at the top of the document. This repetition continues until the "End Find" button is clicked to call the StopSearch() function, which clears the reference variable and hides the search box.

function EndSearch()
{
  PageRange = null;
  document.getElementById("SearchBox").style.visibility = "hidden";
}

Replacing Text

With slight modification, the above search script can be used for searching and replacing. The Search Box is recoded to include a second textbox for replacement text along with a "Replace" button.

Figure 12-17. Continuous search and replacement for an entered text string.

Changes to the previous script and XHTML are shown below in bold.

<script type="text/javascript">
var PageRange;

function StartSearch()
{
  document.getElementById("SearchBox").style.visibility = "visible";
}

function FindString() 
{
  if (document.getElementById("SearchText").value !=  "") {
    
    if (PageRange == null) {
      PageRange = document.body.createTextRange();
    } else {
      PageRange.moveStart("word");
    }
    
    if (PageRange.findText(document.getElementById("SearchText").value) != false) {
      PageRange.select();
      PageRange.scrollIntoView();
    } else {
      PageRange = null;
    }
  }
}

function Replace()
{
  PageRange.pasteHTML(document.getElementById("ReplaceText").value);
}

function EndSearch()
{
  PageRange = null;
  document.getElementById("SearchBox").style.visibility = "hidden";
}

function ScrollSearchBox()
{
  document.getElementById("SearchBox").style.top = document.body.scrollTop +
    (document.body.clientHeight / 2) - 
    (parseInt(document.getElementById("SearchBox").style.height) / 2);
}

</script>

<div id="SearchBox" style="position:absolute; width:420px; height:20px;
left:100px; border:ridge 3px; padding:3px; color:#DC6000; 
background-color:#F0F0F0; visibility:hidden">
  <b>Search:</b> 
  <input type="text" id="SearchText" value="text range"/>
  <b>Replace:</b>
  <input type="text" id="ReplaceText" value="REPLACEMENT"/>
  <input type="button" value="Find Next" onclick="FindString()"/>
  <input type="button" value="Replace" onclick="Replace()"/>
  <input type="button" value="End Find" onclick="EndSearch()"/>
</div>
Listing 12-16. Code for continuous search and replacement for text entered into a scrolling search box.

The PageRange.moveStart("word") method has been moved to the start of the search routine (from its previous location immediately after the search string is found and scrolled into view); otherwise, the cursor location would be moved past the word to be replaced prior to its replacement.

A new function, Replace(), uses the pasteHTML() method to paste the value from the replacement textbox into the selection. Note that both text and XHTML code can be pasted to the page, overwriting a selection.