source: node_modules/d3-drag/src/drag.js

Last change on this file was e4c61dd, checked in by istevanoska <ilinastevanoska@…>, 6 months ago

Prototype 1.1

  • Property mode set to 100644
File size: 5.4 KB
RevLine 
[e4c61dd]1import {dispatch} from "d3-dispatch";
2import {select, pointer} from "d3-selection";
3import nodrag, {yesdrag} from "./nodrag.js";
4import noevent, {nonpassive, nonpassivecapture, nopropagation} from "./noevent.js";
5import constant from "./constant.js";
6import DragEvent from "./event.js";
7
8// Ignore right-click, since that should open the context menu.
9function defaultFilter(event) {
10 return !event.ctrlKey && !event.button;
11}
12
13function defaultContainer() {
14 return this.parentNode;
15}
16
17function defaultSubject(event, d) {
18 return d == null ? {x: event.x, y: event.y} : d;
19}
20
21function defaultTouchable() {
22 return navigator.maxTouchPoints || ("ontouchstart" in this);
23}
24
25export default function() {
26 var filter = defaultFilter,
27 container = defaultContainer,
28 subject = defaultSubject,
29 touchable = defaultTouchable,
30 gestures = {},
31 listeners = dispatch("start", "drag", "end"),
32 active = 0,
33 mousedownx,
34 mousedowny,
35 mousemoving,
36 touchending,
37 clickDistance2 = 0;
38
39 function drag(selection) {
40 selection
41 .on("mousedown.drag", mousedowned)
42 .filter(touchable)
43 .on("touchstart.drag", touchstarted)
44 .on("touchmove.drag", touchmoved, nonpassive)
45 .on("touchend.drag touchcancel.drag", touchended)
46 .style("touch-action", "none")
47 .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
48 }
49
50 function mousedowned(event, d) {
51 if (touchending || !filter.call(this, event, d)) return;
52 var gesture = beforestart(this, container.call(this, event, d), event, d, "mouse");
53 if (!gesture) return;
54 select(event.view)
55 .on("mousemove.drag", mousemoved, nonpassivecapture)
56 .on("mouseup.drag", mouseupped, nonpassivecapture);
57 nodrag(event.view);
58 nopropagation(event);
59 mousemoving = false;
60 mousedownx = event.clientX;
61 mousedowny = event.clientY;
62 gesture("start", event);
63 }
64
65 function mousemoved(event) {
66 noevent(event);
67 if (!mousemoving) {
68 var dx = event.clientX - mousedownx, dy = event.clientY - mousedowny;
69 mousemoving = dx * dx + dy * dy > clickDistance2;
70 }
71 gestures.mouse("drag", event);
72 }
73
74 function mouseupped(event) {
75 select(event.view).on("mousemove.drag mouseup.drag", null);
76 yesdrag(event.view, mousemoving);
77 noevent(event);
78 gestures.mouse("end", event);
79 }
80
81 function touchstarted(event, d) {
82 if (!filter.call(this, event, d)) return;
83 var touches = event.changedTouches,
84 c = container.call(this, event, d),
85 n = touches.length, i, gesture;
86
87 for (i = 0; i < n; ++i) {
88 if (gesture = beforestart(this, c, event, d, touches[i].identifier, touches[i])) {
89 nopropagation(event);
90 gesture("start", event, touches[i]);
91 }
92 }
93 }
94
95 function touchmoved(event) {
96 var touches = event.changedTouches,
97 n = touches.length, i, gesture;
98
99 for (i = 0; i < n; ++i) {
100 if (gesture = gestures[touches[i].identifier]) {
101 noevent(event);
102 gesture("drag", event, touches[i]);
103 }
104 }
105 }
106
107 function touchended(event) {
108 var touches = event.changedTouches,
109 n = touches.length, i, gesture;
110
111 if (touchending) clearTimeout(touchending);
112 touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
113 for (i = 0; i < n; ++i) {
114 if (gesture = gestures[touches[i].identifier]) {
115 nopropagation(event);
116 gesture("end", event, touches[i]);
117 }
118 }
119 }
120
121 function beforestart(that, container, event, d, identifier, touch) {
122 var dispatch = listeners.copy(),
123 p = pointer(touch || event, container), dx, dy,
124 s;
125
126 if ((s = subject.call(that, new DragEvent("beforestart", {
127 sourceEvent: event,
128 target: drag,
129 identifier,
130 active,
131 x: p[0],
132 y: p[1],
133 dx: 0,
134 dy: 0,
135 dispatch
136 }), d)) == null) return;
137
138 dx = s.x - p[0] || 0;
139 dy = s.y - p[1] || 0;
140
141 return function gesture(type, event, touch) {
142 var p0 = p, n;
143 switch (type) {
144 case "start": gestures[identifier] = gesture, n = active++; break;
145 case "end": delete gestures[identifier], --active; // falls through
146 case "drag": p = pointer(touch || event, container), n = active; break;
147 }
148 dispatch.call(
149 type,
150 that,
151 new DragEvent(type, {
152 sourceEvent: event,
153 subject: s,
154 target: drag,
155 identifier,
156 active: n,
157 x: p[0] + dx,
158 y: p[1] + dy,
159 dx: p[0] - p0[0],
160 dy: p[1] - p0[1],
161 dispatch
162 }),
163 d
164 );
165 };
166 }
167
168 drag.filter = function(_) {
169 return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), drag) : filter;
170 };
171
172 drag.container = function(_) {
173 return arguments.length ? (container = typeof _ === "function" ? _ : constant(_), drag) : container;
174 };
175
176 drag.subject = function(_) {
177 return arguments.length ? (subject = typeof _ === "function" ? _ : constant(_), drag) : subject;
178 };
179
180 drag.touchable = function(_) {
181 return arguments.length ? (touchable = typeof _ === "function" ? _ : constant(!!_), drag) : touchable;
182 };
183
184 drag.on = function() {
185 var value = listeners.on.apply(listeners, arguments);
186 return value === listeners ? drag : value;
187 };
188
189 drag.clickDistance = function(_) {
190 return arguments.length ? (clickDistance2 = (_ = +_) * _, drag) : Math.sqrt(clickDistance2);
191 };
192
193 return drag;
194}
Note: See TracBrowser for help on using the repository browser.