source: node_modules/d3-brush/dist/d3-brush.js@ e4c61dd

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

Prototype 1.1

  • Property mode set to 100644
File size: 19.2 KB
RevLine 
[e4c61dd]1// https://d3js.org/d3-brush/ v3.0.0 Copyright 2010-2021 Mike Bostock
2(function (global, factory) {
3typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-dispatch'), require('d3-drag'), require('d3-interpolate'), require('d3-selection'), require('d3-transition')) :
4typeof define === 'function' && define.amd ? define(['exports', 'd3-dispatch', 'd3-drag', 'd3-interpolate', 'd3-selection', 'd3-transition'], factory) :
5(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.d3 = global.d3 || {}, global.d3, global.d3, global.d3, global.d3, global.d3));
6}(this, (function (exports, d3Dispatch, d3Drag, d3Interpolate, d3Selection, d3Transition) { 'use strict';
7
8var constant = x => () => x;
9
10function BrushEvent(type, {
11 sourceEvent,
12 target,
13 selection,
14 mode,
15 dispatch
16}) {
17 Object.defineProperties(this, {
18 type: {value: type, enumerable: true, configurable: true},
19 sourceEvent: {value: sourceEvent, enumerable: true, configurable: true},
20 target: {value: target, enumerable: true, configurable: true},
21 selection: {value: selection, enumerable: true, configurable: true},
22 mode: {value: mode, enumerable: true, configurable: true},
23 _: {value: dispatch}
24 });
25}
26
27function nopropagation(event) {
28 event.stopImmediatePropagation();
29}
30
31function noevent(event) {
32 event.preventDefault();
33 event.stopImmediatePropagation();
34}
35
36var MODE_DRAG = {name: "drag"},
37 MODE_SPACE = {name: "space"},
38 MODE_HANDLE = {name: "handle"},
39 MODE_CENTER = {name: "center"};
40
41const {abs, max, min} = Math;
42
43function number1(e) {
44 return [+e[0], +e[1]];
45}
46
47function number2(e) {
48 return [number1(e[0]), number1(e[1])];
49}
50
51var X = {
52 name: "x",
53 handles: ["w", "e"].map(type),
54 input: function(x, e) { return x == null ? null : [[+x[0], e[0][1]], [+x[1], e[1][1]]]; },
55 output: function(xy) { return xy && [xy[0][0], xy[1][0]]; }
56};
57
58var Y = {
59 name: "y",
60 handles: ["n", "s"].map(type),
61 input: function(y, e) { return y == null ? null : [[e[0][0], +y[0]], [e[1][0], +y[1]]]; },
62 output: function(xy) { return xy && [xy[0][1], xy[1][1]]; }
63};
64
65var XY = {
66 name: "xy",
67 handles: ["n", "w", "e", "s", "nw", "ne", "sw", "se"].map(type),
68 input: function(xy) { return xy == null ? null : number2(xy); },
69 output: function(xy) { return xy; }
70};
71
72var cursors = {
73 overlay: "crosshair",
74 selection: "move",
75 n: "ns-resize",
76 e: "ew-resize",
77 s: "ns-resize",
78 w: "ew-resize",
79 nw: "nwse-resize",
80 ne: "nesw-resize",
81 se: "nwse-resize",
82 sw: "nesw-resize"
83};
84
85var flipX = {
86 e: "w",
87 w: "e",
88 nw: "ne",
89 ne: "nw",
90 se: "sw",
91 sw: "se"
92};
93
94var flipY = {
95 n: "s",
96 s: "n",
97 nw: "sw",
98 ne: "se",
99 se: "ne",
100 sw: "nw"
101};
102
103var signsX = {
104 overlay: +1,
105 selection: +1,
106 n: null,
107 e: +1,
108 s: null,
109 w: -1,
110 nw: -1,
111 ne: +1,
112 se: +1,
113 sw: -1
114};
115
116var signsY = {
117 overlay: +1,
118 selection: +1,
119 n: -1,
120 e: null,
121 s: +1,
122 w: null,
123 nw: -1,
124 ne: -1,
125 se: +1,
126 sw: +1
127};
128
129function type(t) {
130 return {type: t};
131}
132
133// Ignore right-click, since that should open the context menu.
134function defaultFilter(event) {
135 return !event.ctrlKey && !event.button;
136}
137
138function defaultExtent() {
139 var svg = this.ownerSVGElement || this;
140 if (svg.hasAttribute("viewBox")) {
141 svg = svg.viewBox.baseVal;
142 return [[svg.x, svg.y], [svg.x + svg.width, svg.y + svg.height]];
143 }
144 return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]];
145}
146
147function defaultTouchable() {
148 return navigator.maxTouchPoints || ("ontouchstart" in this);
149}
150
151// Like d3.local, but with the name “__brush” rather than auto-generated.
152function local(node) {
153 while (!node.__brush) if (!(node = node.parentNode)) return;
154 return node.__brush;
155}
156
157function empty(extent) {
158 return extent[0][0] === extent[1][0]
159 || extent[0][1] === extent[1][1];
160}
161
162function brushSelection(node) {
163 var state = node.__brush;
164 return state ? state.dim.output(state.selection) : null;
165}
166
167function brushX() {
168 return brush$1(X);
169}
170
171function brushY() {
172 return brush$1(Y);
173}
174
175function brush() {
176 return brush$1(XY);
177}
178
179function brush$1(dim) {
180 var extent = defaultExtent,
181 filter = defaultFilter,
182 touchable = defaultTouchable,
183 keys = true,
184 listeners = d3Dispatch.dispatch("start", "brush", "end"),
185 handleSize = 6,
186 touchending;
187
188 function brush(group) {
189 var overlay = group
190 .property("__brush", initialize)
191 .selectAll(".overlay")
192 .data([type("overlay")]);
193
194 overlay.enter().append("rect")
195 .attr("class", "overlay")
196 .attr("pointer-events", "all")
197 .attr("cursor", cursors.overlay)
198 .merge(overlay)
199 .each(function() {
200 var extent = local(this).extent;
201 d3Selection.select(this)
202 .attr("x", extent[0][0])
203 .attr("y", extent[0][1])
204 .attr("width", extent[1][0] - extent[0][0])
205 .attr("height", extent[1][1] - extent[0][1]);
206 });
207
208 group.selectAll(".selection")
209 .data([type("selection")])
210 .enter().append("rect")
211 .attr("class", "selection")
212 .attr("cursor", cursors.selection)
213 .attr("fill", "#777")
214 .attr("fill-opacity", 0.3)
215 .attr("stroke", "#fff")
216 .attr("shape-rendering", "crispEdges");
217
218 var handle = group.selectAll(".handle")
219 .data(dim.handles, function(d) { return d.type; });
220
221 handle.exit().remove();
222
223 handle.enter().append("rect")
224 .attr("class", function(d) { return "handle handle--" + d.type; })
225 .attr("cursor", function(d) { return cursors[d.type]; });
226
227 group
228 .each(redraw)
229 .attr("fill", "none")
230 .attr("pointer-events", "all")
231 .on("mousedown.brush", started)
232 .filter(touchable)
233 .on("touchstart.brush", started)
234 .on("touchmove.brush", touchmoved)
235 .on("touchend.brush touchcancel.brush", touchended)
236 .style("touch-action", "none")
237 .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
238 }
239
240 brush.move = function(group, selection, event) {
241 if (group.tween) {
242 group
243 .on("start.brush", function(event) { emitter(this, arguments).beforestart().start(event); })
244 .on("interrupt.brush end.brush", function(event) { emitter(this, arguments).end(event); })
245 .tween("brush", function() {
246 var that = this,
247 state = that.__brush,
248 emit = emitter(that, arguments),
249 selection0 = state.selection,
250 selection1 = dim.input(typeof selection === "function" ? selection.apply(this, arguments) : selection, state.extent),
251 i = d3Interpolate.interpolate(selection0, selection1);
252
253 function tween(t) {
254 state.selection = t === 1 && selection1 === null ? null : i(t);
255 redraw.call(that);
256 emit.brush();
257 }
258
259 return selection0 !== null && selection1 !== null ? tween : tween(1);
260 });
261 } else {
262 group
263 .each(function() {
264 var that = this,
265 args = arguments,
266 state = that.__brush,
267 selection1 = dim.input(typeof selection === "function" ? selection.apply(that, args) : selection, state.extent),
268 emit = emitter(that, args).beforestart();
269
270 d3Transition.interrupt(that);
271 state.selection = selection1 === null ? null : selection1;
272 redraw.call(that);
273 emit.start(event).brush(event).end(event);
274 });
275 }
276 };
277
278 brush.clear = function(group, event) {
279 brush.move(group, null, event);
280 };
281
282 function redraw() {
283 var group = d3Selection.select(this),
284 selection = local(this).selection;
285
286 if (selection) {
287 group.selectAll(".selection")
288 .style("display", null)
289 .attr("x", selection[0][0])
290 .attr("y", selection[0][1])
291 .attr("width", selection[1][0] - selection[0][0])
292 .attr("height", selection[1][1] - selection[0][1]);
293
294 group.selectAll(".handle")
295 .style("display", null)
296 .attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection[1][0] - handleSize / 2 : selection[0][0] - handleSize / 2; })
297 .attr("y", function(d) { return d.type[0] === "s" ? selection[1][1] - handleSize / 2 : selection[0][1] - handleSize / 2; })
298 .attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection[1][0] - selection[0][0] + handleSize : handleSize; })
299 .attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection[1][1] - selection[0][1] + handleSize : handleSize; });
300 }
301
302 else {
303 group.selectAll(".selection,.handle")
304 .style("display", "none")
305 .attr("x", null)
306 .attr("y", null)
307 .attr("width", null)
308 .attr("height", null);
309 }
310 }
311
312 function emitter(that, args, clean) {
313 var emit = that.__brush.emitter;
314 return emit && (!clean || !emit.clean) ? emit : new Emitter(that, args, clean);
315 }
316
317 function Emitter(that, args, clean) {
318 this.that = that;
319 this.args = args;
320 this.state = that.__brush;
321 this.active = 0;
322 this.clean = clean;
323 }
324
325 Emitter.prototype = {
326 beforestart: function() {
327 if (++this.active === 1) this.state.emitter = this, this.starting = true;
328 return this;
329 },
330 start: function(event, mode) {
331 if (this.starting) this.starting = false, this.emit("start", event, mode);
332 else this.emit("brush", event);
333 return this;
334 },
335 brush: function(event, mode) {
336 this.emit("brush", event, mode);
337 return this;
338 },
339 end: function(event, mode) {
340 if (--this.active === 0) delete this.state.emitter, this.emit("end", event, mode);
341 return this;
342 },
343 emit: function(type, event, mode) {
344 var d = d3Selection.select(this.that).datum();
345 listeners.call(
346 type,
347 this.that,
348 new BrushEvent(type, {
349 sourceEvent: event,
350 target: brush,
351 selection: dim.output(this.state.selection),
352 mode,
353 dispatch: listeners
354 }),
355 d
356 );
357 }
358 };
359
360 function started(event) {
361 if (touchending && !event.touches) return;
362 if (!filter.apply(this, arguments)) return;
363
364 var that = this,
365 type = event.target.__data__.type,
366 mode = (keys && event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (keys && event.altKey ? MODE_CENTER : MODE_HANDLE),
367 signX = dim === Y ? null : signsX[type],
368 signY = dim === X ? null : signsY[type],
369 state = local(that),
370 extent = state.extent,
371 selection = state.selection,
372 W = extent[0][0], w0, w1,
373 N = extent[0][1], n0, n1,
374 E = extent[1][0], e0, e1,
375 S = extent[1][1], s0, s1,
376 dx = 0,
377 dy = 0,
378 moving,
379 shifting = signX && signY && keys && event.shiftKey,
380 lockX,
381 lockY,
382 points = Array.from(event.touches || [event], t => {
383 const i = t.identifier;
384 t = d3Selection.pointer(t, that);
385 t.point0 = t.slice();
386 t.identifier = i;
387 return t;
388 });
389
390 d3Transition.interrupt(that);
391 var emit = emitter(that, arguments, true).beforestart();
392
393 if (type === "overlay") {
394 if (selection) moving = true;
395 const pts = [points[0], points[1] || points[0]];
396 state.selection = selection = [[
397 w0 = dim === Y ? W : min(pts[0][0], pts[1][0]),
398 n0 = dim === X ? N : min(pts[0][1], pts[1][1])
399 ], [
400 e0 = dim === Y ? E : max(pts[0][0], pts[1][0]),
401 s0 = dim === X ? S : max(pts[0][1], pts[1][1])
402 ]];
403 if (points.length > 1) move(event);
404 } else {
405 w0 = selection[0][0];
406 n0 = selection[0][1];
407 e0 = selection[1][0];
408 s0 = selection[1][1];
409 }
410
411 w1 = w0;
412 n1 = n0;
413 e1 = e0;
414 s1 = s0;
415
416 var group = d3Selection.select(that)
417 .attr("pointer-events", "none");
418
419 var overlay = group.selectAll(".overlay")
420 .attr("cursor", cursors[type]);
421
422 if (event.touches) {
423 emit.moved = moved;
424 emit.ended = ended;
425 } else {
426 var view = d3Selection.select(event.view)
427 .on("mousemove.brush", moved, true)
428 .on("mouseup.brush", ended, true);
429 if (keys) view
430 .on("keydown.brush", keydowned, true)
431 .on("keyup.brush", keyupped, true);
432
433 d3Drag.dragDisable(event.view);
434 }
435
436 redraw.call(that);
437 emit.start(event, mode.name);
438
439 function moved(event) {
440 for (const p of event.changedTouches || [event]) {
441 for (const d of points)
442 if (d.identifier === p.identifier) d.cur = d3Selection.pointer(p, that);
443 }
444 if (shifting && !lockX && !lockY && points.length === 1) {
445 const point = points[0];
446 if (abs(point.cur[0] - point[0]) > abs(point.cur[1] - point[1]))
447 lockY = true;
448 else
449 lockX = true;
450 }
451 for (const point of points)
452 if (point.cur) point[0] = point.cur[0], point[1] = point.cur[1];
453 moving = true;
454 noevent(event);
455 move(event);
456 }
457
458 function move(event) {
459 const point = points[0], point0 = point.point0;
460 var t;
461
462 dx = point[0] - point0[0];
463 dy = point[1] - point0[1];
464
465 switch (mode) {
466 case MODE_SPACE:
467 case MODE_DRAG: {
468 if (signX) dx = max(W - w0, min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx;
469 if (signY) dy = max(N - n0, min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy;
470 break;
471 }
472 case MODE_HANDLE: {
473 if (points[1]) {
474 if (signX) w1 = max(W, min(E, points[0][0])), e1 = max(W, min(E, points[1][0])), signX = 1;
475 if (signY) n1 = max(N, min(S, points[0][1])), s1 = max(N, min(S, points[1][1])), signY = 1;
476 } else {
477 if (signX < 0) dx = max(W - w0, min(E - w0, dx)), w1 = w0 + dx, e1 = e0;
478 else if (signX > 0) dx = max(W - e0, min(E - e0, dx)), w1 = w0, e1 = e0 + dx;
479 if (signY < 0) dy = max(N - n0, min(S - n0, dy)), n1 = n0 + dy, s1 = s0;
480 else if (signY > 0) dy = max(N - s0, min(S - s0, dy)), n1 = n0, s1 = s0 + dy;
481 }
482 break;
483 }
484 case MODE_CENTER: {
485 if (signX) w1 = max(W, min(E, w0 - dx * signX)), e1 = max(W, min(E, e0 + dx * signX));
486 if (signY) n1 = max(N, min(S, n0 - dy * signY)), s1 = max(N, min(S, s0 + dy * signY));
487 break;
488 }
489 }
490
491 if (e1 < w1) {
492 signX *= -1;
493 t = w0, w0 = e0, e0 = t;
494 t = w1, w1 = e1, e1 = t;
495 if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]);
496 }
497
498 if (s1 < n1) {
499 signY *= -1;
500 t = n0, n0 = s0, s0 = t;
501 t = n1, n1 = s1, s1 = t;
502 if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]);
503 }
504
505 if (state.selection) selection = state.selection; // May be set by brush.move!
506 if (lockX) w1 = selection[0][0], e1 = selection[1][0];
507 if (lockY) n1 = selection[0][1], s1 = selection[1][1];
508
509 if (selection[0][0] !== w1
510 || selection[0][1] !== n1
511 || selection[1][0] !== e1
512 || selection[1][1] !== s1) {
513 state.selection = [[w1, n1], [e1, s1]];
514 redraw.call(that);
515 emit.brush(event, mode.name);
516 }
517 }
518
519 function ended(event) {
520 nopropagation(event);
521 if (event.touches) {
522 if (event.touches.length) return;
523 if (touchending) clearTimeout(touchending);
524 touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
525 } else {
526 d3Drag.dragEnable(event.view, moving);
527 view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null);
528 }
529 group.attr("pointer-events", "all");
530 overlay.attr("cursor", cursors.overlay);
531 if (state.selection) selection = state.selection; // May be set by brush.move (on start)!
532 if (empty(selection)) state.selection = null, redraw.call(that);
533 emit.end(event, mode.name);
534 }
535
536 function keydowned(event) {
537 switch (event.keyCode) {
538 case 16: { // SHIFT
539 shifting = signX && signY;
540 break;
541 }
542 case 18: { // ALT
543 if (mode === MODE_HANDLE) {
544 if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
545 if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
546 mode = MODE_CENTER;
547 move(event);
548 }
549 break;
550 }
551 case 32: { // SPACE; takes priority over ALT
552 if (mode === MODE_HANDLE || mode === MODE_CENTER) {
553 if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx;
554 if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy;
555 mode = MODE_SPACE;
556 overlay.attr("cursor", cursors.selection);
557 move(event);
558 }
559 break;
560 }
561 default: return;
562 }
563 noevent(event);
564 }
565
566 function keyupped(event) {
567 switch (event.keyCode) {
568 case 16: { // SHIFT
569 if (shifting) {
570 lockX = lockY = shifting = false;
571 move(event);
572 }
573 break;
574 }
575 case 18: { // ALT
576 if (mode === MODE_CENTER) {
577 if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
578 if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
579 mode = MODE_HANDLE;
580 move(event);
581 }
582 break;
583 }
584 case 32: { // SPACE
585 if (mode === MODE_SPACE) {
586 if (event.altKey) {
587 if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
588 if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
589 mode = MODE_CENTER;
590 } else {
591 if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
592 if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
593 mode = MODE_HANDLE;
594 }
595 overlay.attr("cursor", cursors[type]);
596 move(event);
597 }
598 break;
599 }
600 default: return;
601 }
602 noevent(event);
603 }
604 }
605
606 function touchmoved(event) {
607 emitter(this, arguments).moved(event);
608 }
609
610 function touchended(event) {
611 emitter(this, arguments).ended(event);
612 }
613
614 function initialize() {
615 var state = this.__brush || {selection: null};
616 state.extent = number2(extent.apply(this, arguments));
617 state.dim = dim;
618 return state;
619 }
620
621 brush.extent = function(_) {
622 return arguments.length ? (extent = typeof _ === "function" ? _ : constant(number2(_)), brush) : extent;
623 };
624
625 brush.filter = function(_) {
626 return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), brush) : filter;
627 };
628
629 brush.touchable = function(_) {
630 return arguments.length ? (touchable = typeof _ === "function" ? _ : constant(!!_), brush) : touchable;
631 };
632
633 brush.handleSize = function(_) {
634 return arguments.length ? (handleSize = +_, brush) : handleSize;
635 };
636
637 brush.keyModifiers = function(_) {
638 return arguments.length ? (keys = !!_, brush) : keys;
639 };
640
641 brush.on = function() {
642 var value = listeners.on.apply(listeners, arguments);
643 return value === listeners ? brush : value;
644 };
645
646 return brush;
647}
648
649exports.brush = brush;
650exports.brushSelection = brushSelection;
651exports.brushX = brushX;
652exports.brushY = brushY;
653
654Object.defineProperty(exports, '__esModule', { value: true });
655
656})));
Note: See TracBrowser for help on using the repository browser.