MutationObserver not working

37.2k views Asked by At

Consider the following code:

var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;

var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.target.nodeName);
  });
});

observer.observe(document, {
  attributes: true,
  childList: true,
  characterData: true
});
<div>
  <ol contenteditable oninput="">
    <li>Press enter</li>
  </ol>
</div>

which is a slight modification of this.

Interacting with the jsbin version page does not produce any log. Where am I wrong? Notice that if I substitute line

  observer.observe(document, {

with

  observer.observe(document.querySelector('ol'), {

the script turns on working...

3

There are 3 answers

2
Felix Kling On BEST ANSWER

It doesn't appear to work because you are not mutating anything that you are observing. You are neither changing

  • attributes (attributes: true) of the document node (which is understandable, since document doesn't have attributes)
  • child nodes (childList: true): the only child node of document is the <html> node, and you are not removing or replacing it.
  • character data (characterData: true): you are not changing any Text, Comment, or ProcessingInstruction children of document (also understandable because document cannot have such children).

If you replace the <html> node, you can see that the mutation observer works just as configured.

var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;

var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.target.nodeName);
  });
});

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

document.replaceChild(document.createElement('div'), document.documentElement);


What you are doing is changing the content of the ol element, which is a descendant of document.

If you want to listen to these kind of changes, you have to set subtree to true:

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

More information in the MDN documentation.

var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;

var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.target.nodeName);
  });
});

observer.observe(document, {
  attributes: true,
  childList: true,
  subtree: true,
  characterData: true
});
<div>
  <ol contenteditable oninput="">
    <li>Press enter</li>
  </ol>
</div>

3
Gherkin in God mode On

For anyone using Chrome thats tried the above solutions, try restarting Chrome.

function callback() {
   console.log("mutation occured")
};
console.log("about to run")
const observer = new MutationObserver(callback);
observer.observe(document, { attributes: true, childList: true, subtree: true, characterData: true});

For me the most basic example, logging every possible change with document as the target still wouldn't fire the callback until I restarted Chrome.

2
javed kadgaokar On

Closing the current tab and reopening the url in new tab also does the trick. For my case I had set a breakpoint which had caused chrome to disturb the observer