15
<div class="current"></div>
<a href="#">text</a>

How do I detect when e.g. a .live class is added to this <div> and do something when it happened?

For example, if class is changed, then hide the link.

I have a minified script that makes changes on the <div>'s class. It’s too big for me to find the place where it happens, so I'm searching for some way to catch the class change.

Paul D. Waite
  • 96,640
  • 56
  • 199
  • 270
James
  • 42,081
  • 53
  • 136
  • 161
  • which block? `.current`? – Naftali May 17 '11 at 16:41
  • 2
    A trivial way is always to simply check every so many milliseconds for difference using `setInterval`. – pimvdb May 17 '11 at 16:44
  • I had similar type of issue, but difference is that you were looking to tracking class change, but I had to check attribute changes of not only static dom element but also dynamically added DOM element, follow this link https://stackoverflow.com/a/58501827/6879925 hope this will help you to get the solution of your question – Dinesh Gopal Chand Oct 22 '19 at 10:11

4 Answers4

12

There are DOM events, but they are far from perfect and not available in most browsers. In other words: Not possible (reliably). There are hacks like intervals and checking it in each iteration, but if you need to do something like this, your design is probably screwed. Keep in mind that such things will be slow and that there will always be a delay. The smaller the delay, the slower the application. Do not do that.

jwueller
  • 30,582
  • 4
  • 66
  • 70
  • I don't recall well but I comme across an article on Mozilla Dev Central that warned against using these events (mainly performance issues). – sitifensys May 17 '11 at 17:26
  • This is NOT true, it is possible, and reliable, it just requires you to listen to any and all DOM events and filter them out. In your case specifically listen to body's children $(document).on("EVENT","body *", function()); It will be an expensive operation so i would advise against, it but defnitly possible and reliable – Tobias Hagenbeek Aug 04 '15 at 15:16
  • @TobiasHagenbeek: Which event would you be listening for to detect class attribute changes? As far as I am aware, `on()` utilizes event bubbling to detect events -- not DOM changes -- in an element's children. However, if the browser DOM events are unreliable (which they definitely were at the time of writing), that will not help in accomplishing what the OP was asking for without resorting to interval hacks. Some of these circumstances may have changed, so I am genuinely curious as to how this would be accomplished. Please elaborate. – jwueller Aug 06 '15 at 23:12
  • it depends, i'm pressuming at any time you have control over your code, so you know which events occur to add a class. Check this idea https://gist.github.com/yckart/c893d7db0f49b1ea4dfb – Tobias Hagenbeek Aug 07 '15 at 02:13
  • @TobiasHagenbeek: The referenced snippet modifies jQuery to fire custom events upon using its class manipulation functions. This will not work with arbitrary changes to DOM class attributes, but only the ones made through the public jQuery API. For _reliable_ change detection (i.e. regardless of whether your own code caused the change or not) events like the (now deprecated) `DOMAttrModified` or the newer [Mutation Observer API](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) would be required. However, none of those are available in all currently widespread browsers. – jwueller Aug 07 '15 at 07:50
  • Sorry, but yes, the snippes shows only the jQuery API, but don't you know how to use regular javascript in the same fashion? It was just an example, and you are confusing me, you are pretending you don't know HOW the class get's added, is it a foreign action on your page?? Still there is an event that does that, figure out which it is and monitor it. – Tobias Hagenbeek Aug 07 '15 at 13:05
  • @TobiasHagenbeek: The proposed solution of injecting custom events would _only_ work if your classes are manipulated through a non-native wrapper API (like jQuery), because there is no way to _reliably_ listen for primitive property changes in the DOM (see my previous comment). The snippet creates custom events by wrapping the the jQuery API, but again, that does not work for primitive properties. If a library (i.e. _"foreign action"_) directly manipulated the `className` element property, there would be no way to inject code emitting an appropiate custom event you would be able to listen to. – jwueller Aug 07 '15 at 15:59
  • I like this discussion, but i think we are looking at this from a different direction, i am saying that even those library, are firing a call to manipulate the DOM, it is a developers job to find out what happens and where, thus you can reliably match any event, coming from a API (like jQuery) or usage of primitive manipulation, this brings me back to the point that it can NEVER happen you don't have any control on any dom manipulation that occurs anywhere in YOUR document. – Tobias Hagenbeek Aug 07 '15 at 16:24
  • Sorry @jwueller, from the perspective of a developer that doesn't know/understand scripts he/she uses, you are absolutely right, else it is as reliable as the developer. – Tobias Hagenbeek Aug 07 '15 at 16:25
  • @TobiasHagenbeek: Of course, manually tracking every DOM manipulation is possible. I do not see how that conflicts with my answer, though. Tracking DOM changes yourself will work, but it is still a workaround for incomplete DOM event support. It would not solve OPs problem either, because he is trying to detect changes _without_ adding extra code to the location at which the class attribute is manipulated. Reliably listening for DOM changes without adjusting existing code does not seem possible without resorting to state polling. If you disagree, I would still be very interested in an example. – jwueller Aug 07 '15 at 19:00
  • the comment "without adjusting existing code is never going to be the case, i know what you mean but your always adjusting existing code, wether your adding a line or not, and my point wasn't to make it work for him, you made a general statement not possible and not reliable, it is you just can't be lazy. But a developer should never be anyway. – Tobias Hagenbeek Aug 07 '15 at 21:10
2

You may checkout the following article for some ideas.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
2

I don't know if the class you add to the link is always the same but if so, why don't you use CSS for this.

<style type='text/css>
  .myaddedclass{display:none}
</style>
jeroen.verhoest
  • 5,173
  • 2
  • 27
  • 27
  • Yes. @Rooney, if all you want is to hide/show elements, change colors or other attributes, etc. then just target CSS at the class you are adding and you don't have to monitor for the change at all. The CSS will do it for you. That's how I handle hide/show, marking the "currently selected" row, and similar issues. – Stephen P May 18 '11 at 01:04
2

If you just need to figure this out once (i.e. not in code), Google Chrome’s web inspector shows DOM changes live. Not sure if that’d help your situation out though.

Paul D. Waite
  • 96,640
  • 56
  • 199
  • 270
  • 3
    +1 You can also right-click on the node in (in the Elements tab) and click "Break on Attributes Modification" - this should halt the JS at the correct line. (Un-minify it to get better line breaks: http://jsbeautifier.org/) – peteorpeter May 17 '11 at 18:56
  • @peteorpeter: ooh, that’s really handy, I had no idea about that. – Paul D. Waite May 18 '11 at 00:52
  • I just found it myself (who knows how longs it's been there - sneaky Chrome updates...) – peteorpeter May 18 '11 at 12:23
  • @peteorpeter: I know. Is it lunchtime yet? Because if it is then Chrome’s probably on another major version. – Paul D. Waite May 18 '11 at 12:24