Jonathan Snook.ca

 

Custom Find and Replace Dialog for MSHTML or DEC

The find dialog functionality that comes with the DEC does the trick but if you've moved onto the MSHTML functionality in IE5+ or you want to change the interface in the DEC then you need something custom made.

First, let's put together the code to open the find dialog:

showModelessDialog( "find.html", window,

    "dialogWidth:385px; dialogHeight:165px; scroll:no; status:no; 

    help:no;" ); }

This piece of JavaScript does something pretty simple. It opens find.html into a dialog box. It also passes a reference to the window object to the dialog box.

Note: there are two different types of dialogs in Internet Explorer: Modal and Modeless. A Modal dialog prevents a user from doing anything on the HTML page until they have closed the dialog. Modeless, however, allows the user to still access the main HTML window as well as do things within the dialog. I've used Modeless to allow us to find text in the main window, edit the text in the main window and then go back to the dialog box to search for more words.

The fun really comes in the dialog itself.

<HTML>

    <HEAD>

<TITLE>Find/Replace</TITLE>

<script language="JavaScript">

// on load create a textrange with everything in my 

// editor object tbContentElement 

var rng = dialogArguments.document.all.tbContentElement.

               DOM.selection.createRange();



function window.onunload()

{

  dialogArguments.dWin=null; // releases my reference

}



// returns a calculated value for matching case and

// matching whole words

function searchtype(){

  var retval = 0;

  var matchcase = 0;

  var matchword = 0;

  if (document.all.blnMatchCase.checked) matchcase = 4;

  if (document.all.blnMatchWord.checked) matchword = 2;

  retval = matchcase + matchword;

  return(retval);

}



// find the text I want

function findtext(){

  if (document.all.strSearch.value.length < 1) {

    alert("Please enter text in the \"Find what:\" field.");

  } else {

    var searchval = document.all.strSearch.value;

    rng.collapse(false);

    if (rng.findText(searchval, 1000000000, searchtype())) {

      rng.select();

    } else {

      var startfromtop = confirm("Your word was not found.\nWould you 

                                    like to start again from the top?");

      if (startfromtop) {

        rng.expand("textedit"); // selects everything

        rng.collapse(); // collapse at the beginning

        rng.select(); // create the selection

        findtext(); // start again 

      }

    }

  }

}

</script>

</HEAD>

<BODY bgcolor="ThreeDFace">

  <FORM NAME="frmSearch" method="post" action="">

  <TABLE CELLSPACING="0" cellpadding="5" border="0">

  <TR><TD VALIGN="top" align="left" nowrap 

              style="font-family:Arial; font-size:11px;">

    <label for="strSearch" accesskey="n">Fi<u>n</u>d what:</label><br>

    <INPUT TYPE=TEXT SIZE=40 NAME=strSearch 

           id="strSearch" style="width:280px;"><br>

    <INPUT TYPE=Checkbox SIZE=40 NAME=blnMatchCase id="blnMatchCase">

    <label for="blnMatchCase">Match case</label><br>

    <INPUT TYPE=Checkbox SIZE=40 NAME=blnMatchWord ID="blnMatchWord">

    <label for="blnMatchWord">Match whole word only</label>

   </td>

  <td rowspan="2" valign="top">

    <button name="btnFind" accesskey="f" onClick="findtext();"

        style="width:75px; height:22px; font-family:Tahoma; 

               font-size:11px; margin-top:15px"><u>F</u>ind Next</button><br>

    <button name="btnCancel" onClick="window.close();"

        style="width:75px; height:22px; font-family:Tahoma; 

               font-size:11px; margin-top:7px">Close</button><br>

  </td></tr>

</table>

</FORM>

</BODY>

</HTML>

Basically, when you click on the Find Next button it takes the text that is entered into the input and runs the findtext() function. You'll notice that before I use the findText() method I collapse(false)... this ensures that the select moves to the end of a previously found word. This prevents the dialog from never going beyond the one word. The function checks that you've actually entered something in the input and if so, runs the findText() method (read more about the method at MSDN). The third parameter runs a function searchtype() that calculates whether it should match whole words only and/or match case.

The find function moves forward from where the selection is. If it can't find the word then it asks the user whether or not to start at the top. To start from the top we expand the selection to the entire page and then collapse the selection. That way I know the selection is at the beginning of the document.

Without revealing too many of my secrets, it is also possible to add replace and replace all functionality to this dialog with relative ease!

Enjoy!