Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can jQuery selectors be used with DOM mutation observers?

HTML5 includes a concept of "mutation observers" to monitor changes to the browser's DOM.

Your observer callback will be passed data which looks a lot like DOM tree snippets. I don't know if they are exactly this or how they work really.

But when you are writing code to interact with a 3rd party site over which you have no control, say with a Greasemonkey script or Google Chrome user script, you have to inspect the tree of elements passed in to find which information is relevant to you.

This is much simpler with selectors, just like working with any DOM, than walking the tree manually, especially for cross-browser code.

Is there a way to use jQuery selectors with the data passed to HTML5 mutation observer callbacks?

like image 451
hippietrail Avatar asked Sep 26 '12 07:09

hippietrail


People also ask

Is mutation observer deprecated?

Note: Mutation Events (W3C DOM Level 3 Events) have been deprecated in favor of Mutation Observers (W3C DOM4).

When would you use a mutation observer?

MutationObserver can react to changes in DOM – attributes, text content and adding/removing elements. We can use it to track changes introduced by other parts of our code, as well as to integrate with third-party scripts. MutationObserver can track any changes.

How does mutation observer work?

MutationObserver is a Web API provided by modern browsers for detecting changes in the DOM. With this API one can listen to newly added or removed nodes, attribute changes or changes in the text content of text nodes.

What are mutation observers in Javascript?

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.


2 Answers

Yes, you can use jQuery selectors on data returned to mutation observer callbacks.

See this jsFiddle.

Suppose you had HTML like so and you set an observer, like so:

var targetNodes = $(".myclass");
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
var myObserver = new MutationObserver(mutationHandler);
var obsConfig = {
  childList: true,
  characterData: true,
  attributes: true,
  subtree: true
};

//--- Add a target node to the observer. Can only add one node at a time.
targetNodes.each(function() {
  myObserver.observe(this, obsConfig);
});

function mutationHandler(mutationRecords) {
  console.info("mutationHandler:");

  mutationRecords.forEach(function(mutation) {
    console.log(mutation.type);

    if (typeof mutation.removedNodes == "object") {
      var jq = $(mutation.removedNodes);
      console.log(jq);
      console.log(jq.is("span.myclass2"));
      console.log(jq.find("span"));
    }
  });
}
setTimeout(function() {  
  $(".myclass").html ("[censored!]");
},1000)  
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<span class="myclass"> 
  <span class="myclass2">My 
    <span class="boldly">vastly</span> improved
  </span> 
  text.
</span>

You'll note that we can jQuery on the mutation.removedNodes.


If you then run $(".myclass").html ("[censored!]"); from the console you will get this from Chrome and Firefox:

mutationHandler:
childList
jQuery(<TextNode textContent="\n ">, span.myclass2, <TextNode textContent="\n text.\n ">)
true
jQuery(span.boldly)

which shows that you can use normal jQuery selection methods on the returned node sets.

like image 134
Brock Adams Avatar answered Sep 23 '22 20:09

Brock Adams


I don't have any personal code snippets for this one, but I have three resources that may help:

  • Mutabor Github Repository
  • Article + JQuery Utility for Mutators
  • "jquery-mutation-summary" - extension of mutation-summary ( probably the best out of these three )

Example from link #3 'jquery-mutation-summary' library:

// Use document to listen to all events on the page (you might want to be more specific)
var $observerSummaryRoot = $(document);

// Simplest callback, just logging to the console
function callback(summaries){
    console.log(summaries);
}

// Connect mutation-summary
$observerSummaryRoot.mutationSummary("connect", callback, [{ all: true }]);

// Do something to trigger mutationSummary
$("<a />", { href: "http://joelpurra.github.com/jquery-mutation-summary"}).text("Go to the jquery-mutation-summary website").appendTo("body");

// Disconnect when done listening
$observerSummaryRoot.mutationSummary("disconnect");
like image 7
Vita Pluvia Avatar answered Sep 21 '22 20:09

Vita Pluvia