Shawn31313
Shawn31313

Reputation: 6052

I need a new way to detect if there has been a change to an elements HTML

Right now im trying to find a way to detect when an elements HTML has changed.

I'm currently trying:

var a, b;
setInterval(function() {
    a = $('#chat').text();
}, 150);
setInterval(function() {
    b = $('#chat').text();
    if (a !== b) {
        alert("There has been a new message.");
    }
}, 200);​

What I do is every 150 milliseconds I check for the HTML of #chat and then every 200 seconds I check the HTML again and then check if variable a does not equal to variable b them in the future I will so something with that but for right now I just alert something.

You can see it live here: http://jsfiddle.net/MT47W/

Obviously this way is not working and is not very accurate at all. Is there a better/different to do/achieve this?

Thanks for any help, I've been trying to figure out how to do this a better for about a week now but I just can't find a fix for this and i'm hoping I posted this problem at the right place, and at the right time.

Upvotes: 12

Views: 3038

Answers (4)

Mottie
Mottie

Reputation: 86413

Although it is not highly recommended, it is also possible to use Paul Irish's Duck punching method to tie into jQuery's append function - if you know for sure that the append function is how content is being added (demo):

(function($) {
    // store original reference to the method
    var _old = $.fn.append;
    $.fn.append = function(arg) {
        // append as usual
        _old.apply(this, arguments);

        // do your own checking here
        // "this" is a jQuery object
        if (this[0].id === "chat") {
            alert('there is a new message!');
        }
        return this;
    };

})(jQuery);

With this method, no timing loops are needed.

Upvotes: 0

Fabrício Matté
Fabrício Matté

Reputation: 70149

Use a var to store the element's current text then check against it in a setInverval and update the var to store the current text after checking:

var a = $('#chat').text();
setInterval(function() {
    if (a !== $('#chat').text()) { //checks the stored text against the current
        alert("There has been a new message."); //do your stuff
    }
    a = $('#chat').text(); //updates the global var to store the current text
}, 150); //define your interval time, every 0.15 seconds in this case

Fiddle

You may as well store the value in the .data() of the element to avoid using globals.

Example using .data():

$('#chat').data('curr_text', $('#chat').text());
setInterval(function() {
    if ($('#chat').data('curr_text') !== $('#chat').text()) {
        alert("There has been a new message.");
    }
     $('#chat').data('curr_text', $('#chat').text());
}, 150);

Fiddle

Another approach, to save client's memory, you can just store the number of child divs your #chat element has:

$('#chat').data('n_msgs', $('#chat').children().length);
setInterval(function() {
    if ($('#chat').data('n_msgs') !== $('#chat').children().length) {
        alert("There has been a new message.");
    }
     $('#chat').data('n_msgs', $('#chat').children().length);
}, 150);

Fiddle


EDIT: Here's my very final addition, with a DOM mutation event listener:

$('#chat').on('DOMNodeInserted', function() {
    alert("There has been a new message.");
});

Fiddle (not tested in IE < 8)

Note: As noted in the comments, even though mutation events are still supported they're classed as deprecated by W3C due to the performance loss and some incompatibilities across different browsers, therefore it's suggested to use one of the solutions above and only use DOM Mutation events when there's no other way around.

Upvotes: 7

Kevin Pei
Kevin Pei

Reputation: 5872

Just checking the last chat would improve efficiency and also do what you want. The only way that it would not work is if the same person sends the same message twice - which most likely will not happen.

I hope this would work:

 var lastMessage = $('#chat .body').last().text();
    function checkMessages(){
        var newLastMessage = $('#chat .body').last().text();
        if(lastMessage !== newLastMessage && $('#chat .body').last().length > 0){
             //message has changed
            alert("There has been a new message.");
            lastMessage = $('#chat .body').last().text();
        }
        setTimeout(function(){checkMessages();},1000);
    }
    checkMessages();

Js Fiddle

Upvotes: 2

zatatatata
zatatatata

Reputation: 4821

Use crc32 or md5 hashing to check whether data has changed. Just get the html content of the div that you want to check, hash it as a string with either crc32 or md5 and you'll get a string that will represent that content. Use a hidden timestamp etc to be sure that multiple messages by one user get a different hash. If you do this in a setInterval callback, you should be good.

Upvotes: 1

Related Questions