IE Behaviors To Turn Keywords Into Hyperlinks

By Robbe D. Morris

Printer Friendly Version

Robbe Morris
Robbe & Melisa Morris
Have you ever wanted to convert keywords to hyperlinks in your pages at runtime after the initial page loads?  We refer to these as custom Smart Tags.  Of course, we really don't use Microsoft's Smart Tag technology.  We utilize JavaScript and IE behaviors to dynamically convert the keywords to links.  One of the major challenges we faced with creating this process was not disturbing existing form elements and links.  No small task...
My good friend Peter Bromberg (co-founder of this site and resident human object model) suggested that we trying using the .createTextRange method of the document.body object.  It was a great idea and worked much better than using regular expressions.  We ended up creating an XML data island in the HTML sample page, the behavior file keywordpro.htc and attached it to a style class, and then wrote a JavaScript function to create our links in the page.  If you would like to view a demonstration of this capability, click here.
 


 
In the JavaScript function KeyWordInit(), we collect the A tags as they exist prior to link creation into an array.  If our replacement process happens to alter a link, we'll use this array to reset the links in the page after the process has completed.  We utilize IE behaviors to support normal events over tags such as the BOLD tag we've used here.  By attaching behavior events to the style, we can trigger JavaScript functionality not normally available.
While testing the code, I noticed that on larger pages, the collapse(true) didn't always reset the text range to the beginning again after processing several keywords.  For this reason, you'll see what appears to be an unnecessary recreation of the text range on the body object.  Please review the comments in the JavaScript file for details of how this keyword conversion actually works.

Sample HTML Page
 
     <HTML>
      <xml src="/behaviors/keywordpro.xml" id="xmlkeywords" async="false"></xml>
      <style> .KeyWordHiliting {behavior:url(/behaviors/keywordpro.htc)}</style>
      <SCRIPT LANGUAGE="JavaScript" src=/behaviors/keywordpro.js ></script>

      <BODY onload=KeyWordInit(); >
  
       <form id=frmSubmit name=frmSubmit>
          <table align="center" cellspacing=0 cellpadding=0 border =0>
          <tr><td align="left" >xml stuff</td></tr>
           <tr><td align="left"><a href=http://www.topxml.com target=_blank>XML101.com</a></td></tr>
           <tr><td align="left"><input name=txtBox value='XML'></td></tr>
          </table>
        </form>
   </BODY></HTML>
   
Keywordpro.js JavaScript File
function KeyWordInit()
{ 

  //  Create an XML document object reference to our XML data island
  var oXMLDoc = window.document.all("xmlkeywords");  
  // Create an XML document list of all keywords
  var oXMLList = oXMLDoc.selectNodes("//KEYWORDS/KEYWORD");
  // How many keywords do we have?
  var nTot = oXMLList.length;
  var sKeyURL='';
  var sKeyPhrase='';
  // This array stores the actual .href values of existing links.
  var oLinks = new Array();
  // This array stores the contents between the  tags
  var oLinksHTML = new Array();
 
  var nLinks = document.all.tags('A').length;
 
  // Store our current links in their proper arrays.
  for (i=0;i<nLinks;i++) { oLinks[i] = document.all.tags('A')[i].href; oLinksHTML[i] = document.all.tags('A')[i].innerHTML; }
   
 // Iterate through our XML document of keywords and replace them with links

   for(nCnt=0;nCnt<nTot;nCnt++)
   {
          var oXMLNode = oXMLList.nextNode();
          sKeyURL = oXMLNode.text;
         sKeyPhrase = oXMLNode.attributes(1).text;
     
       // Recreate the text range every other keyword to get around bug mentioned
       // above.

       if (nCnt % 2 == 0) {   var oRange = document.body.createTextRange();   }
       else{  oRange.collapse(true); }

     // Find each instance of the current keyword and process it.
   
      for (i=0;oRange.findText(sKeyPhrase)!=false; i++)
      { 
        try
        {  
  oRange.pasteHTML('<b KeyWordURL=' + sKeyURL + ' style="color:#6666CC;text-decoration:none" class=KeyWordHiliting >' + oRange.text + '</b>'); 
           oRange.collapse(false);
        }
        catch (e) {  oRange.collapse(false);   }				    
      }
    }

   // go through all of the links again and replace them with their original values just in case our processing
   // pasted invalid html in them.

     for (i=0;i<nLinks;i++) {  document.all.tags('A')[i].href = oLinks[i];  document.all.tags('A')[i].innerHTML = oLinksHTML[i]; }
 
}
   
Keywordpro.xml Data Island File
   <?xml version='1.0'?>
<KEYWORDS>
    <KEYWORD id="1" keyphrase="xsl" >http://www.nullskull.com/keywordpromo.asp</KEYWORD>
    <KEYWORD id="2" keyphrase="xselerator">http://www.nullskull.com/keywordpromo.asp</KEYWORD>
    <KEYWORD id="3" keyphrase="sql server" >http://www.nullskull.com/keywordpromo.asp</KEYWORD>
    <KEYWORD id="5" keyphrase="soap" >http://www.nullskull.com/keywordpromo.asp</KEYWORD>
    <KEYWORD id="0" keyphrase="xml" >http://www.nullskull.com/keywordpromo.asp</KEYWORD>
</KEYWORDS> 
   
Keywordpro.htc Behavior File
<PUBLIC:ATTACH EVENT="onmouseover" ONEVENT="Hilite()" />
<PUBLIC:ATTACH EVENT="onmouseout"  ONEVENT="Restore()" />
<PUBLIC:ATTACH EVENT="onclick"  ONEVENT="KeyWordLaunch()" />
<SCRIPT LANGUAGE="JavaScript1.2">
var normalColor;

function Hilite()
{
   if (event.srcElement == element)
   { 
     normalColor = style.color;  
     runtimeStyle.color  = "#000000";
     runtimeStyle.cursor = "hand";
   }
}

function Restore()
{
   if (event.srcElement == element)
   {
      runtimeStyle.color  = normalColor;
      runtimeStyle.cursor = "";
   }
}
function KeyWordLaunch()
{
  if (event.srcElement == element)
   {
         var sOptions = "width=500,height=350,scrollbars=1,resizable=1";
         var winkey = window.open(element.KeyWordURL,"",sOptions);
   }
}
</SCRIPT>
   

Robbe has been a Microsoft MVP in C# since 2004.  He is also the co-founder of NullSkull.com which provides .NET articles, book reviews, software reviews, and software download and purchase advice.