Skip to content

Instantly share code, notes, and snippets.

@johanlunds
Created March 4, 2013 09:54
Show Gist options
  • Save johanlunds/5081171 to your computer and use it in GitHub Desktop.
Save johanlunds/5081171 to your computer and use it in GitHub Desktop.
Discussed in https://github.com/spine/spine/issues/418, diff-format
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