Skip to content

Instantly share code, notes, and snippets.

@johanlunds
Created March 4, 2013 09:55
Show Gist options
  • Save johanlunds/5081176 to your computer and use it in GitHub Desktop.
Save johanlunds/5081176 to your computer and use it in GitHub Desktop.
Discussed in https://github.com/spine/spine/issues/418, patch-format
From 863f316336dae0af7b418d30b40959b5fdd9dcba Mon Sep 17 00:00:00 2001
From: aeischeid <a.eischeid@gmail.com>
Date: Wed, 20 Feb 2013 11:42:46 -0600
Subject: [PATCH 01/10] wild stab at a test for instance individual events
unbinding
---
test/specs/model.js | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/test/specs/model.js b/test/specs/model.js
index 608e792..d1d9477 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,16 @@ 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, refresh, change", spy);
+ asset.unbind('save');
+ asset.save();
+
+ expect(spy).not.toHaveBeenCalled();
+ });
it("should unbind events on instance destroy", function(){
var asset = Asset.create({name: "cartoon world.png"});
--
1.7.10
From 28053c4d1d1fe9b78ad9c17b00e12a060e582e72 Mon Sep 17 00:00:00 2001
From: aeischeid <a.eischeid@gmail.com>
Date: Wed, 20 Feb 2013 11:59:20 -0600
Subject: [PATCH 02/10] more better tests that fail for the model instance
unbinder
---
test/specs/model.js | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/test/specs/model.js b/test/specs/model.js
index d1d9477..a4e57fb 100644
--- a/test/specs/model.js
+++ b/test/specs/model.js
@@ -466,11 +466,22 @@ describe("Model", function(){
it("should be able to unbind individual instance events", function(){
var asset = Asset.create({name: "cartoon world.png"});
- asset.bind("save, refresh, change", spy);
+ asset.bind("save, 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"});
+ asset.bind("customEvent", spy);
+ asset.bind("customEvent", spy2);
+ asset.unbind("customEvent", spy2);
+ asset.trigger('customEvent');
+ expect(spy).toHaveBeenCalled();
+ expect(spy2).not.toHaveBeenCalled();
});
it("should unbind events on instance destroy", function(){
--
1.7.10
From 7af20a9099b39d5f7cad2530eaa6e9709613eb77 Mon Sep 17 00:00:00 2001
From: aeischeid <a.eischeid@gmail.com>
Date: Wed, 20 Feb 2013 12:18:07 -0600
Subject: [PATCH 03/10] forgot to define spy2 for test
---
test/specs/model.js | 3 +++
1 file changed, 3 insertions(+)
diff --git a/test/specs/model.js b/test/specs/model.js
index a4e57fb..f5f1583 100644
--- a/test/specs/model.js
+++ b/test/specs/model.js
@@ -476,6 +476,9 @@ describe("Model", function(){
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.unbind("customEvent", spy2);
--
1.7.10
From 0968b36c3332b250a95138aadd23ed5f83fa552b Mon Sep 17 00:00:00 2001
From: aeischeid <a.eischeid@gmail.com>
Date: Wed, 20 Feb 2013 11:42:46 -0600
Subject: [PATCH 04/10] wild stab at a test for instance individual events
unbinding
---
test/specs/model.js | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/test/specs/model.js b/test/specs/model.js
index 608e792..d1d9477 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,16 @@ 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, refresh, change", spy);
+ asset.unbind('save');
+ asset.save();
+
+ expect(spy).not.toHaveBeenCalled();
+ });
it("should unbind events on instance destroy", function(){
var asset = Asset.create({name: "cartoon world.png"});
--
1.7.10
From 72ba480d0d0e8570044d3d1710e6ee7c5f486895 Mon Sep 17 00:00:00 2001
From: aeischeid <a.eischeid@gmail.com>
Date: Wed, 20 Feb 2013 11:59:20 -0600
Subject: [PATCH 05/10] more better tests that fail for the model instance
unbinder
---
test/specs/model.js | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/test/specs/model.js b/test/specs/model.js
index d1d9477..a4e57fb 100644
--- a/test/specs/model.js
+++ b/test/specs/model.js
@@ -466,11 +466,22 @@ describe("Model", function(){
it("should be able to unbind individual instance events", function(){
var asset = Asset.create({name: "cartoon world.png"});
- asset.bind("save, refresh, change", spy);
+ asset.bind("save, 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"});
+ asset.bind("customEvent", spy);
+ asset.bind("customEvent", spy2);
+ asset.unbind("customEvent", spy2);
+ asset.trigger('customEvent');
+ expect(spy).toHaveBeenCalled();
+ expect(spy2).not.toHaveBeenCalled();
});
it("should unbind events on instance destroy", function(){
--
1.7.10
From fe96cb4ebd41e49e9e050f58d3f58602d72de5be Mon Sep 17 00:00:00 2001
From: aeischeid <a.eischeid@gmail.com>
Date: Wed, 20 Feb 2013 12:18:07 -0600
Subject: [PATCH 06/10] forgot to define spy2 for test
---
test/specs/model.js | 3 +++
1 file changed, 3 insertions(+)
diff --git a/test/specs/model.js b/test/specs/model.js
index a4e57fb..f5f1583 100644
--- a/test/specs/model.js
+++ b/test/specs/model.js
@@ -476,6 +476,9 @@ describe("Model", function(){
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.unbind("customEvent", spy2);
--
1.7.10
From d8e5d360a4439bd5d9f6365e249a199fa2410aa3 Mon Sep 17 00:00:00 2001
From: Chris Engebretson <cengebretson@globalvetlink.com>
Date: Wed, 20 Feb 2013 14:31:16 -0600
Subject: [PATCH 07/10] first stab at getting unbind to work at the instance
level, man that was a pain!
---
lib/spine.js | 14 ++++++++------
src/spine.coffee | 15 ++++++++-------
test/specs/model.js | 3 ++-
3 files changed, 18 insertions(+), 14 deletions(-)
diff --git a/lib/spine.js b/lib/spine.js
index c0aa6dc..0127f33 100644
--- a/lib/spine.js
+++ b/lib/spine.js
@@ -632,10 +632,12 @@
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);
+ this.constructor.bind("unbind", unbinder = function(record, event, cb) {
+ if (record && _this.eql(record) && (!event || events === event)) {
+ if (!cb || cb === callback) {
+ _this.constructor.unbind(events, binder);
+ return _this.constructor.unbind("unbind", unbinder);
+ }
}
});
return binder;
@@ -657,8 +659,8 @@
return (_ref = this.constructor).trigger.apply(_ref, args);
};
- Model.prototype.unbind = function() {
- return this.trigger('unbind');
+ Model.prototype.unbind = function(events, callback) {
+ return this.trigger('unbind', events, callback);
};
return Model;
diff --git a/src/spine.coffee b/src/spine.coffee
index 650a945..5ed952a 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,10 +376,11 @@ 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)
+ @constructor.bind "unbind", unbinder = (record, event, cb) =>
+ if record && @eql(record) and (not event or events is event)
+ if not cb or cb is callback
+ @constructor.unbind(events, binder)
+ @constructor.unbind("unbind", unbinder)
binder
one: (events, callback) ->
@@ -391,8 +392,8 @@ class Model extends Module
args.splice(1, 0, this)
@constructor.trigger(args...)
- unbind: ->
- @trigger('unbind')
+ unbind: (events, callback) ->
+ @trigger('unbind', events, callback)
class Controller extends Module
@include Events
diff --git a/test/specs/model.js b/test/specs/model.js
index f5f1583..20e9fe5 100644
--- a/test/specs/model.js
+++ b/test/specs/model.js
@@ -466,7 +466,8 @@ describe("Model", function(){
it("should be able to unbind individual instance events", function(){
var asset = Asset.create({name: "cartoon world.png"});
- asset.bind("save, customEvent", spy);
+ asset.bind("save", spy);
+ asset.bind("customEvent", spy);
asset.unbind('save');
asset.save();
expect(spy).not.toHaveBeenCalled();
--
1.7.10
From b1fe152d21816c7296bf0b242a71666624696bed Mon Sep 17 00:00:00 2001
From: Chris Engebretson <cengebretson@globalvetlink.com>
Date: Wed, 20 Feb 2013 18:31:35 -0600
Subject: [PATCH 08/10] should be able to use bind and unbind with multiple
events. Also bind/one should return the this object.
---
lib/spine.js | 48 +++++++++++++++++++++++++++++++++++-------------
src/spine.coffee | 25 ++++++++++++++++---------
test/specs/model.js | 31 +++++++++++++++++++++++++++++++
3 files changed, 82 insertions(+), 22 deletions(-)
diff --git a/lib/spine.js b/lib/spine.js
index 0127f33..c5d3f77 100644
--- a/lib/spine.js
+++ b/lib/spine.js
@@ -625,29 +625,40 @@
};
Model.prototype.bind = function(events, callback) {
- var binder, unbinder,
+ var binder, evs, _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, event, cb) {
- if (record && _this.eql(record) && (!event || events === event)) {
- if (!cb || cb === callback) {
- _this.constructor.unbind(events, binder);
+ _ref = events.split(' ');
+ _fn = function(evs) {
+ var unbinder;
+ return _this.constructor.bind("unbind", unbinder = function(record, event, cb) {
+ if (record && _this.eql(record)) {
+ if (event && event !== evs) {
+ return;
+ }
+ if (cb && cb !== callback) {
+ return;
+ }
+ _this.constructor.unbind(event, binder);
return _this.constructor.unbind("unbind", unbinder);
}
- }
- });
- return binder;
+ });
+ };
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ evs = _ref[_i];
+ _fn(evs);
+ }
+ 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);
});
};
@@ -660,7 +671,18 @@
};
Model.prototype.unbind = function(events, callback) {
- return this.trigger('unbind', 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 5ed952a..2311694 100644
--- a/src/spine.coffee
+++ b/src/spine.coffee
@@ -376,16 +376,19 @@ class Model extends Module
@constructor.bind events, binder = (record) =>
if record && @eql(record)
callback.apply(this, arguments)
- @constructor.bind "unbind", unbinder = (record, event, cb) =>
- if record && @eql(record) and (not event or events is event)
- if not cb or cb is callback
- @constructor.unbind(events, binder)
- @constructor.unbind("unbind", unbinder)
- binder
+ for evs in events.split(' ')
+ do (evs) =>
+ @constructor.bind "unbind", unbinder = (record, event, cb) =>
+ if record && @eql(record)
+ return if event and event isnt evs
+ 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...) ->
@@ -393,7 +396,11 @@ class Model extends Module
@constructor.trigger(args...)
unbind: (events, callback) ->
- @trigger('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 20e9fe5..423b458 100644
--- a/test/specs/model.js
+++ b/test/specs/model.js
@@ -482,12 +482,43 @@ describe("Model", function(){
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"});
--
1.7.10
From 80e7a3fc26a462b6909befa46ab1196f412751db Mon Sep 17 00:00:00 2001
From: Chris Engebretson <cengebretson@globalvetlink.com>
Date: Thu, 21 Feb 2013 18:30:56 -0600
Subject: [PATCH 09/10] better variable name
---
src/spine.coffee | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/spine.coffee b/src/spine.coffee
index 2311694..e0e0cbf 100644
--- a/src/spine.coffee
+++ b/src/spine.coffee
@@ -376,11 +376,12 @@ class Model extends Module
@constructor.bind events, binder = (record) =>
if record && @eql(record)
callback.apply(this, arguments)
- for evs in events.split(' ')
- do (evs) =>
+ # 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 evs
+ return if event and event isnt singleEvent
return if cb and cb isnt callback
@constructor.unbind(event, binder)
@constructor.unbind("unbind", unbinder)
--
1.7.10
From 6efd7bbf31e0256c465bc0bf0f020838ee0316a3 Mon Sep 17 00:00:00 2001
From: Chris Engebretson <cengebretson@globalvetlink.com>
Date: Thu, 21 Feb 2013 18:31:09 -0600
Subject: [PATCH 10/10] new spine.js build
---
lib/spine.js | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/lib/spine.js b/lib/spine.js
index c5d3f77..69821b0 100644
--- a/lib/spine.js
+++ b/lib/spine.js
@@ -625,7 +625,7 @@
};
Model.prototype.bind = function(events, callback) {
- var binder, evs, _fn, _i, _len, _ref,
+ var binder, singleEvent, _fn, _i, _len, _ref,
_this = this;
this.constructor.bind(events, binder = function(record) {
if (record && _this.eql(record)) {
@@ -633,11 +633,11 @@
}
});
_ref = events.split(' ');
- _fn = function(evs) {
+ _fn = function(singleEvent) {
var unbinder;
return _this.constructor.bind("unbind", unbinder = function(record, event, cb) {
if (record && _this.eql(record)) {
- if (event && event !== evs) {
+ if (event && event !== singleEvent) {
return;
}
if (cb && cb !== callback) {
@@ -649,8 +649,8 @@
});
};
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- evs = _ref[_i];
- _fn(evs);
+ singleEvent = _ref[_i];
+ _fn(singleEvent);
}
return this;
};
--
1.7.10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment