Create a jQuery special event for content changed
Solution 1
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 :)
Solution 2
I know this post/question is a little old, but these days I was behind a similar solution and I found this:
$('#selector').bind('DOMNodeInserted', function(e) {
console.log(e.target);
});
Source: http://naspinski.net/post/Monitoring-a-DOM-Element-for-Modification-with-jQuery.aspx
Hope this help someone!
Solution 3
The finished code in the original question worked for me, thank you! I would just like to note that I am using jquery 1.9.1 and $.event.handle seems to have been removed. I changed the following to get it to work.
jQuery.event.handle.call(self, {type:'contentchange'});
to
jQuery.event.dispatch.call(self, {type:'contentchange'});
Sindre Sorhus
Updated on June 05, 2022Comments
-
Sindre Sorhus about 2 years
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 theevent.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 theconsole.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.
-
meder omuraliev almost 15 yearsAny reason you're not using 'var' for $this declaration?
-
meder omuraliev almost 15 yearsAnd do you have consistent spelling of 'orginalContent' in the real page?
-
David Andres almost 15 yearswhen is teardown called?
-
Sindre Sorhus almost 15 years@David Andres - when I unbind the event. $('#container').unbind('contentchange');
-
Asaf almost 13 yearsIf I'm not mistaken this implementation will only keep the last timer id. to fix it I would do something like $(this).data("onchange.timer.id",interval) and retrieve in the teardown
-
vsync over 7 yearsYour "finished" code logic has a major BUG since each time
.on("contentchange"..
is binded, it will override the generalinterval
variable, which would hinder othercontentchange
event which might have been binded previously... been 8 years, you can fix it to work better :)
-
-
Sindre Sorhus almost 15 yearsWhat 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?
-
Mushex Antaranian almost 15 yearsI 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.
-
Sindre Sorhus almost 15 yearsMy script doesn't work. Would be great if you could help me make it work :) And by the way, thanks for the other approach.
-
Sindre Sorhus almost 15 yearsThanks :) Good to know that I was close.
-
mkoistinen over 11 yearsHardly worth a downvote. Many things are deprecated, but until ALL browsers offer a better solution, they'll still be used, and it is still useful to understand. (+1 offset vote here)
-
TCHdvlp over 9 yearsneat ! A lot cleaner that a timer even if it's deprecated !
-
Michael Scheper almost 9 yearsDeprecated, yes, but there's a CSS3 replacement. stackoverflow.com/a/25256569/1450294 Even IE finally supports it (in version 11)! caniuse.com/#feat=mutationobserver