Skip to content

Commit

Permalink
Transient listeners for drag behavior.
Browse files Browse the repository at this point in the history
Fixes d3#516.
  • Loading branch information
mbostock committed Feb 23, 2012
1 parent 74be6c1 commit d2f0e0b
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 170 deletions.
140 changes: 58 additions & 82 deletions d3.v2.js
Original file line number Diff line number Diff line change
Expand Up @@ -4607,107 +4607,83 @@ d3.behavior.drag = function() {
origin = null;

function drag() {
this
.on("mousedown.drag", mousedown)
this.on("mousedown.drag", mousedown)
.on("touchstart.drag", mousedown);

d3.select(window)
.on("mousemove.drag", d3_behavior_dragMove)
.on("touchmove.drag", d3_behavior_dragMove)
.on("mouseup.drag", d3_behavior_dragUp, true)
.on("touchend.drag", d3_behavior_dragUp, true)
.on("click.drag", d3_behavior_dragClick, true);
}

// snapshot the local context for subsequent dispatch
function start() {
d3_behavior_dragEventTarget = d3.event.target;
d3_behavior_dragEvent = event.of(d3_behavior_dragTarget = this, arguments);
d3_behavior_dragOrigin = d3_behavior_dragPoint();
function mousedown() {
var event_ = event.of(this, arguments),
eventTarget = d3.event.target,
target = this,
offset,
origin_ = point(),
moved = 0;

var w = d3.select(window)
.on("mousemove.drag", dragmove)
.on("touchmove.drag", dragmove)
.on("mouseup.drag", dragend, true)
.on("touchend.drag", dragend, true);

if (origin) {
d3_behavior_dragOffset = origin.apply(d3_behavior_dragTarget, arguments);
d3_behavior_dragOffset = [d3_behavior_dragOffset.x - d3_behavior_dragOrigin[0], d3_behavior_dragOffset.y - d3_behavior_dragOrigin[1]];
offset = origin.apply(this, arguments);
offset = [offset.x - origin_[0], offset.y - origin_[1]];
} else {
d3_behavior_dragOffset = [0, 0];
offset = [0, 0];
}
d3_behavior_dragMoved = 0;
}

function mousedown() {
start.apply(this, arguments);
d3_behavior_dragEvent({type: "dragstart"});
}

drag.origin = function(x) {
if (!arguments.length) return origin;
origin = x;
return drag;
};

return d3.rebind(drag, event, "on");
};
event_({type: "dragstart"});

var d3_behavior_dragEvent,
d3_behavior_dragEventTarget,
d3_behavior_dragTarget,
d3_behavior_dragOffset,
d3_behavior_dragOrigin,
d3_behavior_dragMoved;
function point() {
var p = target.parentNode,
t = d3.event.changedTouches;
return t ? d3.touches(p, t)[0] : d3.mouse(p);
}

function d3_behavior_dragPoint() {
var p = d3_behavior_dragTarget.parentNode,
t = d3.event.changedTouches;
return t ? d3.touches(p, t)[0] : d3.mouse(p);
}
function dragmove() {
if (!target.parentNode) return dragend(); // target removed from DOM

function d3_behavior_dragMove() {
if (!d3_behavior_dragTarget) return;
var parent = d3_behavior_dragTarget.parentNode;
var p = point(),
dx = p[0] - origin_[0],
dy = p[1] - origin_[1];

// O NOES! The drag element was removed from the DOM.
if (!parent) return d3_behavior_dragUp();
moved |= dx | dy;
origin_ = p;
d3_eventCancel();

var p = d3_behavior_dragPoint(),
dx = p[0] - d3_behavior_dragOrigin[0],
dy = p[1] - d3_behavior_dragOrigin[1];
event_({type: "drag", x: p[0] + offset[0], y: p[1] + offset[1], dx: dx, dy: dy});
}

d3_behavior_dragMoved |= dx | dy;
d3_behavior_dragOrigin = p;
d3_eventCancel();
function dragend() {
event_({type: "dragend"});

d3_behavior_dragEvent({
type: "drag",
x: p[0] + d3_behavior_dragOffset[0],
y: p[1] + d3_behavior_dragOffset[1],
dx: dx,
dy: dy
});
}
// if moved, prevent the mouseup (and possibly click) from propagating
if (moved) {
d3_eventCancel();
if (d3.event.target === eventTarget) w.on("click.drag", click, true);
}

function d3_behavior_dragUp() {
if (!d3_behavior_dragTarget) return;
d3_behavior_dragEvent({type: "dragend"});
w .on("mousemove.drag", null)
.on("touchmove.drag", null)
.on("mouseup.drag", null)
.on("touchend.drag", null);
}

// If the node was moved, prevent the mouseup from propagating.
// Also prevent the subsequent click from propagating (e.g., for anchors).
if (d3_behavior_dragMoved) {
d3_eventCancel();
d3_behavior_dragMoved = d3.event.target === d3_behavior_dragEventTarget;
// prevent the subsequent click from propagating (e.g., for anchors)
function click() {
d3_eventCancel();
w.on("click.drag", null);
}
}

d3_behavior_dragEvent =
d3_behavior_dragEventTarget =
d3_behavior_dragTarget =
d3_behavior_dragOffset =
d3_behavior_dragOrigin = null;
}
drag.origin = function(x) {
if (!arguments.length) return origin;
origin = x;
return drag;
};

function d3_behavior_dragClick() {
if (d3_behavior_dragMoved) {
d3_eventCancel();
d3_behavior_dragMoved = 0;
}
}
return d3.rebind(drag, event, "on");
};
d3.behavior.zoom = function() {
var translate = [0, 0],
translate0, // translate when we started zooming (to avoid drift)
Expand Down
Loading

0 comments on commit d2f0e0b

Please sign in to comment.