I have a node in KineticJs that has both a drag handler and double-click handler on it. When a user attempts to double-click on the object and moves slightly during the initial click, the drag handler intercepts what would be the double-click, breaking the experience. I have googled this extensively and have tried many solutions to no avail. This issue is captured in the link below but no update has been made to kinetic.
https://github.com/ericdrowell/KineticJS/issues/243
Example Code:
shape.on("dblclick dbltap", function (pos) {
ModalWindow(this.parent.data,pos); //Loads a modal window
});
shape.on("mousedown",function(e) {
this.setDraggable(false);
var that = this;
console.log("Drag Off");
setTimeout(function(){
that.setDraggable(true);
console.log("Drag On");
},1000);
});
Determining Drag vs Click is a common problem.
One common way to handle the conflict is:
dragstart
save the starting position of the nodedragend
check if the node has moved less than 10 pixels (or whatever distance)click
eventHere's example code and a Demo: http://jsfiddle.net/m1erickson/yh67y/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.0.1.min.js"></script>
<style>
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
</style>
<script>
$(function(){
$p=$("#event");
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
var circle1 = new Kinetic.Circle({
x:100,
y:100,
radius: 30,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
draggable: true
});
circle1.startingPos;
circle1.referredEvent="";
circle1.on("dragstart",function(){
this.startingPos=this.position();
});
circle1.on("dragend",function(){
var endingPos=this.position();
var dx=Math.abs(endingPos.x-this.startingPos.x);
var dy=Math.abs(endingPos.y-this.startingPos.y);
if(dx<10 && dy<10){
this.position(this.startingPos);
this.referredEvent="--from drag";
this.fire("click");
layer.draw();
}
});
circle1.on("click",function(){
$p.text("clicked"+this.referredEvent);
this.referredEvent="";
});
layer.add(circle1);
layer.draw();
}); // end $(function(){});
</script>
</head>
<body>
<h4>Drags less than 10 pixels will cause click<br>instead of drag.</h4>
<p id="event">Drag or Click the circle</p>
<div id="container"></div>
</body>
</html>
Now for double-tapping:
Since the referred click won't count towards one of the taps of a double-tap, you will have to save the time each click occurs (in the click event handler). If you have 2 clicks within a half-second (or whatever time limit) then trigger the doubletap event--this.fire("doubletap");
And Yes...this all sounds like a hack.
But the fact is a mousedown can equally signal a click or a drag.
This is the best workaround we've got.