views:

922

answers:

1

I'm trying to create a jQuery special event that triggers when the content that is bound, changes. My method is checking the content with a setInterval and check if the content has changed from last time. If you have any better method of doing that, let me know. Another problem is that I can't seem to clear the interval. Anyway, what I need is the best way to check for content changes with the event.special.

(function(){

 var interval;

    jQuery.event.special.contentchange = {
        setup: function(data, namespaces) {
         var $this = $(this);
            var $originalContent = $this.text();
            interval = setInterval(function(){
             if($originalContent != $this.text()) {
              console.log('content changed');
              $originalContent = $this.text();
              jQuery.event.special.contentchange.handler();
             }
            },500);
        },
        teardown: function(namespaces){
            clearInterval(interval);
        },
        handler: function(namespaces) {
            jQuery.event.handle.apply(this, arguments)
     }
    };

})();

And bind it like this:

$('#container').bind('contentchange', function() {
     console.log('contentchange triggered');
});

I get the console.log 'content changed', but not the console.log 'contentchange triggered'. So it's obvious that the callback is never triggered.

I just use Firebug to change the content and to trigger the event, to test it out.

Update
I don't think I made this clear enough, my code doesn't actually work. I'm looking for what I'm doing wrong.


Here is the finished code for anyone interested

(function(){

 var interval;

 jQuery.event.special.contentchange = {
        setup: function(){
            var self = this,
            $this = $(this),
            $originalContent = $this.text();
            interval = setInterval(function(){
             if($originalContent != $this.text()) {
                 $originalContent = $this.text();
                    jQuery.event.handle.call(self, {type:'contentchange'});
             }
            },100);
        },
        teardown: function(){
            clearInterval(interval);
        }
    };

})();

Thanks to Mushex for helping me out.

+4  A: 

Hi, also take a look to James similar script (declaring as jquery object method and not as event)

jQuery.fn.watch = function( id, fn ) {

    return this.each(function(){

        var self = this;

        var oldVal = self[id];
        $(self).data(
            'watch_timer',
            setInterval(function(){
                if (self[id] !== oldVal) {
                    fn.call(self, id, oldVal, self[id]);
                    oldVal = self[id];
                }
            }, 100)
        );

    });

    return self;
};

jQuery.fn.unwatch = function( id ) {

    return this.each(function(){
        clearInterval( $(this).data('watch_timer') );
    });

};

and creating special event

jQuery.fn.valuechange = function(fn) {
    return this.bind('valuechange', fn);
};

jQuery.event.special.valuechange = {

    setup: function() {

        jQuery(this).watch('value', function(){
            jQuery.event.handle.call(this, {type:'valuechange'});
        });

    },

    teardown: function() {
        jQuery(this).unwatch('value');
    }

};

Anyway, if you need it only as event, you script is nice :)

Mushex Antaranian
What I'm looking for is how to just create a special event, like I have done, only one that actualy works. Can you show me that?
mofle
I thought you solved it and just bring this example to you to see a little different approach to this problem. If your script actually doesn't work yet, let me know.
Mushex Antaranian
My script doesn't work. Would be great if you could help me make it work :) And by the way, thanks for the other approach.
mofle
Check http://pastie.org/623665 Works for me. Hope it'll help :)
Mushex Antaranian
Thanks :) Good to know that I was close.
mofle