Created
March 4, 2013 09:54
-
-
Save johanlunds/5081171 to your computer and use it in GitHub Desktop.
Discussed in https://github.com/spine/spine/issues/418, diff-format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/spine.js b/lib/spine.js | |
index c0aa6dc..69821b0 100644 | |
--- a/lib/spine.js | |
+++ b/lib/spine.js | |
@@ -625,27 +625,40 @@ | |
}; | |
Model.prototype.bind = function(events, callback) { | |
- var binder, unbinder, | |
+ var binder, singleEvent, _fn, _i, _len, _ref, | |
_this = this; | |
this.constructor.bind(events, binder = function(record) { | |
if (record && _this.eql(record)) { | |
return callback.apply(_this, arguments); | |
} | |
}); | |
- this.constructor.bind('unbind', unbinder = function(record) { | |
- if (record && _this.eql(record)) { | |
- _this.constructor.unbind(events, binder); | |
- return _this.constructor.unbind('unbind', unbinder); | |
- } | |
- }); | |
- return binder; | |
+ _ref = events.split(' '); | |
+ _fn = function(singleEvent) { | |
+ var unbinder; | |
+ return _this.constructor.bind("unbind", unbinder = function(record, event, cb) { | |
+ if (record && _this.eql(record)) { | |
+ if (event && event !== singleEvent) { | |
+ return; | |
+ } | |
+ if (cb && cb !== callback) { | |
+ return; | |
+ } | |
+ _this.constructor.unbind(event, binder); | |
+ return _this.constructor.unbind("unbind", unbinder); | |
+ } | |
+ }); | |
+ }; | |
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |
+ singleEvent = _ref[_i]; | |
+ _fn(singleEvent); | |
+ } | |
+ return this; | |
}; | |
Model.prototype.one = function(events, callback) { | |
- var binder, | |
- _this = this; | |
- return binder = this.bind(events, function() { | |
- _this.constructor.unbind(events, binder); | |
+ var _this = this; | |
+ return this.bind(events, function() { | |
+ _this.unbind(events, arguments.callee); | |
return callback.apply(_this, arguments); | |
}); | |
}; | |
@@ -657,8 +670,19 @@ | |
return (_ref = this.constructor).trigger.apply(_ref, args); | |
}; | |
- Model.prototype.unbind = function() { | |
- return this.trigger('unbind'); | |
+ Model.prototype.unbind = function(events, callback) { | |
+ var event, _i, _len, _ref, _results; | |
+ if (events) { | |
+ _ref = events.split(' '); | |
+ _results = []; | |
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) { | |
+ event = _ref[_i]; | |
+ _results.push(this.trigger('unbind', event, callback)); | |
+ } | |
+ return _results; | |
+ } else { | |
+ return this.trigger('unbind'); | |
+ } | |
}; | |
return Model; | |
diff --git a/src/spine.coffee b/src/spine.coffee | |
index 650a945..e0e0cbf 100644 | |
--- a/src/spine.coffee | |
+++ b/src/spine.coffee | |
@@ -38,7 +38,7 @@ Events = | |
delete @_callbacks[name] | |
continue | |
- for cb, i in list when cb is callback | |
+ for cb, i in list when (cb is callback) | |
list = list.slice() | |
list.splice(i, 1) | |
@_callbacks[name] = list | |
@@ -376,23 +376,32 @@ class Model extends Module | |
@constructor.bind events, binder = (record) => | |
if record && @eql(record) | |
callback.apply(this, arguments) | |
- @constructor.bind 'unbind', unbinder = (record) => | |
- if record && @eql(record) | |
- @constructor.unbind(events, binder) | |
- @constructor.unbind('unbind', unbinder) | |
- binder | |
+ # create a wrapper function to be called with 'unbind' for each event | |
+ for singleEvent in events.split(' ') | |
+ do (singleEvent) => | |
+ @constructor.bind "unbind", unbinder = (record, event, cb) => | |
+ if record && @eql(record) | |
+ return if event and event isnt singleEvent | |
+ return if cb and cb isnt callback | |
+ @constructor.unbind(event, binder) | |
+ @constructor.unbind("unbind", unbinder) | |
+ this | |
one: (events, callback) -> | |
- binder = @bind events, => | |
- @constructor.unbind(events, binder) | |
+ @bind events, => | |
+ @unbind(events, arguments.callee) | |
callback.apply(this, arguments) | |
trigger: (args...) -> | |
args.splice(1, 0, this) | |
@constructor.trigger(args...) | |
- unbind: -> | |
- @trigger('unbind') | |
+ unbind: (events, callback) -> | |
+ if events | |
+ for event in events.split(' ') | |
+ @trigger('unbind', event, callback) | |
+ else | |
+ @trigger('unbind') | |
class Controller extends Module | |
@include Events | |
diff --git a/test/specs/model.js b/test/specs/model.js | |
index 608e792..423b458 100644 | |
--- a/test/specs/model.js | |
+++ b/test/specs/model.js | |
@@ -453,7 +453,7 @@ describe("Model", function(){ | |
asset.updateAttributes({name: "lonely heart.png"}); | |
}); | |
- it("should be able to unbind instance events", function(){ | |
+ it("should be able to unbind all instance events", function(){ | |
var asset = Asset.create({name: "cartoon world.png"}); | |
asset.bind("save", spy); | |
@@ -462,6 +462,62 @@ describe("Model", function(){ | |
expect(spy).not.toHaveBeenCalled(); | |
}); | |
+ | |
+ it("should be able to unbind individual instance events", function(){ | |
+ var asset = Asset.create({name: "cartoon world.png"}); | |
+ | |
+ asset.bind("save", spy); | |
+ asset.bind("customEvent", spy); | |
+ asset.unbind('save'); | |
+ asset.save(); | |
+ expect(spy).not.toHaveBeenCalled(); | |
+ asset.trigger('customEvent'); | |
+ expect(spy).toHaveBeenCalled(); | |
+ }); | |
+ | |
+ it("should be able to unbind individual callbacks to individual instance events", function(){ | |
+ var asset = Asset.create({name: "cartoon world.png"}); | |
+ var noop2 = {spy2: function(){}}; | |
+ spyOn(noop2, "spy2"); | |
+ var spy2 = noop2.spy2; | |
+ asset.bind("customEvent", spy); | |
+ asset.bind("customEvent", spy2); | |
+ asset.trigger("customEvent"); | |
+ expect(spy).toHaveBeenCalled(); | |
+ expect(spy2).toHaveBeenCalled(); | |
+ spy.reset(); | |
+ spy2.reset(); | |
+ asset.unbind("customEvent", spy2); | |
+ asset.trigger('customEvent'); | |
+ expect(spy).toHaveBeenCalled(); | |
+ expect(spy2).not.toHaveBeenCalled(); | |
+ }); | |
+ | |
+ it("should be able to unbind a single event that uses a callback another event is bind to.", function(){ | |
+ var asset = Asset.create({name: "cartoon world.png"}); | |
+ asset.bind("customEvent1 customEvent2", spy); | |
+ asset.trigger("customEvent1"); | |
+ asset.trigger("customEvent2"); | |
+ expect(spy.calls.length).toEqual(2); | |
+ spy.reset(); | |
+ asset.unbind("customEvent1"); | |
+ asset.trigger("customEvent1"); | |
+ asset.trigger("customEvent2"); | |
+ expect(spy.calls.length).toEqual(1); | |
+ }); | |
+ | |
+ it("should be able to bind and unbind multiple events with a single call.", function(){ | |
+ var asset = Asset.create({name: "cartoon world.png"}); | |
+ asset.bind("customEvent1 customEvent2", spy) | |
+ asset.trigger("customEvent1"); | |
+ asset.trigger("customEvent2"); | |
+ expect(spy.calls.length).toEqual(2); | |
+ spy.reset(); | |
+ asset.unbind("customEvent1 customEvent2") | |
+ asset.trigger("customEvent1"); | |
+ asset.trigger("customEvent2"); | |
+ expect(spy.calls.length).toEqual(0); | |
+ }); | |
it("should unbind events on instance destroy", function(){ | |
var asset = Asset.create({name: "cartoon world.png"}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment