Spaces:
Sleeping
Sleeping
| import "../core/document"; | |
| import "../core/identity"; | |
| import "../core/rebind"; | |
| import "../event/drag"; | |
| import "../event/event"; | |
| import "../event/mouse"; | |
| import "../event/touch"; | |
| import "behavior"; | |
| d3.behavior.drag = function() { | |
| var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), | |
| origin = null, | |
| mousedown = dragstart(d3_noop, d3.mouse, d3_window, "mousemove", "mouseup"), | |
| touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_identity, "touchmove", "touchend"); | |
| function drag() { | |
| this.on("mousedown.drag", mousedown) | |
| .on("touchstart.drag", touchstart); | |
| } | |
| function dragstart(id, position, subject, move, end) { | |
| return function() { | |
| var that = this, | |
| target = d3.event.target.correspondingElement || d3.event.target, | |
| parent = that.parentNode, | |
| dispatch = event.of(that, arguments), | |
| dragged = 0, | |
| dragId = id(), | |
| dragName = ".drag" + (dragId == null ? "" : "-" + dragId), | |
| dragOffset, | |
| dragSubject = d3.select(subject(target)).on(move + dragName, moved).on(end + dragName, ended), | |
| dragRestore = d3_event_dragSuppress(target), | |
| position0 = position(parent, dragId); | |
| if (origin) { | |
| dragOffset = origin.apply(that, arguments); | |
| dragOffset = [dragOffset.x - position0[0], dragOffset.y - position0[1]]; | |
| } else { | |
| dragOffset = [0, 0]; | |
| } | |
| dispatch({type: "dragstart"}); | |
| function moved() { | |
| var position1 = position(parent, dragId), dx, dy; | |
| if (!position1) return; // this touch didn’t move | |
| dx = position1[0] - position0[0]; | |
| dy = position1[1] - position0[1]; | |
| dragged |= dx | dy; | |
| position0 = position1; | |
| dispatch({ | |
| type: "drag", | |
| x: position1[0] + dragOffset[0], | |
| y: position1[1] + dragOffset[1], | |
| dx: dx, | |
| dy: dy | |
| }); | |
| } | |
| function ended() { | |
| if (!position(parent, dragId)) return; // this touch didn’t end | |
| dragSubject.on(move + dragName, null).on(end + dragName, null); | |
| dragRestore(dragged); | |
| dispatch({type: "dragend"}); | |
| } | |
| }; | |
| } | |
| drag.origin = function(x) { | |
| if (!arguments.length) return origin; | |
| origin = x; | |
| return drag; | |
| }; | |
| return d3.rebind(drag, event, "on"); | |
| }; | |
| // While it is possible to receive a touchstart event with more than one changed | |
| // touch, the event is only shared by touches on the same target; for new | |
| // touches targetting different elements, multiple touchstart events are | |
| // received even when the touches start simultaneously. Since multiple touches | |
| // cannot move the same target to different locations concurrently without | |
| // tearing the fabric of spacetime, we allow the first touch to win. | |
| function d3_behavior_dragTouchId() { | |
| return d3.event.changedTouches[0].identifier; | |
| } | |