handleEvents API tweaks

This commit is contained in:
Jeremy Ashkenas
2010-10-12 16:47:56 -04:00
parent d8308f9712
commit 15b2ec81e8
3 changed files with 31 additions and 18 deletions

View File

@@ -507,6 +507,9 @@
return $(selector, this.el);
};
// Cached regex to split keys for `handleEvents`.
var eventSplitter = /^(\w+)\s+(.*)$/;
// Set up all inheritable **Backbone.View** properties and methods.
_.extend(Backbone.View.prototype, {
@@ -538,11 +541,11 @@
// Set callbacks, where this.callbacks is a hash of
//
// *{selector.event_name: callback_name}*
// *{"event selector": "callback"}*
//
// {
// '.icon.pencil.mousedown': 'edit',
// '.button.click': 'save'
// 'mousedown .title': 'edit',
// 'click .button': 'save'
// }
//
// pairs. Callbacks will be bound to the view, with `this` set properly.
@@ -550,13 +553,13 @@
// Passing a selector of `el` binds to the view's root element.
// Change events are not delegated through the view because IE does not
// bubble change events at all.
handleEvents : function(callbacks) {
handleEvents : function(events) {
$(this.el).unbind();
if (!(callbacks || (callbacks = this.callbacks))) return this;
for (key in callbacks) {
var methodName = callbacks[key];
key = key.split(/\.(?!.*\.)/);
var selector = key[0], eventName = key[1];
if (!(events || (events = this.events))) return this;
for (key in events) {
var methodName = events[key];
var match = key.match(eventSplitter);
var eventName = match[1], selector = match[2];
var method = _.bind(this[methodName], this);
if (selector === '' || eventName == 'change') {
$(this.el).bind(eventName, method);

View File

@@ -943,11 +943,21 @@ ui.Chapter = Backbone.View.extend({
Uses jQuery's <tt>delegate</tt> function to provide declarative callbacks
for DOM events within a view.
If an <b>events</b> hash is not passed directly, uses <tt>this.events</tt>
as the source. Events are written in the format <tt>{selector.event: callback}</tt>
as the source. Events are written in the format <tt>{"event selector": "callback"}</tt>.
</p>
<p>
For example, a view that displays a document in a search result might look
Using <b>handleEvents</b> provides a number of advantages over manually
binding events to child elements within <tt>render</tt>. All attached
callbacks are bound to the view before being handed off to jQuery, so when
the callbacks are invoked, <tt>this</tt> continues to refer to the view object. When
<b>handleEvents</b> is run again, perhaps with a different <tt>events</tt>
hash, all callbacks are removed and delegated afresh &mdash; useful for
views which need to behave differently when in different modes.
</p>
<p>
A view that displays a document in a search result might look
something like this:
</p>
@@ -955,12 +965,12 @@ ui.Chapter = Backbone.View.extend({
var DocumentView = Backbone.View.extend({
events: {
".title.click" : "select",
".title.dblclick" : "open",
".icon.doc.contextmenu" : "showMenu",
".show_notes.click" : "toggleNotes",
".title .lock.click" : "editAccessLevel",
".title .date.mouseover" : "showTooltip"
"click .title" : "select",
"dblclick .title" : "open",
"contextmenu .icon.doc" : "showMenu",
"click .show_notes" : "toggleNotes",
"click .title .lock" : "editAccessLevel",
"mouseover .title .date" : "showTooltip"
},
render: {

View File

@@ -32,7 +32,7 @@ $(document).ready(function() {
view.increment = function() {
return ++counter;
};
var events = {"#qunit-banner.click": "increment"};
var events = {"click #qunit-banner": "increment"};
view.handleEvents(events);
$('#qunit-banner').trigger('click');
equals(counter, 1);