Tuesday, September 17, 2024

Custom Smart Tags In IE

You may have noticed that several keywords on the EggHeadCafe website get converted to links (like XML for example) 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.

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 <a></a> 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.eggheadcafe.com/keywordpromo.asp</KEYWORD>

<KEYWORD id=”2″keyphrase=”xselerator”>
http://www.eggheadcafe.com/keywordpromo.asp</KEYWORD>

<KEYWORD id=”3″ keyphrase=”sql server”>
http://www.eggheadcafe.com/keywordpromo.asp</KEYWORD>

<KEYWORD id=”5″ keyphrase=”soap”>
http://www.eggheadcafe.com/keywordpromo.asp</KEYWORD>

<KEYWORD id=”0″ keyphrase=”xml”>
http://www.eggheadcafe.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 D. Morris
http://www.EggheadCafe.com

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles