Essentially I want to have a script execute when the contents of a DIV
change. Since the scripts are separate (content script in the Chrome extension & webpage script), I need a way simply observe changes in DOM state. I could set up polling but that seems sloppy.
“MutationObserver” is a Web API provided by modern browsers for detecting changes in the DOM. By using this API you can listen to changes in DOM, like added or removed nodes, attribute changes or changes in the text content of text nodes and make changes. Web apps are getting complex on the client-side nowadays.
jQuery provides a number of methods to manipulate DOM in efficient way. You do not need to write big and complex code to set or get the content of any HTML element.
jQuery is a wrapper that normalizes DOM manipulation in a way that works consistently in every major browser. It's fully reasonable for it to perform 25x slower than direct DOM manipulation. The performance loss is a tradeoff to have concise code.
When you update the DOM, the reflow and repaint happen. Every time the DOM changes, the browser needs to recalculate the CSS, do a layout and repaint the web page. React doesn't really do anything new. It's just a strategic move.
For a long time, DOM3 mutation events were the best available solution, but they have been deprecated for performance reasons. DOM4 Mutation Observers are the replacement for deprecated DOM3 mutation events. They are currently implemented in modern browsers as MutationObserver
(or as the vendor-prefixed WebKitMutationObserver
in old versions of Chrome):
MutationObserver = window.MutationObserver || window.WebKitMutationObserver; var observer = new MutationObserver(function(mutations, observer) { // fired when a mutation occurs console.log(mutations, observer); // ... }); // define what element should be observed by the observer // and what types of mutations trigger the callback observer.observe(document, { subtree: true, attributes: true //... });
This example listens for DOM changes on document
and its entire subtree, and it will fire on changes to element attributes as well as structural changes. The draft spec has a full list of valid mutation listener properties:
childList
- Set to
true
if mutations to target's children are to be observed.attributes
- Set to
true
if mutations to target's attributes are to be observed.characterData
- Set to
true
if mutations to target's data are to be observed.subtree
- Set to
true
if mutations to not just target, but also target's descendants are to be observed.attributeOldValue
- Set to
true
ifattributes
is set to true and target's attribute value before the mutation needs to be recorded.characterDataOldValue
- Set to
true
ifcharacterData
is set to true and target's data before the mutation needs to be recorded.attributeFilter
- Set to a list of attribute local names (without namespace) if not all attribute mutations need to be observed.
(This list is current as of April 2014; you may check the specification for any changes.)
Edit
This answer is now deprecated. See the answer by apsillers.
Since this is for a Chrome extension, you might as well use the standard DOM event - DOMSubtreeModified
. See the support for this event across browsers. It has been supported in Chrome since 1.0.
$("#someDiv").bind("DOMSubtreeModified", function() { alert("tree changed"); });
See a working example here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With