Reputation: 4701
I'm creating some functions to highlight words on a page. This will be done wrapping span tags around the given words. I've completed this task but will explain a little more.
The way the code works is to take the innerHTML when the page first loads, and store this in memory (so I have a copy of the original content).
I then take a copy of the innerHTML (called copyInnerHtml) - I then find the search words on copyInnerHtml, and wrap them with <span id="find-iteration">
(where iteration is a unique number, such as find-0, find-1, find-2 etc) tags and replace the contents of the page with copyInnerHtml. Then, when the user re-hits the search button, I first revert the page back to the original innerHTML content, and then continue as above. This works well.
How to do I find text (website copy) only words and note words used as values in HTML elements/attributes.
Example, Consider the following code
<div class="search">This is the search box</div>
Now, I want to perform a search for the word "search". The issue is, it will find it twice.
Without using regular expressions, and only using JavaScript (no jQuery please), how can I detect if the string is part of the HTML tag or not?
This JSFIDDLE should make things clearer in regards to what I've done
Now, you'll hopefully note the following line in the fiddle
<p class="changeMe"> </p><p> </p>
Please update this to
<p class="find"> </p><p> </p>
And you will see the code breaks. This is what I mean, when I search for a word (in the case of the JSFIDDLE, the word 'find') then I only want to search by website copy.
Upvotes: 0
Views: 1001
Reputation: 358
as you know, you have to process the whole (or part of) the DOM. While doing this, you have to cross-check each tagName against a blacklist of tags you do not want to process.
Here is a small example of how this might be done in vanilla javascript:
var excludeElements = ['script', 'style', 'a', 'form', 'iframe', 'canvas'];
var markText = function(textToHighlight) {
walk(document.body, textToHighlight, function(node, match, offset) {
var abbrevNode = document.createElement("span");
abbrevNode.appendChild(document.createTextNode(textToHighlight));
abbrevNode.className="someClass";
});
}
var walk = function(node, textToHighlight, callback) {
var child = node.firstChild;
while (child) {
switch (child.nodeType) {
case 1:
if (excludeElements.indexOf(child.tagName.toLowerCase()) > -1)
break;
walk(child, textToHighlight, callback);
break;
case 3:
var bk = 0;
child.data.replace(textToHighlight, function(all) {
var args = [].slice.call(arguments),
offset = args[args.length - 2],
newTextNode = child.splitText(offset+bk), tag;
bk -= child.data.length + all.length;
newTextNode.data = newTextNode.data.substr(all.length);
tag = callback.apply(window, [child].concat(args));
child.parentNode.insertBefore(tag, newTextNode);
child = newTextNode;
});
break;
}
child = child.nextSibling;
}
return node;
};
Upvotes: 2