In my previous post I wrote about the Backbone.js library. When creating a view that contained several clickable areas and also anchor HTML elements I noticed that the anchor links did not work. Further investigation using a cool tool called Visual Event led me to the part of the code that interprets the view’s events object. In the Backbone.View constructor, there is a call for delegateEvents function. What this function actually does is go over the events object and use jQuery to bind the handlers to their relevant events. The thing is that in BB the events object has the ability to contain selectors e.g. ‘eventName .class-name’ : ‘eventHandler’. This little difference is quite big in terms of both performance and functionality. At the end of the delegateEvents function there are the following lines of code:
This little line of code makes all the difference. Instead of simply bind the event like he does when there is no selector, BB uses delegate. In the delegate documentation you see this simple explanation: “Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements.”. It is not by accident that I highlighted the “in the future” phrase. What it actually means is that he attaches a handler on the jQuery object, and when the event is triggered, it uses the selector to find the relevant element inside the element represented by the jQuery element. For example:
This will bind the tap event to all elements with the class=”class1″, and when the event is triggered, it will trigger it only on the inner elements with the class=”class2″. Let’s say that under a class1 element you have this element:
Tapping this element would just not work! You need to bind the tap event manually after the element is added to the view, so instead of writing this:
Which will cause this call:
You should call this:
You should know that there is subtle difference between these calls. In the first one I used “method” instead of this.eventHandler. The reason is that BB does not pass the function as is, but encapsulate it with its own bind method that allows it to pass a context to the method which is basically saying: when you run this handler function, set the “this” object to the one I specify. In the latter line of code, this.eventHandler will have the DOM element on which the event was triggered on as the context (“this” object). To overcome this “this” issue (sorry, couldn’t resist), you can use the jQuery.proxy function, in this case:
What we basically do is change the context of the eventHanler when called. Have a look on the proxy function implementation, pretty straight forward.
There is a lot to learn when looking inside the libraries code (as demonstrated in Paul Irish‘s highly recommended video: “10 things I learned from the jQuery source“). So don’t be afraid to look into these libraries and try not to consider them as a black box. I know I did.