22

I recently came across this awesome MutationObserver feature which sort of keep tracks of the changes on any dom element. I used the code that was shown on the mozilla developer network, but can't seem to make it run. This is the code I used (link):

// create an observer instance var target = document.querySelector('#something'); console.log(target); var observer = new WebKitMutationObserver(function(mutations) { mutations.forEach(function(mutation) { console.log("Success"); //$('#log').text('input text changed: "' + target.text() + '"'); //console.log(mutation, mutation.type); }); }); observer.observe(target, { attributes: true, childList: true, characterData: true }); //observer.disconnect(); - to stop observing // test case setInterval(function(){ document.querySelector('#something').innerHTML = Math.random(); },1000); 

The above code doesn't seems to work. However if I modify the same code with a bit of jQuery, everything seems to work just fine (Demo here). Is there something I'm missing from the docs or I'm just misinterpreting the observer feature.

0

4 Answers 4

17

You need subtree: true

http://jsfiddle.net/6Jajs/1/

The inner text would normally be a child text() element in the DOM. Without the subtree it will only watch the element itself.

There is possible confusion surrounding "characterData" (https://developer.mozilla.org/en-US/docs/Web/API/CharacterData), but it seems that that applies only to nodes that directly contain text. The DOM is structured so that most markup elements contain mixed type which optionally include a child text node (which in turn would implement characterData, but would be a child of the targeted node).

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the clarification. I should do more research before jumping to questioning. :)
It's also an argument to stick with tools like jQuery even as native JavaScript and the DOM API have become more powerful. The underlying API doesn't (and IMO shouldn't) hide these types of technical details, so there's benefit to an additional layer of usability abstraction.
4

Refer to the documentation for the observe function parameters.

Watching for text or input changes

Use characterData: true:

const target = document.querySelector('#text'); const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { console.log(mutation.type); }); }); const config = { characterData: true, subtree: true, }; observer.observe(target, config); // Cleanup: observer.disconnect();
<div id="text" contenteditable="true">characterData:true</div>

Watching for children being added to the node

Use childList:true, and subtree: true if you "want to extend monitoring to the entire subtree of nodes rooted at target":

const target = document.querySelector('#text'); const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { console.log(mutation.type); }); }); const config = { childList: true, subtree: true, }; observer.observe(target, config);
<div id="text" contenteditable="true">characterData:true</div> <button onclick="document.getElementById('text').append('text')"> append </button>

Watching for DOM attribute changes

Use attributes: true:

const target = document.querySelector('#text'); const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { console.log(mutation.type); }); }); const config = { attributes: true, }; observer.observe(target, config);
<div id="text" contenteditable="true">characterData:true</div> <button onclick="document.getElementById('text').setAttribute('data-prop','text')"> set attribute </button>

Comments

2

Mutation Observer bacic example :

The MutationObserver interface provides the ability to watch for changes being made to the DOM tree. It is designed as a replacement for the older Mutation Events feature, which was part of the DOM3 Events specification.

 let demo = document.querySelector(".demo"); function callback(mutationList, observer) { for (let list of mutationList) { // console.log(list.type) -> attribute | child (tag) change detect list.addedNodes[0].nodeValue = "still change the value"; console.log("change is detected in tag"); // list.target.innerHTML = "java"; } } let mo = new MutationObserver(callback); //Element to detect changes mo.observe(demo, { childList: true, attributes: true, subtree: true }); //Making changes so that mutation observer can detect change setTimeout(() => { demo.children[1].innerHTML = "javascript"; }, 1000);
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div class="demo"> <h2>HELLO</h2> <p>World</p> </div> </body> </html>

Comments

1

Simple Example:

<div contentEditable id="myID">MUST EDIT NOW</div> <script> let x = new MutationObserver( function(){ alert('DETECTED'); } ); x.observe( myID , {subtree:true,characterData:true} ); </script> 

See Example Live: https://jsfiddle.net/mbo9eLt5/

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.