Mutation Observer does not detect nodes added through innerHTML, appendChild
Asked Answered
G

1

5

When we try to add nested nodes in DOM using appendChild or innerHTML, the nested nodes do not come in the addedNodes of a mutation.

Initial HTML setUp:

<html>
    <body>
        <div id="container">
        </div>
    </body>
</html>

Here is my Mutation Observer code:

var observer = new MutationObserver(function(mutations) {
  for (var i = 0; i < mutations.length; i++) {
    var mutation = mutations[i];
    switch(mutation.type) {
      case 'childList':
        console.log(mutation.addedNodes);
      break;
      default:

    }
  }
});

observer.observe(document, {
    childList: true,
    subtree: true,
    attributes: true,
    characterData: true
});

If I now do appendChild with a nested img node in a div,

var img = document.createElement('img');
img.setAttribute("src", "http://img.zohostatic.com/discussions/v1/images/defaultPhoto.png");
var div = document.createElement('div');
div.appendChild(img);
var container = document.getElementById("container");
container.appendChild(div);

The Mutation Observer only logs the div which is appended to the container, but does not log the img as an addedNode in mutation.

Here is a working JSFiddle: https://jsfiddle.net/aedhefhn/

Is there a workaround for this?

Gird answered 5/2, 2018 at 19:7 Comment(0)
P
5

That is the expected behavior. The div was all that was appended, it just happened to have some children. You can certainly walk through its child nodes yourself from .addedNodes though. .addedNodes is just an array of nodes, so you can go through each item recursively to get all the children.

Pacemaker answered 5/2, 2018 at 19:40 Comment(6)
I agree. But, if instead we have a DOM structure with <div> <img src=""></img> </div>, why does Mutation Observer has image in the addedNodes? Shouldn't it behave in the same way. Because, either programatically or not, the DOM looks the sameGird
The objective of MutationObserver is to list mutation operations that were performed, not explicitly track everything that was added. Your observer is listening to the subtree of document. The only mutation performed on the document was appending div. When the image was appended to the div, the div wasn't attached, so there was no mutation observer attached to div at the time that would have picked up the append operation for the image.Pacemaker
I'm using MutationObserver in a summernote editing program, but it does not fire for cuts or pastes. For keyboard events it will fire. So for cuts and pastes, I'm polling the DOM to look for a change when a cut or paste occurs. It would be convenient to have an "after-paste-completed event", but as there is none, I hoped MutationObserver would catch that. Alas, no.Dowzall
@DennisH Definitely surprised to hear that, got a reproduction? I'd definitely expect it to work in that case tooPacemaker
Just found out. Summernote is wrapping the whole document in a <p> tag for some reason. I just found out when I couldn't get a nodeList.forEach to see the change even when polling the DOM as a whole detected one. I have to remove that pesky <p> tag and it should be fine. It was working ok before. I'm trying to use multiple summernotes and changed from <div id='summernote'> to <div class='summernote active'> and I think that's when the trouble started...Dowzall
Update: Getting rid of the <p> tag isn't the solution. Writing accurate looping code to parse through the child nodes IS the solution!Dowzall

© 2022 - 2024 — McMap. All rights reserved.