An element has a javascript style
object which contains the different names and values of css styles. I'd like to trigger a function every time this object changes without use of polling. Is there any way to do this in a way that is cross-browser compatible and would work reliably with third party code (because let's say you're providing a drop-in script)? Binding a javascript event like DOMAttrModified
or DOMSubtreeModified
won't suffice because they don't work in Chrome.
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.
The actual answer is "use mutation observers" (as outlined in this question: Determining if a HTML element has been added to the DOM dynamically), however support (specifically on IE) is limited (http://caniuse.com/mutationobserver). So the actual ACTUAL answer is "Use mutation observers....
The easiest way to access a single element in the DOM is by its unique ID. You can get an element by ID with the getElementById() method of the document object. In the Console, get the element and assign it to the demoId variable. Logging demoId to the console will return our entire HTML element.
Edit 4: Live Demo
$(function() { $('#toggleColor').on('click', function() { $(this).toggleClass('darkblue'); }).attrchange({ trackValues: true, callback: function(event) { $(this).html("<ul><li><span>Attribute Name: </span>" + event.attributeName + "</li><li><span>Old Value: </span>" + event.oldValue + "</li><li><span>New Value: </span>" + event.newValue + "</li></ul>"); } }); });
body { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 12px; } #toggleColor { height: 70px; width: 300px; padding: 5px; border: 1px solid #c2c2c2; background-color: #DBEAF9; } #toggleColor span { font-weight: bold; } #toggleColor.darkblue { background-color: #1A9ADA; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script src="http://meetselva.github.io/attrchange/javascripts/attrchange.js"></script> <p>Click below div to toggle class darkblue.</p> <div id="toggleColor"></div>
Edit 3: I have put all this together as a plugin that can be downloaded from git attrchange and here is the demo page.
Edit 2:
Edit 1:
Thanks to @benvie for his feedback.
DEMO: http://jsfiddle.net/zFVyv/10/ (Tested in FF 12, Chrome 19 and IE 7.)
$(function() { (function($) { var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; function isDOMAttrModifiedSupported() { var p = document.createElement('p'); var flag = false; if (p.addEventListener) p.addEventListener('DOMAttrModified', function() { flag = true }, false); else if (p.attachEvent) p.attachEvent('onDOMAttrModified', function() { flag = true }); else return false; p.setAttribute('id', 'target'); return flag; } $.fn.attrchange = function(callback) { if (MutationObserver) { var options = { subtree: false, attributes: true }; var observer = new MutationObserver(function(mutations) { mutations.forEach(function(e) { callback.call(e.target, e.attributeName); }); }); return this.each(function() { observer.observe(this, options); }); } else if (isDOMAttrModifiedSupported()) { return this.on('DOMAttrModified', function(e) { callback.call(this, e.attrName); }); } else if ('onpropertychange' in document.body) { return this.on('propertychange', function(e) { callback.call(this, window.event.propertyName); }); } } })(jQuery); $('.test').attrchange(function(attrName) { alert('Attribute: ' + attrName + ' modified '); }).css('height', 100); });
Ref:
Mutation Observers is the proposed replacement for mutation events in DOM4. They are expected to be included in Firefox 14 and Chrome 18
Browser Support:
onpropertychange
- is supported in IE (tested in IE 7)
DOMAttrModified
- is supported in IE 9, FF and Opera
MutationObservers
- is very new and it worked fine in Chrome 18. Not sure how far it is supported and yet to be tested in Safari.
Thanks @benvie on adding info about WebkitMutationObserver
EDIT2:
If you still want to use mutation observer
, use this library: mutation-summary
As I said in my answer below and thanks to Vega for his comment, using things such as object.watch
or mutation observers
are not recommended for using in large apps. this is actual quote from MDN:
Generally you should avoid using
watch()
andunwatch()
when possible. These two methods are implemented only in Gecko, and they're intended primarily for debugging use. In addition, using watchpoints has a serious negative impact on performance, which is especially true when used on global objects, such as window. You can usually use setters and getters or proxies instead. See Compatibility for details.Warning
So if cross-browser compatibility is in your check list, Again, I highly suggest overriding setter
s and getter
s of style
object.
object.watch
and have these in mind for a cross-browser solution: You may override getter
and setter
methods of element's style
object too.
There is a jQuery plugin available for this, jQuery watch
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