0

I have a list that looks like this:

<ul id="colors">
 <li class="variant on">red</li>
 <li class="variant off">blue</li>
 <li class="variant off">white</li>
 <li class="variant off">black</li>
</ul>

I want get an event when an item changes from off to on class changes, e.g. if the following happens:

 <li class="variant off">red</li>
 <li class="variant on">blue</li>

For that I tried to use livequery but I don't manage to get the events or set it right.

$('#colors li.on').livequery(function(){ 
                             console.log(this.text())
                          });
Guy Korland
  • 9,139
  • 14
  • 59
  • 106

2 Answers2

2

This would only be possible in modern browsers that supports the MutationObserver object. You will not be able to observe DOM changes directly otherwise. You could always write some interceptors of the addClass function that would automatically raise events, but I would not recommend this. What you are trying to achieve is pretty bad design. You should not rely on the DOM to keep track of your application state.

plalx
  • 42,889
  • 6
  • 74
  • 90
  • did you ever use livequery plugin? – Guy Korland May 05 '13 at 14:14
  • @GuyKorland, no I never did, but I quickly took a look and that's not what it does. Basically it does the same thing as passing a second selector to the `on` function in jQuery. – plalx May 05 '13 at 14:23
  • I found this answer, which seems to provide solution for browsers which don't support MutationObserver http://stackoverflow.com/a/11004907/593425 – Guy Korland May 05 '13 at 14:27
  • @GuyKorland, Just don't do this... listening to DOM changes to track your application state is ugly and inefficient... *Unless you would be writing a two-way binding feature* – plalx May 05 '13 at 14:32
  • I don't see any other option, the classes are changed by third part scripts which I have no control of, but I do need to react on class change. – Guy Korland May 05 '13 at 14:33
  • @Guy Korland worst case can add a `setInterval` for browsers that don't support DOM observation events and run a function that checks the class constantly – charlietfl May 05 '13 at 14:42
  • 2
    @GuyKorland, wich third-party scripts? Did you read their docs to see if they generate events in such situations? Are the third-party scripts using jQuery? If they are you could try the implementation that Joseph proposed. Otherwise you could check if you can use a similar approach to intercept actions performed by the third-party's scripts. In last resort, without the `MutationObserver`, you could regularly check the DOM for changes using `setInterval` or `setTimeout`. If you know what user actions triggers those changes, you could also listen to the same events the other script listen's to. – plalx May 05 '13 at 14:43
1

An ugly way to do it is to patch the jQuery functions with some intermediate functions of yours before running jQuery's implementation. You could run intermediate code on addClass and removeClass.

For example, patching the addClass. We take the original addClass

jQuery.fn.addClass = (function(){
  var addClass = jQuery.fn.addClass;
  return function(){
    //do stuff here before running the original addClass
    //you could collect callbacks and run them here
    return addClass.apply(this,arguments);
  }
}());

The other way would be MutationObserver which currently is only supported by Chrome, Firefox and Safari.

Joseph
  • 117,725
  • 30
  • 181
  • 234