Mobile web/Coding conventions/JavaScript/Views

= Handling DOM events in JS views =

Delegated declarative dom events
The preferred way of handling dom events on a view is by using the events map.

In the view properties, we just define a  map (just like we do with   and others).

The events  map consists of:

Where:


 * is any valid jQuery event.
 * is an optional valid jQuery selector. If ommited, the event will be bound to the views.
 * is either a, or a   (name of a method on the view). The handler is defined and will be invoked on the view's.

Advantages

 * More efficient. Events are bound with delegate, effectively attaching one DOM listener per event type on the view's root DOM element. (Read http://api.jquery.com/on/#direct-and-delegated-events)
 * Easier to understand. To see which DOM events the view binds and reacts to, just need to find the events map of the view.
 * Event handling code (usually pieces of logic of the view) gets a name, and it's encapsulated on its own method giving us:
 * Reuse of such logic/functionality
 * Easier and better testability
 * Cleaner postRender methods

Naming handlers
When creating event handlers, if they are doing DOM stuff, like preventDefault, or extracting data from the DOM node, manipulating the DOM, etc, you should name the handler, for example   or.

If possible, extract functionality that makes sense independently into methods with a good name and call them from the handlers as needed.

When creating methods on a view, like the  example above, that happen to be called when an event happens but make sense independently, you should probably give that method a name   makes more sense than a handler name , but that is open to common sense and taste.

For example, if I had to extract what to increment from a DOM element, and then increment it, then I would use both approaches:

This way we can cleanly test our  function without touching the DOM, and it can be reused from other parts of the view (or called from external consumers of the view).

Getting the DOM element that generated the event
A common practice you can see with the manual approach is inside the event handler to access the DOM element that initiated the event by doing. With the events map approach the handlers/methods are at view level and are consistently bound to the view's, so how do we access the DOM element of the event?

Handler methods get an  as a parameter, so:

http://api.jquery.com/category/events/event-object/

A View that from another View class
If the View for which you are implementing the events map inherits/extends from another View class, for safety when declaring the events map declare it extending from the parent events map, like this:

Careful with child views
When implementing events map on a View, be careful with the children classes. If you implement the events map, and a children class implements it also, without extending as explained above, then the child view will be overriding the parent events.

As a quick rule, when implementing it on a view, have a look at sub-views (search for " ") and if any of the sub-views uses events map, modify it to extend from the parent events map as explained in the example above.

How does it work
Internally, this is just using jQuery to delegate the events and the selectors to specified handlers bound to the view, no black magic.

This is inspired and brought from Backbone.js, a very simple and clean JS library, similar in philosophy to our own.


 * http://backbonejs.org/#View-extend
 * http://backbonejs.org/#View-delegateEvents

Manual approach with jQuery
To bind events to the view manually, we bind them on the  method, like so:

After the view has been rendered, we use the  shortcut to select elements within the view's   and bind events as we would do with jQuery. You can use also delegated events with this approach.

Gotchas

 * Everytime the view renders, we bind events (multiple of them), this is inefficient, there are better ways.
 * The postRender method on views grows a lot in size, event handling declarations and method code is mixed with display logic.
 * The complexity of the view (arguably) increases, and with it the ability to read and modify the source confidently.