开发者

JavaScript Node.replaceChild() doesn't count new child's innerHtml

开发者 https://www.devze.com 2023-02-01 06:19 出处:网络
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, containing Node.TEXT_NODE as one or more of it\'s chil

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, containing Node.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.

So I decided to make replacements in text nodes only. But text nodes can't contain a HTML tag, so I had to wrap them with <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.

If I uncomment this code:

//          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.

Looks like it doesn't take new 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.

0

精彩评论

暂无评论...
验证码 换一张
取 消