4

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?

skjindal93
  • 706
  • 1
  • 16
  • 34

1 Answers1

4

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.

loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • I agree. But, if instead we have a DOM structure with
    , 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 same
    – skjindal93 Feb 06 '18 at 08:00
  • 1
    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. – loganfsmyth Feb 06 '18 at 16:38
  • 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. – Dennis H Feb 19 '23 at 03:18
  • @DennisH Definitely surprised to hear that, got a reproduction? I'd definitely expect it to work in that case too – loganfsmyth Feb 19 '23 at 03:38
  • Just found out. Summernote is wrapping the whole document in a

    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

    tag and it should be fine. It was working ok before. I'm trying to use multiple summernotes and changed from

    to
    and I think that's when the trouble started...
    – Dennis H Feb 19 '23 at 03:47
  • Update: Getting rid of the

    tag isn't the solution. Writing accurate looping code to parse through the child nodes IS the solution!

    – Dennis H Feb 19 '23 at 04:05