Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Watching for DOM changes, the elegant way

Tags:

html

jquery

dom

I need to watch for an attribute change on any of the children of a specific DOM element. So far, I have been using mutation events.

The problem was - they were buggy: e.g. under Chromium, DOMAttrModified was not fired but DOMSubtreeModified was. The problem was easy to solve: because according to the specification, DOMSubtreeModified is fired if any of the other events is fired, so I just listened to DOMSubtreeModified.

Anyway, Chromium, in the recent versions, stopped firing anything if an attribute has been modified.

The new Mutation Observer API, however, works flawlessly.

Until now, I only need to fire a callback upon ANY change of the subtree of a specific element - simply because nothing else is supposed to change - so I solved my problem by just using mutation events & mutation observer (when available) in the same piece of code.

However, now I need to do more powerful filtering of the events (e.g. on new node, on removed node) - so is there a library, possibly a jQuery plug-in, that would allow me to elegantly use both of these APIs - MutationObserver if available and mutation events as a fallback, with the ability to filter for specific event types (e.g. element added, attribute changed).

E.g.

$("#test").watch({onNewElement: 1}, function(newElement){})
$("#test").watch({onNewAttribute: 1}, function(modifiedElement) {})

Or without jQuery

watchChanges("#test", {onNewElement: 1}, function(newElement){})
watchChanges("#test", {onNewAttribute: 1}, function(modifiedElement){})
like image 233
Ivo Avatar asked Jul 15 '12 11:07

Ivo


People also ask

How do you observe DOM changes?

observe() The MutationObserver method observe() configures the MutationObserver callback to begin receiving notifications of changes to the DOM that match the given options. Depending on the configuration, the observer may watch a single Node in the DOM tree, or that node and some or all of its descendant nodes.

How do Mutation observers 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 is Mutation observer 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.

How to use Mutation observer in jquery?

For example, to monitor an element we can now write: // The node to be monitored var target = $( "#content" )[0]; // Create an observer instance var observer = new MutationObserver(function( mutations ) { mutations. forEach(function( mutation ) { var newNodes = mutation. addedNodes; // DOM NodeList if( newNodes !==


2 Answers

Would this work?

http://darcyclarke.me/development/detect-attribute-changes-with-jquery/

$.fn.watch = function(props, callback, timeout){     if(!timeout)         timeout = 10;     return this.each(function(){         var el      = $(this),             func    = function(){ __check.call(this, el) },             data    = { props:  props.split(","),                         func:   callback,                         vals:   [] };         $.each(data.props, function(i) { data.vals[i] = el.css(data.props[i]); });         el.data(data);         if (typeof (this.onpropertychange) == "object"){             el.bind("propertychange", callback);         } else if ($.browser.mozilla){             el.bind("DOMAttrModified", callback);         } else {             setInterval(func, timeout);         }     });     function __check(el) {         var data    = el.data(),             changed = false,             temp    = "";         for(var i=0;i < data.props.length; i++) {             temp = el.css(data.props[i]);             if(data.vals[i] != temp){                 data.vals[i] = temp;                 changed = true;                 break;             }         }         if(changed && data.func) {             data.func.call(el, data);         }     } } 
like image 179
Coffee Bite Avatar answered Sep 30 '22 17:09

Coffee Bite


For efficient DOM monitoring with jQuery, you might take a look at the jQuery Behavior Plugin (Disclaimer: I'm the author) which utilizes a optimized version of Live Query. I'm using it in several products for 3 year now, without any problems.

Edit: Listening for attribute changes would work like this:

$.behavior({
    'div:first': {
        'changeAttr': function (event, data) {
            console.log('Attribute "' +  data.attribute + '" changed from "' + data.from + '" to "' + data.to + '"');
        }
    }
});

$('div:first').attr('foo', 'bar');
like image 42
FloHimself Avatar answered Sep 30 '22 17:09

FloHimself