mirror of
https://github.com/jashkenas/backbone.git
synced 2026-01-22 13:28:22 -05:00
implement callbacks as linked list
This commit is contained in:
46
backbone.js
46
backbone.js
@@ -15,6 +15,9 @@
|
||||
// Save the previous value of the `Backbone` variable.
|
||||
var previousBackbone = root.Backbone;
|
||||
|
||||
// Create a local reference to slice.
|
||||
var slice = Array.prototype.slice;
|
||||
|
||||
// The top-level namespace. All public Backbone classes and modules will
|
||||
// be attached to this. Exported for both CommonJS and the browser.
|
||||
var Backbone;
|
||||
@@ -70,8 +73,9 @@
|
||||
// Passing `"all"` will bind the callback to all events fired.
|
||||
bind : function(ev, callback, context) {
|
||||
var calls = this._callbacks || (this._callbacks = {});
|
||||
var list = calls[ev] || (calls[ev] = []);
|
||||
list.push([callback, context]);
|
||||
var list = calls[ev] || (calls[ev] = {});
|
||||
var tail = list.tail || list;
|
||||
list.tail = tail.next = {callback: callback, context: context};
|
||||
return this;
|
||||
},
|
||||
|
||||
@@ -79,20 +83,19 @@
|
||||
// callbacks for the event. If `ev` is null, removes all bound callbacks
|
||||
// for all events.
|
||||
unbind : function(ev, callback) {
|
||||
var calls;
|
||||
var calls, list, node, prev;
|
||||
if (!ev) {
|
||||
this._callbacks = {};
|
||||
} else if (calls = this._callbacks) {
|
||||
if (!callback) {
|
||||
calls[ev] = [];
|
||||
} else {
|
||||
var list = calls[ev];
|
||||
if (!list) return this;
|
||||
for (var i = 0, l = list.length; i < l; i++) {
|
||||
if (list[i] && callback === list[i][0]) {
|
||||
list[i] = null;
|
||||
break;
|
||||
}
|
||||
calls[ev] = {};
|
||||
} else if (list = node = calls[ev]) {
|
||||
while (prev = node, node = node.next) {
|
||||
if (node.callback !== callback) continue;
|
||||
prev.next = node.next;
|
||||
if (list.tail === node) list.tail = prev;
|
||||
node.context = node.callback = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,21 +106,12 @@
|
||||
// same arguments as `trigger` is, apart from the event name.
|
||||
// Listening for `"all"` passes the true event name as the first argument.
|
||||
trigger : function(eventName) {
|
||||
var list, calls, ev, callback, args;
|
||||
var both = 2;
|
||||
var node, calls, callback, args, ev, events = ['all', eventName];
|
||||
if (!(calls = this._callbacks)) return this;
|
||||
while (both--) {
|
||||
ev = both ? eventName : 'all';
|
||||
if (list = calls[ev]) {
|
||||
for (var i = 0, l = list.length; i < l; i++) {
|
||||
if (!(callback = list[i])) {
|
||||
list.splice(i, 1); i--; l--;
|
||||
} else {
|
||||
args = both ? Array.prototype.slice.call(arguments, 1) : arguments;
|
||||
callback[0].apply(callback[1] || this, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (ev = events.pop()) {
|
||||
if (!(node = calls[ev])) continue;
|
||||
args = ev == 'all' ? arguments : slice.call(arguments, 1);
|
||||
while (node = node.next) if (callback = node.callback) callback.apply(node.context || this, args);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -66,21 +66,33 @@ $(document).ready(function() {
|
||||
equals(obj.counterA, 1, 'counterA should have only been incremented once.');
|
||||
equals(obj.counterB, 1, 'counterB should have only been incremented once.');
|
||||
});
|
||||
|
||||
|
||||
test("Events: bind a callback with a supplied context", function () {
|
||||
expect(1);
|
||||
|
||||
|
||||
var TestClass = function () { return this; }
|
||||
TestClass.prototype.assertTrue = function () {
|
||||
ok(true, '`this` was bound to the callback')
|
||||
};
|
||||
|
||||
|
||||
var obj = _.extend({},Backbone.Events);
|
||||
|
||||
|
||||
obj.bind('event', function () { this.assertTrue(); }, (new TestClass));
|
||||
|
||||
|
||||
obj.trigger('event');
|
||||
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
test("Events: nested trigger with unbind", function () {
|
||||
expect(1);
|
||||
var obj = { counter: 0 };
|
||||
_.extend(obj, Backbone.Events);
|
||||
var incr1 = function(){ obj.counter += 1; obj.unbind('event', incr1); obj.trigger('event'); };
|
||||
var incr2 = function(){ obj.counter += 1; };
|
||||
obj.bind('event', incr1);
|
||||
obj.bind('event', incr2);
|
||||
obj.trigger('event');
|
||||
equals(obj.counter, 3, 'counter should have been incremented three times');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user