homepage Welcome to WebmasterWorld Guest from 54.145.183.169
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member
Home / Forums Index / Code, Content, and Presentation / JavaScript and AJAX
Forum Library, Charter, Moderator: open

JavaScript and AJAX Forum

    
DOM/Javascript Add/Remove <span> tags
I wish to add/remove span tags of a specific class on a button press
Igau

10+ Year Member



 
Msg#: 1170 posted 3:36 am on Jan 22, 2004 (gmt 0)

Hi everyone, I wonder if you can help me with a small, but irritating bug that I have in my code.

First of all, the code itself (based on a highlight bookmarklet):

<script type="text/javascript">

function smartContextHighlight(text, selectionType) {

var dv;

if (selectionType == 'grouped') searchArray = [text];
else searchArray = text.split(" ");

var spans = document.getElementsByTagName('span');
var numSpans = spans.length;

for (var a = 0; a < numSpans; ++a) {

spans[a].style.backgroundColor = "transparent";

}

for (var i = 0; i < searchArray.length; i++) {

text = searchArray[i];

if (text == null ¦¦ text.length==0) return;

function searchWithinNode (node, te, len, colour) {
var pos, skip, spannode, middlebit, endbit, middleclone;
skip = 0;

if (node.nodeType == 3) {
pos=node.data.toUpperCase().indexOf(te);
if (pos>=0) {
spannode = document.createElement("span");
spannode.style.backgroundColor = colour;
spannode.className = "smartContextHighlighted";
middlebit = node.splitText(pos);
endbit = middlebit.splitText(len);
middleclone = middlebit.cloneNode(true);
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode,middlebit);
skip=1;
}
}

else if (node.nodeType == 1 && node.childNodes && node.tagName.toUpperCase()!= "SCRIPT" && node.tagName.toUpperCase!= "STYLE") {
for (var child=0; child < node.childNodes.length; ++child) {
child=child+searchWithinNode(node.childNodes[child], te, len, "yellow");
}
}
return skip;
}
searchWithinNode(document.body, text.toUpperCase(), text.length);
}
}

</script>

<body>
This is a selection test. This is a selection test. This is a selection test. Selection selection selection test test test this is a test of selection.
<input type="button" value="Group" onClick="smartContextHighlight('selection test', 'grouped');" />
<input type="button" value="Words" onClick="smartContextHighlight('selection test');" />
<input type="button" value="Group" onClick="smartContextHighlight('is a', 'grouped');" />
<input type="button" value="Words" onClick="smartContextHighlight('is a');" />
</body>
</html>

With that out of the way, I'll explain what I hope to achieve, and what the problem is.

Essentially, I wish for the user to be able to highlight text within ANY page (so treat the content as simple, raw content with no HTML), and I'm using this JavaScript to apply the highlighting.

It works in two ways, it can either highlight a group of words ("this is a test" gets highlighted) or highlight each word in that group, whether they're together or not ("this", "is", "a", "test" gets highlighted.)

What currently happens is that the script searches through the content and creates a <span> element around the search strings, then applies formatting.

That all works well, but I would prefer that with each run of this function, the old searches are cleared. Now...one thing I tried was just changing the properties of the <span>s that already existed... or nesting <span> tags but it just builds up more and more spans, the more you search....and if your keywords are common, there is immediate slowdown. Also, it doesn't work properly, as far as I've been able to manage.

Ideally, I wish to remove the highlight <span> tags altogether, but leave the original content in tact, but I have no idea on how to do this, and I would need to remove only the <span> tags that have their className set to "smartContextHighlighted", to avoid messing up any other <span> tags present on pages.

As it stands, I've tried to set any existing <span> tags with className="smartContextHighlighted" to have a transparent background. This causes only the 2nd and 4th buttons to work after a run through of the tests...

Can anyone help?

 

TrinkDawg

10+ Year Member



 
Msg#: 1170 posted 8:21 pm on Jan 22, 2004 (gmt 0)

Try this:

<html>
<head>
<script language="JavaScript">
<!--
function smartContextHighlight()
{
var bodyHTML = document.body.innerHTML;
var re = new RegExp('(<span class\=highlight>)([^<>]*)(<\/span>)', 'gi');
var newBodyHTML = bodyHTML.replace(re, "$2");
document.body.innerHTML = newBodyHTML;

if (arguments.length > 0)
{
var txt = '';
for (var i=0; i<arguments.length; i++)
{
txt += arguments[i];
if (i < arguments.length-1)
{
txt += '';
}
}
var bodyHTML = document.body.innerHTML;
/* strip html */
var re = new RegExp('<[^<>]*>', 'gi');
var HTMLArray = bodyHTML.match(re);
var strippedText = bodyHTML.replace(re, '$!$');

var re2Text = '(' + txt + ')';
var re2 = new RegExp(re2Text, 'gi');
var highlighted = strippedText.replace(re2, '<span class="highlight">$1</span>');

for(j=0; highlighted.indexOf("$!$")>-1; j++)
{
highlighted = highlighted.replace("$!$", HTMLArray[j]);
}

document.body.innerHTML = highlighted;
}
return;
}

