2

I am using spine javascript library for a standalone javascript application. I heavily use the publisher/subscriber model and bind proxied callbacks to spine models. When I try to unbind a proxied callback, it doesnt unbind it. This happens only with proxied callbacks. A demo code

var Listener = Spine.Model.sub({
onChange : function(){this.log("Hooray!!")},
log:function(msg){console.log("Rxed event"+msg);},
bind: function(){SomeModel.bind("onChange",this.proxy(this.onChange));},
unBind:function(){SomeModel.unbind("onChange",this.proxy(this.onChange));}
 });

var listener = new Listener();

when listener.bind() is called it binds it correctly and callbacks are correct. but when listener.unBind() is called, the unbind doesnt happen.

If the callback was not proxied, it works but I need the correct context for the callback and so I need to proxy it.

Any help would be greatly appreciated.

Neysor
  • 3,893
  • 11
  • 34
  • 66

1 Answers1

0

You should do Spine.Class.sub since you don't need a model. Secondly, change the unbind to: SomeModel.unbind("onChange");. This way all callbacks are cleared. But you are right ... if you wrap the unbind with or without the proxy call it won't work. So I hope you don't have a need to unbind specific callbacks.

I made a jsfiddle to easily test it: http://jsfiddle.net/SpoBo/cmUmT/2/

edit: http://jsfiddle.net/SpoBo/cmUmT/3/ By using underscore's bindAll functionality it works. I guess the proxy does something odd which prevents the unbind function from successfully comparing callbacks.

http://jsfiddle.net/SpoBo/cmUmT/7/ It's recommended to use CoffeeScript though to write Spine and CS has a solution of itself for this problem. Just use the 'fat arrows'. However, if you can't use CS you can just use the code that CS generates. I solved it this way in version 7.

Basically, it creates a __bind function which returns a proxied function from a closure. After that you override the original function with the proxied function.

__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }

someObject.onChange = __bind(someObject.onChange, someObject);

And now onChange will always be called from the context of someObject. Pretty cool stuff! But check the jsFiddle for a working demo.

SpoBo
  • 2,100
  • 2
  • 20
  • 28
  • Thanks for the reply. The issue is I need to unbind specific callbacks as there could be more than one callback attached to the same model. SomeModel.unbind("onChange"); will unbind all the callbacks – user1280645 Mar 21 '12 at 13:16
  • Yes.. This works. Thanks a lot.It would have been great if Spine added support for this. – user1280645 Mar 22 '12 at 12:13
  • check solution 3 that uses the underscore library. it's pretty small syntax wise and very readable. it's how they do it for backbonejs. The 'official' solution is to just use CoffeeScript. And because of this a feature like this will probably never be included. I really recommend learning it though as it will save you lots of time and frustration :) – SpoBo Mar 23 '12 at 18:58