fixed mouseover / mouseout incorrectly firing when moving from one node to another node inside the same container

This commit is contained in:
Eric Rowell 2012-07-06 00:27:55 -07:00
parent d28d2c910d
commit 014d4f198f
7 changed files with 223 additions and 109 deletions

62
dist/kinetic-core.js vendored
View File

@ -3,7 +3,7 @@
* http://www.kineticjs.com/
* Copyright 2012, Eric Rowell
* Licensed under the MIT or GPL Version 2 licenses.
* Date: Jul 04 2012
* Date: Jul 06 2012
*
* Copyright (C) 2011 - 2012 by Eric Rowell
*
@ -1152,8 +1152,8 @@ Kinetic.Node = Kinetic.Class.extend({
}
var stage = this.getStage();
var mouseoverNode = stage ? stage.mouseoverShape : null;
var mouseoutNode = stage ? stage.mouseoutShape : null;
var mover = stage ? stage.mouseoverShape : null;
var mout = stage ? stage.mouseoutShape : null;
var el = this.eventListeners;
var okayToRun = true;
@ -1161,26 +1161,30 @@ Kinetic.Node = Kinetic.Class.extend({
* determine if event handler should be skipped by comparing
* parent nodes
*/
if(eventType === 'mouseover' && mouseoutNode && mouseoutNode._id === this._id) {
if(eventType === 'mouseover' && mout && mout._id === this._id) {
okayToRun = false;
}
else if(eventType === 'mouseout' && mouseoverNode && mouseoverNode._id === this._id) {
else if(eventType === 'mouseout' && mover && mover._id === this._id) {
okayToRun = false;
}
if(el[eventType] && okayToRun) {
var events = el[eventType];
for(var i = 0; i < events.length; i++) {
events[i].handler.apply(this, [evt]);
if(okayToRun) {
if(el[eventType]) {
var events = el[eventType];
for(var i = 0; i < events.length; i++) {
events[i].handler.apply(this, [evt]);
}
}
}
var mouseoverParent = mouseoverNode ? mouseoverNode.parent : undefined;
var mouseoutParent = mouseoutNode ? mouseoutNode.parent : undefined;
if(stage && mover && mout) {
stage.mouseoverShape = mover.parent;
stage.mouseoutShape = mout.parent;
}
// simulate event bubbling
if(!evt.cancelBubble && this.parent && this.parent.nodeType !== 'Stage') {
this._handleEvent.call(this.parent, eventType, evt);
// simulate event bubbling
if(!evt.cancelBubble && this.parent) {
this._handleEvent.call(this.parent, eventType, evt);
}
}
}
});
@ -2705,19 +2709,6 @@ Kinetic.Layer = Kinetic.Container.extend({
}, 17);
}
},
/**
* set throttle
* @param {Number} throttle in ms
*/
setThrottle: function(throttle) {
this.attrs.throttle = throttle;
},
/**
* get throttle
*/
getThrottle: function() {
return this.attrs.throttle;
},
/**
* set before draw function handler
*/
@ -2788,7 +2779,7 @@ Kinetic.Layer = Kinetic.Container.extend({
});
// add getters and setters
Kinetic.Node.addGettersSetters(Kinetic.Layer, ['clearBeforeDraw']);
Kinetic.Node.addGettersSetters(Kinetic.Layer, ['clearBeforeDraw', 'throttle']);
/**
* set flag which determines if the layer is cleared or not
@ -2798,12 +2789,25 @@ Kinetic.Node.addGettersSetters(Kinetic.Layer, ['clearBeforeDraw']);
* @param {Boolean} clearBeforeDraw
*/
/**
* set throttle
* @name setThrottle
* @methodOf Kinetic.Layer.prototype
* @param {Number} throttle
*/
/**
* get flag which determines if the layer is cleared or not
* before drawing
* @name getClearBeforeDraw
* @methodOf Kinetic.Layer.prototype
*/
/**
* get throttle
* @name getThrottle
* @methodOf Kinetic.Layer.prototype
*/
///////////////////////////////////////////////////////////////////////
// Group
///////////////////////////////////////////////////////////////////////

File diff suppressed because one or more lines are too long

View File

@ -61,19 +61,6 @@ Kinetic.Layer = Kinetic.Container.extend({
}, 17);
}
},
/**
* set throttle
* @param {Number} throttle in ms
*/
setThrottle: function(throttle) {
this.attrs.throttle = throttle;
},
/**
* get throttle
*/
getThrottle: function() {
return this.attrs.throttle;
},
/**
* set before draw function handler
*/
@ -144,7 +131,7 @@ Kinetic.Layer = Kinetic.Container.extend({
});
// add getters and setters
Kinetic.Node.addGettersSetters(Kinetic.Layer, ['clearBeforeDraw']);
Kinetic.Node.addGettersSetters(Kinetic.Layer, ['clearBeforeDraw', 'throttle']);
/**
* set flag which determines if the layer is cleared or not
@ -154,9 +141,22 @@ Kinetic.Node.addGettersSetters(Kinetic.Layer, ['clearBeforeDraw']);
* @param {Boolean} clearBeforeDraw
*/
/**
* set throttle
* @name setThrottle
* @methodOf Kinetic.Layer.prototype
* @param {Number} throttle
*/
/**
* get flag which determines if the layer is cleared or not
* before drawing
* @name getClearBeforeDraw
* @methodOf Kinetic.Layer.prototype
*/
/**
* get throttle
* @name getThrottle
* @methodOf Kinetic.Layer.prototype
*/