-->
</script>
<style type="text/css">
.highlight { background-color: red; }
</style>
</head>

<body>
Hi everyone, I wonder if you can help me with a small, but irritating bug that I have in my code.
First of all, the code itself (based on a highlight bookmarklet):

<br><br>
This is a selection test that is grouped. This is a selection test that is grouped. This is a selection test that is grouped. Selection group selection grouped selection test test test this is a test of grouped selection. <br><br>
<input type="button" value="Group" onClick="smartContextHighlight('selection test', 'grouped');" />
<input type="button" value="Words" onClick="smartContextHighlight('selection test');" />
<input type="button" value="Group" onClick="smartContextHighlight('is a', 'grouped');" />
<input type="button" value="Words" onClick="smartContextHighlight('is a');" />
<br><br>

</body>
</html>

Many props to this guy: [mikezilla.com...]

Igau

10+ Year Member



 
Msg#: 1170 posted 9:23 pm on Jan 22, 2004 (gmt 0)

Well, I cant make that work on Mozilla Firebird or Internet Explorer 6, so I dont know what's wrong there :/ I also took a look at that website, and the text highlight function works, but once again, I cant remove the highlighting, any ideas why?

TrinkDawg

10+ Year Member



 
Msg#: 1170 posted 9:48 pm on Jan 22, 2004 (gmt 0)

Hi Igau, you need to delete the pipe character () and type a new one. For some reason, the one that gets copied and pasted doesn't work. At least, on my machine it didn't. So, try this code again with that change and it works for me in IE6.

Hope that helps.

Igau

10+ Year Member



 
Msg#: 1170 posted 5:38 pm on Jan 23, 2004 (gmt 0)

Still had no luck with that other code for some reason or other. I've modified mine slightly, and it's working, apart from a single bug, which I cannot figure out. Here's the revised code:


<html>
<head>
<title>Testing Javascript Highlight</title>

<script type="text/javascript">

var spanid = 1;

function smartContextHighlight(text, selectionType) {

function resetHighlights(idText, spanNum) {
var styleHandle = true;
styleHandle = document.getElementById(idText + spanNum);

if (styleHandle) {
styleHandle.style.backgroundColor = "inherit";
}
}

for (var reset = 1; reset <= spanid; reset++) {

resetHighlights('smartContextHighlighted', reset);

}

var dv;

if (selectionType == 'grouped') searchArray = [text];
else searchArray = text.split(" ");

for (var i = 0; i < searchArray.length; i++) {

text = searchArray[i];
if (text == null) return;

function searchWithinNode (node, te, len, colour) {
var pos, skip, spannode, middlebit, endbit, middleclone;
skip = 0;

if (node.nodeType == 3) {
pos=node.data.toUpperCase().indexOf(te);
if (pos>=0) {
spannode = document.createElement("span");
spannode.style.backgroundColor = colour;

var concat_id = "smartContextHighlighted" + spanid;
spanid++;

spannode.setAttribute("id", concat_id);

middlebit = node.splitText(pos);
endbit = middlebit.splitText(len);
middleclone = middlebit.cloneNode(true);
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode,middlebit);
skip=1;
}
}

else if (node.nodeType == 1 && node.childNodes && node.tagName.toUpperCase()!= "SCRIPT" && node.tagName.toUpperCase!= "STYLE") {
for (var child=0; child < node.childNodes.length; ++child) {
child=child+searchWithinNode(node.childNodes[child], te, len, "yellow");
}
}
return skip;
}
searchWithinNode(document.body, text.toUpperCase(), text.length);

}

}

</script>

<body>
This is a selection test. This is a selection test. This is a selection test. Selection selection selection test test test this is a test of selection.<br />
<input type="button" value="'selection test'" onClick="smartContextHighlight('selection test', 'grouped');" />
<input type="button" value="'selection' 'test'" onClick="smartContextHighlight('selection test');" />
<input type="button" value="'is a'" onClick="smartContextHighlight('is a', 'grouped');" />
<input type="button" value="'is' 'a'" onClick="smartContextHighlight('is a');" />

</body>
</html>

I now assign each new <span> an ID, based on a concatenation of a word and number (making each unique). Then I loop through using getElementById and change the properties of that element. I may revise the ways this mechanism works later, I just want to get it working properly first.

If you save my example as an html file and test it, you'll see that the principle works, you can click the buttons left to right, and each one will work. However, once you've done that, highlighting now ONLY works with the 2nd and 4th buttons, the other two appear to do nothing. Any ideas?

HocusPocus

10+ Year Member



 
Msg#: 1170 posted 5:56 pm on Jan 23, 2004 (gmt 0)

I would do away with the spans and go down the createTextRange and TextRange route.

h**p://msdn.microsoft.com/workshop/samples/author/dhtml/overview/cont_08.htm

Igau

10+ Year Member



 
Msg#: 1170 posted 1:09 am on Jan 24, 2004 (gmt 0)

Well, I'm not coding only for IE, and I'm entirely against using propriery coding in general.

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / JavaScript and AJAX
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved