Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 840
Shawn31313 Avatar asked Jun 11 '12 01:06

Shawn31313


3 Answers

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.

like image 117
Fabrício Matté Avatar answered Oct 04 '22 01:10

Fabrício Matté


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

like image 44
Kevin Pei Avatar answered Oct 04 '22 02:10

Kevin Pei


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.

like image 31
zatatatata Avatar answered Oct 04 '22 01:10

zatatatata