View File

@ -732,8 +732,8 @@ Kinetic.Node = Kinetic.Class.extend({
}
var stage = this.getStage();
var mouseoverNode = stage ? stage.mouseoverShape : null;
var mouseoutNode = stage ? stage.mouseoutShape : null;
var mover = stage ? stage.mouseoverShape : null;
var mout = stage ? stage.mouseoutShape : null;
var el = this.eventListeners;
var okayToRun = true;
@ -741,26 +741,30 @@ Kinetic.Node = Kinetic.Class.extend({
* determine if event handler should be skipped by comparing
* parent nodes
*/
if(eventType === 'mouseover' && mouseoutNode && mouseoutNode._id === this._id) {
if(eventType === 'mouseover' && mout && mout._id === this._id) {
okayToRun = false;
}
else if(eventType === 'mouseout' && mouseoverNode && mouseoverNode._id === this._id) {
else if(eventType === 'mouseout' && mover && mover._id === this._id) {
okayToRun = false;
}
if(el[eventType] && okayToRun) {
var events = el[eventType];
for(var i = 0; i < events.length; i++) {
events[i].handler.apply(this, [evt]);
if(okayToRun) {
if(el[eventType]) {
var events = el[eventType];
for(var i = 0; i < events.length; i++) {
events[i].handler.apply(this, [evt]);
}
}
}
var mouseoverParent = mouseoverNode ? mouseoverNode.parent : undefined;
var mouseoutParent = mouseoutNode ? mouseoutNode.parent : undefined;
if(stage && mover && mout) {
stage.mouseoverShape = mover.parent;
stage.mouseoutShape = mout.parent;
}
// simulate event bubbling
if(!evt.cancelBubble && this.parent && this.parent.nodeType !== 'Stage') {
this._handleEvent.call(this.parent, eventType, evt);
// simulate event bubbling
if(!evt.cancelBubble && this.parent) {
this._handleEvent.call(this.parent, eventType, evt);
}
}
}
});

View File

@ -23,7 +23,7 @@
test.run();
document.getElementsByTagName('body')[0].addEventListener('mousemove', function(evt) {
console.log(evt.clientX + ',' + evt.clientY);
//console.log(evt.clientX + ',' + evt.clientY);
}, false);
};

View File

@ -257,7 +257,7 @@ Test.prototype.tests = {
container: containerId,
width: 578,
height: 200,
throttle: 9999
throttle: 999
});
var layer = new Kinetic.Layer();
var circle = new Kinetic.Ellipse({
@ -302,7 +302,7 @@ Test.prototype.tests = {
circle.on('mouseout', function() {
mouseout = true;
//log('mousedown');
//log('mouseout');
});
circle.on('mousemove', function() {
@ -435,7 +435,11 @@ Test.prototype.tests = {
test(!mouseout, '6) mouseout should be false');
// move mouse outside of circle to trigger mouseout
stage._mouseout({
stage._mousemove({
clientX: 0,
clientY: 100
});
stage._mousemove({
clientX: 0,
clientY: 100
});
@ -447,10 +451,10 @@ Test.prototype.tests = {
test(click, '7) click should be true');
test(dblclick, '7) dblclick should be true');
test(mouseout, '7) mouseout should be true');
/*
* mobile tests
*/
// reset inDoubleClickWindow
stage.inDoubleClickWindow = false;
@ -601,5 +605,151 @@ Test.prototype.tests = {
test(groupMousedowns === 4, 'groupMousedowns should be 4');
test(greenCircleMousedowns === 2, 'greenCircleMousedowns should be 2');
},
'EVENTS - group mouseover events': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
height: 200,
throttle: 9999
});
var layer = new Kinetic.Layer();
var group = new Kinetic.Group({
name: 'group'
});
var redMouseovers = 0;
var redMouseouts = 0;
var greenMouseovers = 0;
var greenMouseouts = 0;
var groupMouseovers = 0;
var groupMouseouts = 0;
var redEllipse = new Kinetic.Ellipse({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 80,
strokeWidth: 4,
fill: 'red',
stroke: 'black',
name: 'red'
});
var greenEllipse = new Kinetic.Ellipse({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 40,
strokeWidth: 4,
fill: 'green',
stroke: 'black',
name: 'green'
});
group.on('mouseover', function() {
groupMouseovers++;
//onsole.log('over')
});
group.on('mouseout', function() {
groupMouseouts++;
//console.log('out')
});
redEllipse.on('mouseover', function() {
redMouseovers++;
//console.log('over')
});
redEllipse.on('mouseout', function() {
redMouseouts++;
//console.log('out')
});
greenEllipse.on('mouseover', function() {
greenMouseovers++;
});
greenEllipse.on('mouseout', function() {
greenMouseouts++;
});
group.add(redEllipse);
group.add(greenEllipse);
layer.add(group);
stage.add(layer);
// move mouse outside of circles
stage._mousemove({
clientX: 177,
clientY: 146
});
test(redMouseovers === 0, 'redMouseovers should be 0');
test(redMouseouts === 0, 'redMouseouts should be 0');
test(greenMouseovers === 0, 'greenMouseovers should be 0');
test(greenMouseouts === 0, 'greenMouseouts should be 0');
test(groupMouseovers === 0, 'groupMouseovers should be 0');
test(groupMouseouts === 0, 'groupMouseouts should be 0');
// move mouse inside of red circle
stage._mousemove({
clientX: 236,
clientY: 145
});
test(redMouseovers === 1, 'redMouseovers should be 1');
test(redMouseouts === 0, 'redMouseouts should be 0');
test(greenMouseovers === 0, 'greenMouseovers should be 0');
test(greenMouseouts === 0, 'greenMouseouts should be 0');
test(groupMouseovers === 1, 'groupMouseovers should be 1');
test(groupMouseouts === 0, 'groupMouseouts should be 0');
// move mouse inside of green circle
stage._mousemove({
clientX: 284,
clientY: 118
});
test(redMouseovers === 1, 'redMouseovers should be 1');
test(redMouseouts === 1, 'redMouseouts should be 1');
test(greenMouseovers === 1, 'greenMouseovers should be 1');
test(greenMouseouts === 0, 'greenMouseouts should be 0');
test(groupMouseovers === 1, 'groupMouseovers should be 1');
test(groupMouseouts === 0, 'groupMouseouts should be 0');
// move mouse back to red circle
stage._mousemove({
clientX: 345,
clientY: 105
});
stage._mousemove({
clientX: 345,
clientY: 105
});
test(redMouseovers === 2, 'redMouseovers should be 2');
test(redMouseouts === 1, 'redMouseouts should be 1');
test(greenMouseovers === 1, 'greenMouseovers should be 1');
test(greenMouseouts === 1, 'greenMouseouts should be 1');
test(groupMouseovers === 1, 'groupMouseovers should be 1');
test(groupMouseouts === 0, 'groupMouseouts should be 0');
// move mouse outside of circles
stage._mousemove({
clientX: 177,
clientY: 146
});
stage._mousemove({
clientX: 177,
clientY: 146
});
test(redMouseovers === 2, 'redMouseovers should be 2');
test(redMouseouts === 2, 'redMouseouts should be 2');
test(greenMouseovers === 1, 'greenMouseovers should be 1');
test(greenMouseouts === 1, 'greenMouseouts should be 1');
test(groupMouseovers === 1, 'groupMouseovers should be 1');
test(groupMouseouts === 1, 'groupMouseouts should be 1');
}
};

View File

@ -622,50 +622,6 @@ Test.prototype.tests = {
layer.add(group);
stage.add(layer);
},
'EVENTS - group mouseover events': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var group = new Kinetic.Group({
name: 'group'
});
group.on('mouseover', function() {
log('mouseover group');
});
group.on('mouseout', function() {
log('mouseout group');
});
var redEllipse = new Kinetic.Ellipse({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 80,
strokeWidth: 4,
fill: 'red',
stroke: 'black',
name: 'red'
});
var greenEllipse = new Kinetic.Ellipse({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 40,
strokeWidth: 4,
fill: 'green',
stroke: 'black',
name: 'green'
});
group.add(redEllipse);
group.add(greenEllipse);
layer.add(group);
stage.add(layer);
},
'EVENTS - cancel event bubbling (only the red Ellipse should fire click event)': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,