Very strange error caused by html whitespace

孤人 提交于 2020-01-14 09:36:08

问题


I have encountered a very strange bug in Firefox.

I have a javascript function in an external file that works perfectly on regular complexity websites. However I have been putting together a few demonstration examples and come across something odd.

With html formatted like this (in an editor):

<div><p>Q: Where's the rabbit?</p><p class="faq_answer">A: I don't know, honest</p></div>

The Javascript works as expected.

However when like this:

<div>
<p>Q: Where's the rabbit?</p>
<p class="faq_answer">A: I don't know, honest</p>
</div>

It fails at this line:

elementsList[i].parentNode.firstChild.appendChild(finalRender.cloneNode(true));

Why on Earth would formatting of html cause anything at all?


回答1:


It is not a bug. The DOM has not only element nodes, but also text nodes [docs] (among others). In this example:

<div>
<p>Q: Where's the rabbit?</p>

you have at least two text nodes:

  • One between the <div> and the <p>, containing a line-break.
  • One text node inside the <p> element node, containing the text Where's the rabbit?.

Thus, if elementsList[i].parentNode refers to the <div> element,

elementsList[i].parentNode.firstChild

will refer to the first text node.

If you want to get the first element node, use

elementsList[i].parentNode.children[0]

Update: You mentioned Firefox 3.0, and indeed, the children property is not supported in this version.

Afaik the only solution to this is to loop over the children (or traversing them) and test whether it is a text node or not:

var firstChild = elementsList[i].parentNode.firstChild;

// a somehow shorthand loop
while(firstChild.nodeType !== 1 && (firstChild = firstChild.nextSibling));

if(firstChild) {
    // exists and found
}

You might want to put this in an extra function:

function getFirstElementChild(element) {
    var firstChild = null;
    if(element.children) {
        firstChild = element.children[0] || null;
    }
    else {
      firstChild = element.firstChild;
      while(firstChild.nodeType !== 1 && (firstChild = firstChild.nextSibling));
    }
    return firstChild;
}

You can (and should) also consider using a library that abstracts from all that, like jQuery.

It depends on what your code is actually doing, but if you run this method for every node, it would be something like:

$('.faq_answer').prev().append(finalRender.cloneNode(true));

(assuming the p element always comes before the .faq_answer element)

This is the whole code, you wouldn't have to loop over the elements anymore.




回答2:


Because you have a text node between <div> and <p>.

As usual, the assumption of a browser bug is incorrect: this is, instead, a programmer bug!




回答3:


Couldn't one achieve it by using ParentNode.children instead?



来源:https://stackoverflow.com/questions/6572408/very-strange-error-caused-by-html-whitespace

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!