Firing event on DOM attribute change
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);
}
} }
Comments
-
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 over 13 yearsDOM 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 almost 12 years@TimDown if it comes to IE, it's not a strange thing.
-
EricG over 11 yearsusage of intervals for this is really poor in my opinion (Yes it is 'a' way).
-
DanielB almost 11 yearsThese are now deprecated in favor of
MutationObserver
, developer.mozilla.org/en-US/docs/Web/API/MutationObserver -
Xaxis about 10 yearsThe 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 over 9 yearsFor 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 about 9 yearsThere are pretty huge performance implications with this approach.
-
Stranded Kid almost 8 yearsWorks like a charm in Chrome. Really useful!
-
Richardissimo about 6 years"Good article" link broken :(
-
kmuenkel about 4 yearsThe 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.