Reputation: 3607
I am using d3js drag behavior. here is demo. When I click on element the 'drag' and 'dragend' event fired. Even though I do not try to drag them, still the event fires. I want to call some other function on click of item.And drag event should be fired only when I drag item. So how to separate out drag event and click event here.
function onDragDrop(dragHandler, dropHandler) {
var drag = d3.behavior.drag();
drag.on("drag", dragHandler)
.on("dragend", dropHandler);
return drag;
}
var d = [{ x: 20, y: 20 }];
var g = d3.select("body").select("svg").data(d).append("g").attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; })
.call(onDragDrop(dragmove, dropHandler));
g.append("rect")
.attr("width", 40)
.attr("height", 40)
.attr("stroke", "red")
.attr("fill","transparent")
.attr("x", "20" )
.attr("y", "20")
g.append("text")
.text("Any Text")
.attr("x", "20" )
.attr("y", "20")
function dropHandler(d) {
alert('dropped');
}
function dragmove(d) {
alert('dragged');
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", "translate(" + d.x + "," + d.y + ")");
}
Upvotes: 3
Views: 1144
Reputation: 3607
As i did'nt get expected answer, so i am giving an alternate to acheive this. Hope somebody has some answer for it. and thanks again @jonah. if you find any update in this regard just let me know. Here is Alternate way to do this.
var d = [{ x: 20, y: 20 }];
var flag = false;
var g = d3.select("svg").data(d).append("rect")
.attr("width", 40)
.attr("height", 40)
.attr("stroke", "red")
.attr("fill","transparent")
.attr("x", "20" )
.attr("y", "20")
.on("click", function(){ console.log('clicked');})
.call(d3.behavior.drag().on("drag", dragHandler).on("dragend", dropHandler))
function dropHandler(d) {
if(flag){
console.log('dropped');
flag = false;
}}
function dragHandler(d) {
flag = true;
console.log('dragged');
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", "translate(" + d.x + "," + d.y + ")");
}
Upvotes: 1
Reputation: 16242
This is in response to your alternate answer post. The fiddle you posted there does not accurately reflect the solution I was trying to describe. I updated it. The fiddle below should be an example of the correct way to differentiate click and "true" dragend events. Note that we are not using a "click" handler.
Ok, I posted this question on the d3 google group and got an answer from Jason Davies. The behavior we're seeing is the intended behavior, it's not a bug. A "click" is simply considered a trival (0 pixels moved) drag, but it is still a drag. Mike, the creator of d3, explains the reasoning here:
https://github.com/mbostock/d3/pull/368
Hence the correct solution to your problem is the one I described as a hack before: You need to detect if a movement has actually been made inside your dragend handler, and then only trigger your logic if it has.
Please note my original answer below is wrong. I had misunderstood the problem. The comments below and my edit to the OP should clarify
The only problem here is using alert
. I changed all the alert
s to console.log
s and it works fine:
I think it's getting confused with the alerts because as soon as you start dragging, it fires the alert box, which requires you to close it. But then by the time you've closed it the mouse has jumped, and something about the process is messing things up.
Anyway, console.log with chrome or firefox js console open will fix you up nice.
Upvotes: 2