Page 1 of 2
Disconnecting Event Handlers
Posted: 08 December 2019, 04:37
by VanHlebar
I have been struggling with this for the better part of today. I found the following items here in searching the forums:
1. this.connectClass
2. this.disconnectAll()
I have the following code in my onEnteringState function
Code: Select all
case 'placeCaballeros':
case 'client_PlayerPlaceCaballeros':
if( this.placed_meeple == false )
{
this.connectClass( '.scoring_board', 'onclick', this.clickPlaceCaballero );
this.connectClass( '.scoring_board', 'onmouseenter', this.mouseEnter );
this.connectClass( '.scoring_board', 'onmouseleave', this.mouseLeave );
}
break;
Then in my onCancelAction button function I perform the following
I do have this.connections = [] defined with my other global variables in my constructor and I have examined this array after the disconnectAll() call and it does show that it is empty. My onclick event handler is gone, but the two mouse event handlers are still firing even after the disconnectAll call. Is there something I am doing incorrectly here? How can I get the handers for the 2 mouse events to get disconnected?
Thanks,
Eric
Re: Disconnecting Event Handlers
Posted: 08 December 2019, 20:32
by vincentt
Hi,
Unless mistaken, you may need to put this.connections['toto'] = this.connectClass( '.scoring_board', 'onclick', this.clickPlaceCaballero );
Do that for each, and then try to disconnect if defined.
I remember having a discussion with Souris telling me that I should try to avoid connecting/disconnecting as it was the main reason for bugs, however we implemented it in DF (as too many things changes during the game).
Hope it works!
Vincent
Re: Disconnecting Event Handlers
Posted: 08 December 2019, 20:55
by sourisdudesert
Hi
This is generally a bad idea to connect/disconnect elements. This frequently leads to bug where elements are connected twice or not at all. It also leads players to report bugs because they clicked on something not allowed by the rules and "nothing happens".
You should connect elements only once, when they are created. Then, if an element's event is fired at a moment which is not allowed by the rule, you can display an explicit message explaining why.
This way you avoid a lot of problems

Re: Disconnecting Event Handlers
Posted: 08 December 2019, 23:11
by RicardoRix
Firstly, where are all these undocumented functions:
1. this.connectClass
2. this.disconnectAll() ?
There really shouldn't be any reason not to do this, you just need some more robust code.
I use a technique that I call an 'edge trigger' (taken from electronics). It works really well with c# properties and the setter for a property like 'Enable'. I'll write a JS version below as an example.
You can happily call this function multiple times without fear, the connect can never occur twice.
Code: Select all
setupButton: function( bEnable) // boolean
{
if (this.setupButtonEnable == bEnable)
return; // it's NOT a edge change, nothing to do..
this.setupButtonEnable = bEnable;
if (bEnable)
{
// connect
}
else
{
//disconnect.
}
}
Most of the time you don't even need a separate variable to hold the state of the enable, it's likely some other variable will be set or null or something.
Re: Disconnecting Event Handlers
Posted: 09 December 2019, 01:38
by VanHlebar
RicardoRix wrote: ↑08 December 2019, 23:11
Firstly, where are all these undocumented functions:
1. this.connectClass
2. this.disconnectAll() ?
Agreed on this. I will say that the one thing that really has frustrated me is the lack of documenation. I found the above 2 items in searching the forums here. Is there any project in place for updating the documentation at all for everything?
I will have to look at your solution. The problem that I have is that a player needs to have 3 different options when they click on a region of the map:
1. Move the King to that location
2. Move their Grande to that location
3. Place a Caballero into that region.
Yes each of these options are only available from a single State, it would be silly to display an error message for the first and second option when the user is trying to place a Caballero into a region. Once I have connected the onclick event to the div for the region for during the phase place King phase, if I don't disconnect it then it will still be there when the player moves to the next phase of the turn which is placing Caballeros.
So far my solution has been to disconnectAll() and completely remove the mouseenter/mouseleave events because I just couldn't figure out how to get them to not fire after disconnecting them all.
Thanks everyone!
Eric
Re: Disconnecting Event Handlers
Posted: 09 December 2019, 08:02
by sourisdudesert
VanHlebar wrote: ↑09 December 2019, 01:38
Firstly, where are all these undocumented functions:
1. this.connectClass
2. this.disconnectAll() ?
Well. If you look at my answer you should easily guess why they are undocumented

Re: Disconnecting Event Handlers
Posted: 09 December 2019, 10:38
by RicardoRix
Goona tackle the bull by it's horns here...
It's either:
Document the feature correctly so people know how to use it properly. (This forum thread is the case in point).
OR
It's dangerous so it shouldn't even be there. (Why are undocumented features even considered?!)
OR
Make an alternative, usable way of doing it.
Re: Disconnecting Event Handlers
Posted: 09 December 2019, 10:43
by sourisdudesert
This is not dangerous, but it is strongly discouraged.
There are plenty of functions that are undocumented because they are used internally by the framework and are not supposed to be used by game developers. This is the case on almost any framework (see Android for example).
The alternative is explained in my first message. I programmed maybe 50 games here and I never need to disconnect any event.
Re: Disconnecting Event Handlers
Posted: 09 December 2019, 11:18
by RicardoRix
Everyone has different methods and different ideas on how to do things. You should be open to that.
Just because other people employ bad practices (even if it is google) doesn't mean you should as well.
I did on my 2nd game.
I had a stock item, a playerHand, and different phases of the game I want the playerHand to trigger a different event.
This seems perfectly normal and safe to me:
Code: Select all
onUpdateActionButtons: function( stateName, args )
{
if (this.playerHand_connect != null)
dojo.disconnect(this.playerHand_connect);
switch( stateName )
{
case 'selectRiverCardFromHand' :
{
this.playerHand_connect = dojo.connect( this.playerHand, 'onChangeSelection', this, 'onSelectRiverCards' );
break;
}
case 'playCards' :
{
//note: this event gets called BOTH when a card is selected AND deselected.
this.playerHand_connect = dojo.connect( this.playerHand, 'onChangeSelection', this, 'onPlayCards' );
}
Re: Disconnecting Event Handlers
Posted: 09 December 2019, 11:41
by sourisdudesert
As I explained, we are totally open to that, but as this is not recommended we don't want to encourage that nor document that.
Sorry I don't know how to make this more clear.