Skip to content

Commit

Permalink
Re-adopt d3-dispatch.
Browse files Browse the repository at this point in the history
Also, use d3.customEvent for drag and dragend for consistency with dragstart.
  • Loading branch information
mbostock committed May 6, 2016
1 parent 0737a6a commit 48792de
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 24 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
If you use NPM, `npm install d3-drag`. Otherwise, download the [latest release](https://github.com/d3/d3-drag/releases/latest). You can also load directly from [d3js.org](https://d3js.org), either as a [standalone library](https://d3js.org/d3-drag.v0.0.min.js) or as part of [D3 4.0 alpha](https://github.com/mbostock/d3/tree/4). AMD, CommonJS, and vanilla environments are supported. In vanilla, a `d3_drag` global is exported:

```html
<script src="https://d3js.org/d3-dispatch.v0.4.min.js"></script>
<script src="https://d3js.org/d3-selection.v0.7.min.js"></script>
<script src="https://d3js.org/d3-drag.v0.0.min.js"></script>
<script>
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"postpublish": "VERSION=`node -e 'console.log(require(\"./package.json\").version)'`; git push && git push --tags && cp build/d3-drag.js ../d3.github.com/d3-drag.v0.0.js && cp build/d3-drag.min.js ../d3.github.com/d3-drag.v0.0.min.js && cd ../d3.github.com && git add d3-drag.v0.0.js d3-drag.v0.0.min.js && git commit -m \"d3-drag ${VERSION}\" && git push && cd - && zip -j build/d3-drag.zip -- LICENSE README.md build/d3-drag.js build/d3-drag.min.js"
},
"dependencies": {
"d3-dispatch": "~0.4.3",
"d3-selection": "~0.7.2"
},
"devDependencies": {
Expand Down
59 changes: 36 additions & 23 deletions src/drag.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import constant from "./constant";
import noop from "./noop";
import {dispatch} from "d3-dispatch";
import {event, customEvent, select, mouse, touch} from "d3-selection";

function nodefault() {
Expand Down Expand Up @@ -29,13 +29,14 @@ function touchContext() {
return event.target;
}

export default function(dragstarted) {
export default function() {
var x = null,
y = null,
filter = defaultFilter,
container = defaultContainer,
mousestart = start("mousemove", "mouseup", mouse, mouseContext),
touchstart = start("touchmove", "touchend touchcancel", touch, touchContext);
touchstart = start("touchmove", "touchend touchcancel", touch, touchContext),
listeners = dispatch("dragstart", "drag", "dragend");

function drag(selection) {
selection
Expand All @@ -53,60 +54,67 @@ export default function(dragstarted) {
}
}

function start(move, end, position, contextify) {
function start(move, end, pointer, contextify) {
return function(that, args, id) {
var parent,
p0,
dx,
dy;

// You can’t listen for the beforedragstart event explicitly, but it’s
// needed to expose the current identifier to accessors via d3.event.

if (!customEvent({type: "beforedragstart", identifier: id}, function() {
if (filter.apply(that, args)) {
parent = container.apply(that, args);
p0 = position(parent, id);
p0 = pointer(parent, id);
dx = x == null ? 0 : x.apply(that, args) - p0[0];
dy = y == null ? 0 : y.apply(that, args) - p0[1];
return true;
}
})) return;

var listen = customEvent({type: "dragstart", identifier: id, x: p0[0] + dx, y: p0[1] + dy}, dragstarted, that, args) || noop,
dragged = typeof listen === "function" ? listen : listen.drag || noop,
dragended = listen.dragend || noop,
noclick = false,
view = select(event.view).on(name("dragstart selectstart"), nodefault, true),
context = select(contextify.apply(that, args)).on(name(move), moved).on(name(end), ended);

// I’d like to call preventDefault on mousedown to disable native dragging
// of links or images and native text selection. However, in Chrome this
// causes mousemove and mouseup events outside an iframe to be dropped:
// https://bugs.chromium.org/p/chromium/issues/detail?id=269917
// And if you preventDefault on touchstart on iOS, it prevents the click
// event on touchend, even if there was no touchmove! So instead, we
// cancel the specific undesirable behaviors.
// cancel the specific undesirable behaviors. If you want to change this
// behavior, you can unregister these listeners on dragstart.

var sublisteners = listeners.copy(),
startevent = {type: "dragstart", identifier: id, x: p0[0] + dx, y: p0[1] + dy, on: on},
view = select(event.view).on(name("dragstart selectstart"), nodefault, true),
context = select(contextify.apply(that, args)).on(name(move), moved).on(name(end), ended),
noclick = false;

customEvent(startevent, sublisteners.apply, sublisteners, ["dragstart", that, args]);

function on() {
var value = sublisteners.on.apply(sublisteners, arguments);
return value === sublisteners ? startevent : value;
}

function name(types) {
var name = id == null ? ".drag" : ".drag-" + id;
return types == null ? name : types.trim()
.split(/^|\s+/)
.map(function(type) { return type + name; })
.join(" ");
return types == null ? name : types.trim().split(/^|\s+/).map(function(type) { return type + name; }).join(" ");
}

function moved() {
var p = position(parent, id);
if (p == null) return; // This touch didn’t change.
var p = pointer(parent, id);
if (p == null) return; // This pointer didn’t change.
nodefault(), noclick = true;
dragged.call(that, p[0] + dx, p[1] + dy);
customEvent({type: "drag", x: p[0] + dx, y: p[1] + dy, identifier: id}, sublisteners.apply, sublisteners, ["drag", that, args]);
}

function ended() {
var p = position(parent, id);
if (p == null) return; // This touch didn’t end.
var p = pointer(parent, id);
if (p == null) return; // This pointer didn’t end.
view.on(name(), null);
context.on(name(), null);
if (noclick) view.on(name("click"), nodefault, true), setTimeout(afterended, 0);
dragended.call(that, p[0] + dx, p[1] + dy);
customEvent({type: "dragend", x: p[0] + dx, y: p[1] + dy, identifier: id}, sublisteners.apply, sublisteners, ["dragend", that, args]);
}

function afterended() {
Expand All @@ -131,5 +139,10 @@ export default function(dragstarted) {
return arguments.length ? (y = typeof _ === "function" ? _ : constant(+_), drag) : y;
};

drag.on = function() {
var value = listeners.on.apply(listeners, arguments);
return value === listeners ? drag : value;
};

return drag;
}
1 change: 0 additions & 1 deletion src/noop.js

This file was deleted.

0 comments on commit 48792de

Please sign in to comment.