tags:

views:

310

answers:

4
+5  Q: 

jQuery watch div

Is there any way to watch, if the content within a div changes?

Let's say I have:

<div id="hello"><p>Some content here</p></div>

Which at some point 5 seconds later changes to:

<div id="hello"><ul><li>This is totally different!</li></ul></div>

How can I be notified of this via a callback or something else? I can in most cases get the javascript that's doing the inserting, to tell me. But I wanted to know if it was possible.

+1  A: 

Who/what will change this? If it's some JS you control, use that to also trigger your callback. Obviously a user cannot change this.

If you want to watch a <input> element etc, use the 'change' event. jQuery version here: http://api.jquery.com/change/

psychotik
Speak for yourself! [pets Firebug] ;) Seriously now, +1.
Amadan
A: 

Here's a code sample that calls a simple alert when the given value changes:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>watchu, watchu, watchu want, watchu want?</title>
</head>
<body>

    <div id='foo'>Hello World!</div>

    <p><input type="button" id="ChangeButton" value="Change It" /></p>

    <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.min.js"&gt;&lt;/script&gt;
    <script type="text/javascript">

        $(function () {

            $('#ChangeButton').click(function () {
                $('#foo').html('Awfveeterzain!');
            });

            window.watchForChangeOriginalValue = $('#foo').html();
            watchForChange();
        });

        function watchForChange() {
            if ($('#foo').html() != window.watchForChangeOriginalValue)
                alert('the value changed!');
            else
                window.setTimeout(watchForChange, 500);
        }

    </script>
</body>
</html>
AndrewDotHay
+8  A: 

The jQuery .change() method works only for form fields.

I wrote a little jQuery plugin for you:

<!-- jQuery is required -->

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"&gt;&lt;/script&gt;


<!-- this is the plugin -->

<script>
  jQuery.fn.contentChange = function(callback){
    var elms = jQuery(this);
    elms.each(
      function(i){
        var elm = jQuery(this);
        elm.data("lastContents", elm.html());
        window.watchContentChange = window.watchContentChange ? window.watchContentChange : [];
        window.watchContentChange.push({"element": elm, "callback": callback});
      }
    )
    return elms;
  }
  setInterval(function(){
    if(window.watchContentChange){
      for( i in window.watchContentChange){
        if(window.watchContentChange[i].element.data("lastContents") != window.watchContentChange[i].element.html()){
          window.watchContentChange[i].callback.apply(window.watchContentChange[i].element);
          window.watchContentChange[i].element.data("lastContents", window.watchContentChange[i].element.html())
        };
      }
    }
  },500);
</script>



<!-- some divs to test it with -->

<p>Testing it:  (click on divs to change contents)</p>

<div id="a" onclick="$(this).append('i')">Hi</div>
<div id="b" onclick="$(this).append('o')">Ho</div>
<div class="c" onclick="$(this).append('y')">He</div>
<div class="c" onclick="$(this).append('w')">He</div>
<div class="c" onclick="$(this).append('a')">He</div>




<!-- this is how to actually use it -->

<script>
  function showChange(){
    var element = $(this);
    alert("it was '"+element.data("lastContents")+"' and now its '"+element.html()+"'");
  }

  $('#a').contentChange(function(){  alert("Hi!") });
  $('div#b').contentChange( showChange );
  $('.c').contentChange(function(){  alert("He he he...") });
</script>
Sebastián Grignoli
Thanks. Clearly the only way to do it is to manually set a timer. I probably will never need to use the plugin, but kudos for writing it.
Jasie
Be aware that this watches changes in the contents of the element (html) only, not the attributes.
Sebastián Grignoli
+1  A: 

There is no native jQuery/DOM event that will fire when HTML/DOM content changes.

You could (if you are feeling particularly wasteful) do something like this:

$(function() {
  var $div = $("#hello");
  var html = $div.html();
  var checking = setInterval(function() {
    var newhtml = $div.html();
    if (html != newhtml) {
      myCallback();
      html = newhtml;
    }
  },100);

  function myCallback() {
    alert('content changed!');
    // if you only want it to fire once, uncomment the following:
    // clearInterval(checking);
  }
});

Just remember, calling .html() every 100ms is probably not the best idea for your sites performance.

jsFiddle mockup

gnarf