Here's a scenario I've run into on a few occasions: I need to be able to monitor certain CSS properties on an HTML element and know when that CSS element changes. For example, I have a some HTML element behavior plugins like a drop shadow that attaches to any HTML element, but I then need to be able to automatically keep the shadow in sync with the window if the  element dragged around the window or moved via code.

Unfortunately there's no move event for HTML elements so you can't tell when it's location changes. So I've been looking around for some way to keep track of the element and a specific CSS property, but no luck. I suspect there's nothing native to do this so the only way I could think of is to use a timer and poll rather frequently for the property.

I ended up with a generic jQuery plugin that looks like this:

[updated based on comments using DOMAttrChanged and propertyChange events]

(function($){
$.fn.watch = function(prop, func, interval, id) {
    /// <summary>
    /// Allows you to monitor changes in a specific
    /// CSS property of an element by polling the value.
    /// when the value changes a function is called.
    /// The function called is called in the context
    /// of the selected element (ie. this)
    /// </summary>    
    /// <param name="prop" type="String">CSS Property to watch. If not specified (null) code is called on interval</param>    
    /// <param name="func" type="Function">
    /// Function called when the value has changed.
    /// </param>    
    /// <param name="func" type="Function">
    /// optional id that identifies this watch instance. Use if
    /// if you have multiple properties you're watching.
    /// </param>        
    /// <returns type="jQuery" />   
    if (!interval)
        interval = 200;
    if (!id)
        id = "_watcher";

    this.each(function() {
        var _t = this;
        var el = $(this);
        var fnc = function() {__watcher.call(_t, id) };
        var itId = null;

        var z = el.get(0);                        
        if (typeof(z.onpropertychange) == "object")
           el.bind("propertychange", fnc);
        else if ($.browser.mozilla)
            el.bind("DOMAttrModified", fnc);
        else
            itId = setInterval(fnc, interval);

        el.data(id, { id: itId,
            prop: prop,
            func: func,
            val: prop ? el.css(prop) : null
        });
    });
    return this;
}
$.fn.unwatch = function(id) {
    this.each(function() {
        var w = $(this).data(id);
        $(this).removeData();

        if (typeof (z.onpropertychange) == "object")
            el.unbind("propertychange", fnc);
        else if ($.browser.mozilla)
            el.unbind("DOMAttrModified", fnc);
        else
            clearInterval(w.id);
    });
    return this;
}
function __watcher(id) {
    var el = $(this);
    var w = el.data(id);
    
    if (w.prop) {
        var newVal = el.css(w.prop);
        if (w.val != newVal)
            w.val = newVal;
        else
            return;
    }
    if (w.func) {        
        var _t = this;
        w.func.call(_t)
    }
}
})(jQuery);

With this I can now monitor movement by monitoring say the top CSS property of the element. The following code creates a box and uses the draggable (jquery.ui) plugin and a couple of custom plugins that center and create a shadow. Here's how I can set this up with the watcher:

$("#box")
        .draggable()
        .centerInClient()
        .shadow()
        .watch("top", function() {
                    $(this).shadow();
               },70,"_shadow");
                
... 
$("#box")
.unwatch("_shadow")
.shadow("remove");

This code basically sets up the window to be draggable and initially centered and then a shadow is added. The .watch() call then assigns a CSS property to monitor (top in this case) and a function to call in response. The component now sets up a setInterval call and keeps on pinging this property every time. When the top value changes the supplied function is called.

While this works and I can now drag my window around with the shadow following suit it's not perfect by a long shot. The shadow move is delayed and so drags behind the window, but using a higher timer value is not appropriate either as the UI starts getting jumpy if the timer's set with too small of an increment.

This sort of monitor can be useful for other things as well where operations are maybe not quite as time critical as a UI operation taking place.

Can anybody see a better a better way of capturing movement of an element on the page?