Hacker News new | past | comments | ask | show | jobs | submit login

What about event delegation? In JQuery there exists an overload to .on() that can pass a selector string to filter the descendants of the selected elements that trigger the event.

Is there something similar in Minified?




No, not directly. From the jQuery API docs:

$("#dataTable tbody").on("click", "tr", function(event){ alert($(this).text()); });

In Minified, the easiest way to get exactly the same event handler is this: $("#dataTable tbody").each(function(tbody) { $('tr', tbody).on("click", function(){ alert($(this).text()); }, tbody);


That's not exactly the same at all.


Where's the difference? Admittedly I don't know that function in jQuery very well, but I though it would register a 'click' handler for every tr, just with the difference that it passes the parent tbody instead of the tr in 'this' to the handler. What else does it do?


Delegated events let you handle events for child elements that aren't even in the DOM at the time you attach the handler. The jQuery docs explain it:

api.jquery.com/on/#direct-and-delegated-events

> Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers. This element could be the container element of a view in a Model-View-Controller design, for example, or document if the event handler wants to monitor all bubbling events in the document. The document element is available in the head of the document before loading any other HTML, so it is safe to attach events there without waiting for the document to be ready. ... In addition to their ability to handle events on descendant elements not yet created, another advantage of delegated events is their potential for much lower overhead when many elements must be monitored.


Event delegation is entirely different to how you would normally do it. It relies on the events from the inner elements bubbling up through the parent elements. So you put an event listener on some common ancestor (the tbody in this case) to the elements you care about (the tr elements). A click event on some tr will bubble up to the tbody*, the event handler there can check whether the originating element matches the selector "tr", and if it does, it does something like: `yourCallback.call(event.srcElement, event)`.

The obvious benefit of this is that if there are 10,000 tr elements, it is quicker to attach your listeners (there's only a single listener on the tbody) and less memory is consumed (again, only a single listener). A more subtle set of benefits come from manipulation of the DOM. Your listener is able to respond to events on elements that have been inserted after the listener was first registered. Also, when removing tr elements from the DOM you don't have to remember to unbind all your event handlers (a common source of memory leaks, as they can be GC'd)


A HUGE difference, performance-wise. Delegation is O(1), while using any form of `each()` is going to be O(n).

To elaborate -- jQuery does not set an event-handler for each TR -- it sets one on the parent element (the table), and basically when the table is clicked jQuery gets the event and asks: "are you a TR?", and if so, then the handler is called with the clicked element as the context. So even if your table has 1million rows, only 1 event handler is attached and the DOM is only accessed once.

Of course, accessing the DOM 1 million times within a loop is going to take forever.


That's certainly true, but for what kind of use case do you need 1 million rows? It think that 1000 is already a lot, and if you exceed this, maybe it's better to design the app in a way that you need fewer rows...


It's not just for large numbers of elements. If you have dynamic elements that get added/removed you can define a single event handler on the parent with a filter condition on it's children that handles them all.

The following CoffeeScript event handler would be fired for every table cell with the foobar class that is a child of #myTable:

    $('#myTable').on 'click', 'td.foobar', () ->
        # Do something
What's great here is I can add/remove rows to the table without binding/unbinding event handlers. We use this a lot in our app (http://www.jackdb.com/). The main app content is a single page with all content dynamically loaded and added/removed on the fly. If we had to add event handlers for each data cell (or even row) there would be 1000s of them.


That's not how I would do it in Minified. I'd rather set up the event handler when creating the table row, one at a time, using the element factory (EE() or clone()) onCreate handler. Because otherwise you'd have to store data in the DOM model, which IMHO is not a very elegant design. But it's certainly faster or at least easier on memory consumption if you have many thousand rows.


I love what you are doing, but if you are trying to provide a comparable framework, a thorough understanding of what the functionality you are replicating is vital. The delegation of .on() is quite handy (for reasons others have elaborated already).




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

Search: