最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Removing an element through the parentNode.removeChild throws a DOM Exception 8 - Stack Overflow

programmeradmin3浏览0评论

I have code which is roughly as follows (I removed some parts, as they are irrelevant):

Library.focus = function(event) {
    var element, paragraph;

    element = event.srcElement;

    paragraph = document.createElement("p");
    paragraph.innerText = element.innerText;

    element.parentNode.insertBefore(paragraph, element);        // Line #1
    element.parentNode.removeChild(element);                    // Line #2
};

The issue I have, is that the last call which I've numbered as line #2 throws this:

Uncaught Error: NOT_FOUND_ERR: DOM Exception 8

Note that the previous line #1 works fine, and inserts the paragraph node before it. Element is an existing element, and both element.parentNode and element.parentNode.removeChild exist as well.

I find this illogical, as element is by definition a child of its parentNode. Maybe StackOverflow will be able to help me out, here?

I have code which is roughly as follows (I removed some parts, as they are irrelevant):

Library.focus = function(event) {
    var element, paragraph;

    element = event.srcElement;

    paragraph = document.createElement("p");
    paragraph.innerText = element.innerText;

    element.parentNode.insertBefore(paragraph, element);        // Line #1
    element.parentNode.removeChild(element);                    // Line #2
};

The issue I have, is that the last call which I've numbered as line #2 throws this:

Uncaught Error: NOT_FOUND_ERR: DOM Exception 8

Note that the previous line #1 works fine, and inserts the paragraph node before it. Element is an existing element, and both element.parentNode and element.parentNode.removeChild exist as well.

I find this illogical, as element is by definition a child of its parentNode. Maybe StackOverflow will be able to help me out, here?

Share Improve this question edited Mar 4, 2013 at 4:03 Josh Unger 7,1637 gold badges37 silver badges55 bronze badges asked Jul 22, 2012 at 12:27 user697108user697108 3,6513 gold badges21 silver badges14 bronze badges 5
  • i dont think element = event.srcElement; is returning what you are expecting, so first console.log(element); after, element = event.srcElement; and let us know what it is returning. – Shreedhar Commented Jul 22, 2012 at 12:38
  • 1 What is the Library? Because when I tried "what I think it is", it worked? – Alvin Wong Commented Jul 22, 2012 at 12:40
  • @shreedhar It does return what I'm expecting. It's an h1 with contentEditable (hence the focus event). – user697108 Commented Jul 22, 2012 at 12:41
  • Both "srcElement" and "innerText" are Internet Explorer things that won't work in Firefox and (possibly) WebKit. – Pointy Commented Jul 22, 2012 at 12:41
  • @pointy I'm working in Chrome, so it isn't an issue (they exist and work fine in Webkit). – user697108 Commented Jul 22, 2012 at 12:46
Add a ment  | 

3 Answers 3

Reset to default 8

From mdn docs:

If child is actually not a child of the element node, the method throws an exception. This will also happen if child was in fact a child of element at the time of the call, but was removed by an event handler invoked in the course of trying to remove the element (eg, blur.)

I can reproduce this error in jsfiddle

Basically, you focus the element, which triggers a remove, which triggers a blur, which moves the element, which makes the element not the parent anymore.

If you're trying to modify, in an onblur handler, the same node you're trying to remove in another handler (eg onfocus, keydown etc) then the first call to removeChild will fire the onblur handler before actually removing the node. If the onblur handler then modifies the node so that its parent changes, control will return from the onblur handler to the removeChild call in your onfocus handler which will then try to remove the node and fail with the exception you describe.

Any amount of checking for the presence of the child before calling removeChild in your onfocus handler will be fruitless, since those checks will happen before the onblur handler is triggered.

Apart from re-arranging your event handling and node modifications, your best bet is probably to just handle the exception in a try catch block.

The following code will show how the onblur event handler runs before removeChild in onfocus actually removes the child. It is also on jsfiddle

html

<div id="iParent">
    <input id="i">
</div>

js

var input = document.querySelector("#i"),
inputParent = document.querySelector('#iParent');

input.onblur = function() {
    console.log('onblur : input ' + (input.parentNode ? 'has' : 'doesnt have') 
            + ' a parent BEFORE delete');
    try {
        inputParent.removeChild(input);
    } catch (err) {
        console.log('onblur : removeChild failed, input ' 
                + (input.parentNode ? 'has' : 'doesnt have') + ' a parent');
        return false;
    }
    console.log('onblur : child removed');
};

input.onfocus = function() {
    console.log('onfocus : input ' + (input.parentNode ? 'has' : 'doesnt have') 
            + ' a parent BEFORE delete');
    try {
        inputParent.removeChild(input);
    } catch (err) {
        console.log('onfocus : removeChild failed, input ' 
                + (input.parentNode ? 'has' : 'doesnt have') + ' a parent');
        return false;
    }
    console.log('onfocus : child removed');
};​

Console output after focusing on the input field will be

onfocus : input has a parent BEFORE delete
onblur : input has a parent BEFORE delete
onblur : child removed
onfocus : removeChild failed, input doesnt have a parent 

Dont pass the event as parameter for Library.focus function. it will work.

Library.focus = function() {
    var element, paragraph;

    element = event.srcElement;

    paragraph = document.createElement("p");
    paragraph.innerText = element.innerText;

    element.parentNode.insertBefore(paragraph, element);        // Line #1
    element.parentNode.removeChild(element);                    // Line #2
};
发布评论

评论列表(0)

  1. 暂无评论