I create some custom events in the constructor of a KineticJS class
this.on('mouseover', this.mouseOver);
this.on('mouseout', this.mouseOut);
this.on('dblclick', this.dblclick);
When I clone this class I end up having these event listeners duplicated.
var copy = this.clone();
this.parent.add(copy);
console.log(this);
console.log(copy);
You can see the duplication if you drill down into the event listeners on my Entity class.
eventListeners: Object
dblclick: Array[2]
mouseout: Array[2]
mouseover: Array[2]
The full example is on the following jsFiddle, double click on the circle to have a copy made. http://jsfiddle.net/qQEj7/
Am I defining my event listeners incorrectly here? Is there a different way to do this when using KineticJS?
That is strange behavior.. I looked at it for a while but couldn't come up with an answer as to why clone()
was duplicating your event listeners. It looks like because of the way you structured your Kinetic.Entity
, everytime you clone()
your entity, it would clone the node like normal, but ALSO add again your defined eventListeners
(which is undesired).
Maybe this happens because when you clone()
your Entity node, it clones the eventListeners, but also calls your _initEntity
function which binds the eventListeners again??
If you call clone()
on a regular Kinetic.Shape
the issue does not occur. This tells me it probably has something to do with the way you define your eventListeners in your Kinetic.Entity
along with how it plays with the clone()
method.
In your comment above, you mentioned that you tried:
this.off('mouseover mouseout dblclick');
Well this worked for me, but it would remove the eventListeners from the original node (that you double clicked). It depends on when you called the line above though:
clone()
seems to add a set of the eventListeners you defined, thus you will end up with 2 sets of eventListeners which we didn't want.clone()
method adds a set of eventListeners.In any case, I did find a way that works so hopefully it works for you. I created a new method which adds your events:
_bindEvents: function() {
this.on('mouseover.entity', this.mouseOver);
this.on('mouseout.entity', this.mouseOut);
this.on('dblclick.entity', this.dblclick);
},
And I call this inside your _initEntity
function.
Then, for your double click event, you remove your eventListeners by calling off
on the copied node (not this - the node your clicked!), that way the original node keeps it's eventListeners, and the new node removes all eventListeners that were copied and duplicated. After remove the eventsListeners from the copied node, you can recall _bindEvents
to bind the events back in place:
dblclick: function () {
var copy = this.clone();
copy.off('.entity');
copy._bindEvents();
this.parent.add(copy);
console.log(this);
console.log(copy);
}
Here's the JSFiddle.
TIP: Notice that I named your events like this mouseover.entity
, mouseout.entity
, dblclick.entity
. This is because KineticJS allows you to name your events to group them together. Naming those events .entity
allows me to remove them all in one go by calling .off('.entity')
. This makes things cleaner, more scalable and easier to manage than calling something like .off('mouseover mouseout dblclick')
. Just think, if you added a new eventListener like mousedown
, you would also have to edit your off
function to .off('mouseover mouseout dblclick mousedown')
, and every other time you add another event!