I am relatively new to d3, and I'm still bumping into things that stump me.
Basically, I have a tree with draggable nodes. I want to restrict the "drag handle" of the nodes to only the circle, not the circle and text (and whatever else I end up adding).
I know that it has something to do with properly setting the origin in my drag behavior, but I just can't quite seem to get it.
I've found some useful information here on stackoverflow (sorry, I can only post two links), and looking at https://groups.google.com/forum/#!topic/d3-js/fjp1mpvVW1M it appears that I'm applying the drag behavior to a child element of a g container and then trying to apply the transform to its g container.
How can I accomplish this?
here's the relevant code:
var dragListener = d3.behavior.drag()
.origin(function () {
var t = d3.select(this);
return {
x: t.attr("x") + d3.transform(t.attr("transform")).translate[0],
y: t.attr("y") + d3.transform(t.attr("transform")).translate[1]
};
})
.on("drag", function (d) {
d.x0 += d3.event.dy;
d.y0 += d3.event.dx;
//var node = d3.select(this); //this works
var node = d3.select(this.parentNode) //this doesn't work
node.attr("transform", "translate(" + d.y0 + "," + d.x0 + ")");
});
var nodeEnter = node.enter().append("g")
//.call(dragListener) // this works
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
.on("click", click);
nodeEnter.append("circle")
.call(dragListener) // this doesn't work
.attr("r", 1e-6)
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
Here's a fiddle: http://jsfiddle.net/tsmith77/4R3Cb/
UPDATE
I wasn't able to get the child group to do what I wanted, but I accomplished what I want by intercepting the mousedown event on the text:
nodeEnter.append("text")
.on("mousedown", function (d) {
d3.event.stopPropagation();
})
.on("click", function (d) {
alert("text clicked");
})
This prevents the text from being a drag handle, but still allows me to perform an action when the text is clicked.