Is it possible to listen to a “style change” event?

Is it possible to listen to a “style change” event?

Is it possible to create an event listener in jQuery that can be bound to any style changes? For example, if I want to “do” something when an element changes dimensions, or any other changes in the style attribute I could do:
$(‘div’).bind(‘style’, function() {
console.log($(this).css(‘height’));
});

$(‘div’).height(100); // yields ‘100’

It would be really useful.
Any ideas?
UPDATE
Sorry for answering this myself, but I wrote a neat solution that might fit someone else:
(function() {
var ev = new $.Event(‘style’),
orig = $.fn.css;
$.fn.css = function() {
$(this).trigger(ev);
return orig.apply(this, arguments);
}
})();

This will temporary override the internal prototype.css method and the redefine it with a trigger at the end. So it works like this:
$(‘p’).bind(‘style’, function(e) {
console.log( $(this).attr(‘style’) );
});

$(‘p’).width(100);
$(‘p’).css(‘color’,’red’);

Solutions/Answers:

Solution 1:

Since jQuery is open-source, I would guess that you could tweak the css function to call a function of your choice every time it is invoked (passing the jQuery object). Of course, you’ll want to scour the jQuery code to make sure there is nothing else it uses internally to set CSS properties. Ideally, you’d want to write a separate plugin for jQuery so that it does not interfere with the jQuery library itself, but you’ll have to decide whether or not that is feasible for your project.

Related:  how to set value of a input hidden field through javascript?

Solution 2:

Things have moved on a bit since the question was asked – it is now possible to use a MutationObserver to detect changes in the ‘style’ attribute of an element, no jQuery required:

var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutationRecord) {
        console.log('style changed!');
    });    
});

var target = document.getElementById('myId');
observer.observe(target, { attributes : true, attributeFilter : ['style'] });

The argument that gets passed to the callback function is a MutationRecord object that lets you get hold of the old and new style values.

Support is good in modern browsers including IE 11+.

Solution 3:

The declaration of your event object has to be inside your new css function. Otherwise the event can only be fired once.

(function() {
    orig = $.fn.css;
    $.fn.css = function() {
        var ev = new $.Event('style');
        orig.apply(this, arguments);
        $(this).trigger(ev);
    }
})();

Solution 4:

I think the best answer if from Mike in the case you can’t launch your event because is not from your code. But I get some errors when I used it. So I write a new answer for show you the code that I use.

Related:  How to get the element clicked (for the whole document)?

Extension

// Extends functionality of ".css()"
// This could be renamed if you'd like (i.e. "$.fn.cssWithListener = func ...")
(function() {
    orig = $.fn.css;
    $.fn.css = function() {
        var result = orig.apply(this, arguments);
        $(this).trigger('stylechanged');
        return result;
    }
})();

Usage

// Add listener
$('element').on('stylechanged', function () {
    console.log('css changed');
});

// Perform change
$('element').css('background', 'red');

I got error because var ev = new $.Event(‘style’); Something like style was not defined in HtmlDiv.. I removed it, and I launch now $(this).trigger(“stylechanged”). Another problem was that Mike didn’t return the resulto of $(css, ..) then It can make problems in some cases. So I get the result and return it. Now works ^^ In every css change include from some libs that I can’t modify and trigger an event.

Solution 5:

As others have suggested, if you have control over whatever code is changing the style of the element you could fire a custom event when you change the element’s height:

$('#blah').bind('height-changed',function(){...});
...
$('#blah').css({height:'100px'});
$('#blah').trigger('height-changed');

Otherwise, although pretty resource-intensive, you could set a timer to periodically check for changes to the element’s height…

Related:  Setting top and left CSS attributes

Solution 6:

There is no inbuilt support for the style change event in jQuery or in java script. But jQuery supports to create custom event and listen to it but every time there is a change, you should have a way to trigger it on yourself. So it will not be a complete solution.