While creating a Firefox addon, I've run into a weird problem.
I have an array of nodes, returned by some iterator. Iterator returns only nodes, containingNode.TEXT_NODE
as one or more of it's children. The script runs on page load.
I have to find some text in that nodes by regexp and surround it with a SPAN
tag.
//beginning skipped
var node = nodeList[i];
var node_html = node.innerHTML;
var node_content = node.textContent;
if(node_content.length > 1){
var new_str = "<SPAN class='bar'>" + foo + "</SPAN>";
var regexp = new RegExp( foo , 'g' );
node_html = node_html.replace(regexp, new_str);
node.innerHTML = node_html;
}
Basic version looked like th开发者_StackOverflowis, and it worked except one issue - node.innerHTML
could contain attributes, event handlers, that could also contain foo
, that should not be surrounded with <span>
tags.
<div>
. Like this:
var node = nodeList[i];
for(var j=0; j<node.childNodes.length; j++){
var child = node.childNodes[j];
var child_content = child.textContent;
if(child.nodeType == Node.TEXT_NODE && child_content.length >1){
var newChild = document.createElement('div');
// var newTextNode = document.createTextNode(child_content);
// newChild.appendChild(newTextNode);
var new_html = child_content;
var new_str = "<SPAN class='bar'>" + foo + "</SPAN>";
var regexp = new RegExp( foo , 'g' );
new_html = new_html.replace(regexp, new_str);
newChild.innerHTML = new_html;
alert(newChild.innerHTML);
node.replaceChild(newChild, child);
}
}
In this case, alert(newChild.innerHTML);
shows right html. But after the page is rendered, all <div>
s created are empty! I'm puzzled.
// var newTextNode = document.createTextNode(child_content);
// newChild.appendChild(newTextNode);
alert
also shows things right, and <div>
s are filled with text (textNode adding works ok) , but again without <span>
s. And another funny thing is that I can't highlight that new <div>
s' content with a mouse in browser.
innerHTML
into account, and I can't understand why.
Do I do something wrong? (I certainly do, but what? Or, is that a FF bug/feature?)Since you are in Firefox you can use fun stuff like TreeWalker and Range. You may even be able to get rid of the code that gives you the initial array of nodes.
var walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null, false);
var range = document.createRange();
var wrapper = document.createElement('span');
wrapper.className = "wrapper";
var node;
var re = /^wrap me$/;
while (node = walker.nextNode()) {
if (re.test(node.textContent)) {
range.selectNode(node);
range.surroundContents(wrapper.cloneNode(true));
}
}
JSBin
You could tweak this so only part of the text node is wrapped by setting the range differently and TreeWalker can be filtered more.
Range / TreeWalker
That code is really odd; why are those three lines outside of the if
statement?
I think it should look something like this:
var node = nodeList[i];
for(var j=0; j<node.childNodes.length; j++){
var child = node.childNodes[j];
var child_content = child.textContent;
if(child.nodeType == Node.TEXT_NODE && child_content.length >1){
var newChild = document.createElement('div');
newChild.innerHTML = '<span class="bar">' + child_content + '</span>';
node.replaceChild(newChild, child);
}
Now I can't figure out what was going on with that regex and the replacement stuff; it makes no sense to me in the code you've posted.
精彩评论