views:

2208

answers:

3

Hey all, I was looking for an easy way to monitor an object or variable for changes, and I found Object.Watch that's supported in Mozilla browsers, but not IE. So I started searching around to see if anyone had written some sort of equivalent.

About the only thing I've found has been a jQuery plugin (http://plugins.jquery.com/files/jquery-watch.js.txt), but I'm not sure if that's the best way to go. I certainly use jQuery in most of my projects, so I'm not worried about the jQuery aspect...

Anyway, the question: can someone show me a working example of that jQuery plugin? I'm having problems making it work...

Or, does anyone know of any better alternatives that would work cross browser? Thanks!

Update after answers:

Thanks everyone for the responses! I tried out the code posted here: http://webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html

But I couldn't seem to make it work with IE. The code below works fine in FireFox, but does nothing in IE. In Firefox, each time watcher.status is changed, the document.write in watcher.watch is called and you can see the output on the page. In IE, that doesn't happen, but I can see that watcher.status is updating the value, because the last document.write shows the correct value (in both IE and FF). But, if the callback function isn't called, then that's kind of pointless... :)

Am I missing something?

var options = {'status': 'no status'},
watcher = createWatcher(options);

watcher.watch("status", function(prop, oldValue, newValue) {
    document.write("old: " + oldValue + ", new: " + newValue + "<br>");
    return newValue;
});

watcher.status = 'asdf';
watcher.status = '1234';

document.write(watcher.status + "<br>");
A: 

I found two people which claim to have solved this problem:

Crossbrowser Object watch (claims support for IE, Opera, Safari)

watch() Missing JS Function in IE with use of prototype.js for IE (? Opera, Safari ?)

jitter
Thanks for the links... I tried out the first one and had some issues with IE still. I've updated my initial post above with more info. I haven't had a chance to try out the code in the second link yet, but I'll be sure to do that today.
SeanW
+2  A: 

That plugin simply uses a timer/interval to repeatedly check for changes on an object. Maybe good enough but personally I would like more immediacy as an observer.

Here's an attempt at bringing watch/unwatch to IE: http://webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html.

It does change the syntax from the Firefox way of adding observers. Instead of :

var obj = {foo:'bar'};
obj.watch('foo', fooChanged);

You do:

var obj = {foo:'bar'};
var watcher = createWatcher(obj);
watcher.watch('foo', fooChanged);

Not as sweet, but as an observer you are notified immediately.

Crescent Fresh
Already listed above.
SleepyCod
@SleepyCod: why would you downvote a helpful answer? Look at the timestamps. We posted within 2 seconds of each other (literally, I remember). Here's how it works: downvote incorrect or otherwise irrelevant answers.
Crescent Fresh
Yep, watch those timestamps... no need to downvote, also crescentfresh added more info to the post, even if it was the same link. Meanwhile, I've tried the code found on that page and still see a problem. I may be overlooking something though. I've updated my original post with more info...
SeanW
+3  A: 

(Sorry for the cross-posting, but this answer I gave to a similar question works fine here)

I have created a small object.watch shim for this a while ago. It works in IE8, Safari, Chrome, Firefox, Opera, etc.

/*
* object.watch v0.0.1: Cross-browser object.watch
*
* By Elijah Grey, http://eligrey.com
*
* A shim that partially implements object.watch and object.unwatch
* in browsers that have accessor support.
*
* Public Domain.
* NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
*/

// object.watch
if (!Object.prototype.watch)
    Object.prototype.watch = function (prop, handler) {
        var oldval = this[prop], newval = oldval,
        getter = function () {
            return newval;
        },
        setter = function (val) {
            oldval = newval;
            return newval = handler.call(this, prop, oldval, val);
        };
        if (delete this[prop]) { // can't watch constants
            if (Object.defineProperty) // ECMAScript 5
                Object.defineProperty(this, prop, {
                    get: getter,
                    set: setter
                });
            else if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) { // legacy
                Object.prototype.__defineGetter__.call(this, prop, getter);
                Object.prototype.__defineSetter__.call(this, prop, setter);
            }
        }
    };

// object.unwatch
if (!Object.prototype.unwatch)
    Object.prototype.unwatch = function (prop) {
        var val = this[prop];
        delete this[prop]; // remove accessors
        this[prop] = val;
    };
Eli Grey