Firing event on DOM attribute change

72,943

Solution 1

Note: As of 2012, Mutation Events have been removed from the standard and are now deprecated. See other answers or documentation for how to use their replacement, MutationObserver.

You are referring to DOM Mutation Events. There is poor (but improving) browser support for these events. Mutation Events plugin for jQuery might get you some of the way.

Solution 2

How to setup a MutationObserver, mostly copied from MDN but I've added my own comments for clarity.

window.MutationObserver = window.MutationObserver
    || window.WebKitMutationObserver
    || window.MozMutationObserver;
// Find the element that you want to "watch"
var target = document.querySelector('img'),
// create an observer instance
observer = new MutationObserver(function(mutation) {
     /** this is the callback where you
         do what you need to do.
         The argument is an array of MutationRecords where the affected attribute is
         named "attributeName". There is a few other properties in a record
         but I'll let you work it out yourself.
      **/
}),
// configuration of the observer:
config = {
    attributes: true // this is to watch for attribute changes.
};
// pass in the element you wanna watch as well as the options
observer.observe(target, config);
// later, you can stop observing
// observer.disconnect();

Hope this helps.

Solution 3

If you only need something specific then a simple setInterval() will work, by checking the target attribute(s) every few milliseconds:

var imgSrc = null;
setInterval(function () {
   var newImgSrc = $("#myImg").attr("src");
   if (newImgSrc !== imgSrc) {
      imgSrc = newImgSrc;
      $("#myImg").trigger("srcChange");
   }
}, 50);

Then bind to the custom "srcChange" event:

$("#myImg").bind("srcChange", function () {....});

Solution 4

There is no native dom changed event you can hook into.

Good article here which tries to provide a solution in the form of a jquery plugin.

Code from article

$.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);
        }
    } }
Share:
72,943
ts.
Author by

ts.

...

Updated on July 08, 2022

Comments

  • ts.
    ts. almost 2 years

    Is there any way to trigger event (may be custom) on attribute change?

    Let's say, when IMG src is changed or DIV's innerHtml?

  • Tim Down
    Tim Down over 13 years
    DOM mutation events are actually reasonably well supported among browsers. It's just that IE doesn't support them at all (although IE 9 will).
  • Alba Mendez
    Alba Mendez almost 12 years
    @TimDown if it comes to IE, it's not a strange thing.
  • EricG
    EricG over 11 years
    usage of intervals for this is really poor in my opinion (Yes it is 'a' way).
  • DanielB
    DanielB almost 11 years
    These are now deprecated in favor of MutationObserver, developer.mozilla.org/en-US/docs/Web/API/MutationObserver
  • Xaxis
    Xaxis about 10 years
    The usage of intervals is appropriate in limited quantities especially where performance won't become an issue. I haven't ran any bench tests but I know from experience I can manipulate all kinds of properties in the DOM in a fast interval without noticing performance degradation.
  • Daniel Katz
    Daniel Katz over 9 years
    For me this answer is too succinct. I couldn't find out how to use the plugin for jquery. But the answer of Mats is simple and there's no need for extra plugin.
  • posit labs
    posit labs about 9 years
    There are pretty huge performance implications with this approach.
  • Stranded Kid
    Stranded Kid almost 8 years
    Works like a charm in Chrome. Really useful!
  • Richardissimo
    Richardissimo about 6 years
    "Good article" link broken :(
  • kmuenkel
    kmuenkel about 4 years
    The MutationObserver may be a more elegant solution, but what if the element in question hasn't been generated yet? And for debugging purposes, I think it's ok to let things temporarily be a little messy. My use-case at the moment is trying to chase down what's responsible for erroneously changing a value in a Legacy system, so this solution actually suits me better than the cleaner one.