Hacker News new | past | comments | ask | show | jobs | submit login
How to detect DOM changes in CSS (streak.com)
71 points by OmarIsmail on Nov 15, 2012 | hide | past | favorite | 17 comments



Its a very clever technique, but unfortunately its very fragile and may not really be needed.

By fragile, I mean that you must construct your css to be very specific in order for this technique to trigger properly. Any non-expected changes to the DOM are rather difficult to trap for. This somewhat limits its applicability.

DOM Mutation Events were, indeed, very performance intensive. They've been deprecated for a while now and are gradually being removed from browsers. However, there is a replacement in the works and WebKit/Firefox browsers already support it.

Enter Mutation Observers. https://hacks.mozilla.org/2012/05/dom-mutationobserver-react...

With Observers, you can target a specific parent node and be informed of any changes to its children. Its highly performant and eventually should be available in all platforms (IE taking the longest to adopt it).

I do see room here for an interesting compromise though. It seems we might be able to combine both techniques to have a universal wrapper for detecting DOM changes across any browser in a relatively efficient manner.

While IE9+ may not have all of the cutting edge features to be found in Chrome, IE9+ have exceedingly fast javascript engines and graphics acceleration. Its entirely reasonable to expect a DOM Mutation Observer shim for IE9+ to behave rather well.


Thanks for pointing out the new MutationObserver API! I actually wasn't aware of that, so for exhaustive comparison I'd have to do more research into it. Reading up on the API there are a few issues that I see though:

1) You still have the same DOM structure brittleness. For detecting insertions you have to bind to a an ancestor node and monitor each change to see if the new nodes are of the type you're interested in - which is essentially through selectors/traversal.

2) with the CSS technique you can structure the selectors/animations to only trigger when the specific nodes come into existence. It's true that you have a callback on every animation fired, but that's a simple switch case that executes super fast. With MutationObserver you have to do a lot more processing on each callback, including interacting with the DOM to figure out which nodes were added/changed/deleted - and accessing the DOM is quite slow. I think you'll have to be really careful with these MutationObservers or you can run into situations where you do have a big performance hit.


Interesting discussion Omar. I think combining the API with the css technique could lead to some interesting uses.


I would like to mention that when you working over a stable JS DOM manipulation framework you can intercept events and easily create your custom mutation detection solution; fast and cross-browser.

A little example using jQuery:

    _append = $.fn.append
    $.fn.append = function(){
        $(this).trigger("mutated");
        return _append.apply(this,arguments)
    }


Hey whatdayaknow, the method I created! Here's a follow-up I published a while back that provides an generic listener method using the technique: http://www.backalleycoder.com/2012/08/06/css-selector-listen...


Damn, this is almost what I was looking for earlier.

I was trying to figure out how to tell when an iframe's document size changed (because, for instance, a $(node).show() was called), in order to adjust a custom html-and-js powered scrollbar.


I tried doing that in 2001, it was aweful. Have you got it solved yet? I was thinking about this because the other day I was trying to intercept child scrolling events on mobile OS.


Very cool. Maybe this is a silly question, but any reason you're using 2n and 2n+1 instead of just "even" and "odd"? Is it just to avoid targeting the first-of-type?


I'm not very familiar with Chrome development, but it seems like you have pretty strong capabilities. Why couldn't bind to the click event on the Compose button?


Answered here: http://news.ycombinator.com/item?id=4791596

Summary is that there are a lot more ways than clicking on the compose button to bring up a compose window.


Hmm, still seems kinda messy to rely on CSS.

Next thought, maybe you can override Google's open method with something like this: http://jsfiddle.net/Z3Ysq/

They may have been able to prevent this with a closure, but I think you could workaround everything. Watch out for scope issues, but I think there's a way to make this completely generalizable.

That being said, I agree that at some point, it might get too messy figuring this all out that your existing solution is best. Kudos for the clever concept.


You look at Gmail's JS and tell me which function is the "open compose" :)

Someone who can do that would get hired pretty quickly!


Just one little citation of the original article that demonstrated this hack would be nice. The guy references David Walsh's blog (a friend of mine), who even in the article cites and attributes the method, yet doesn't include it in here? Just a tad lame, that's all: http://www.backalleycoder.com/2012/04/25/i-want-a-damnodeins...


It's an interesting hack, but it seems like the DOM changes that they're trying to detect all result from some user event. (clicking "reply" or something) Wouldn't it be easier to just listen for that user event?


Not necessarily true. It's not through reply, but instead compose. And theoretically you could bind to all the trigger events, but you may miss some, and there's a lot of bindings...

You can click on the big compose button in the top right. You can use one of the two keyboard shortcuts, you click click on an email address in an email, you can click on the email icon in the little contact card, etc.

Binding to all of those events (such as the contact card) is about as difficult, if not more so, than binding to the creation of new compose windows themselves.



This is an awesome hack Omar, thanks for sharing.




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: