Skip to content

Commit 473f72a

Browse files
committed
Add test, refactor cover slip
1 parent 8579d78 commit 473f72a

File tree

3 files changed

+122
-48
lines changed

3 files changed

+122
-48
lines changed

src/components/dragelement/index.js

Lines changed: 18 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
'use strict';
1111

1212
var mouseOffset = require('mouse-event-offset');
13-
var hasHover = require('has-hover');
1413

1514
var Plotly = require('../../plotly');
1615
var Lib = require('../../lib');
@@ -30,13 +29,6 @@ dragElement.unhoverRaw = unhover.raw;
3029
/**
3130
* Abstracts click & drag interactions
3231
*
33-
* During the interaction, a "coverSlip" element - a transparent
34-
* div covering the whole page - is created, which has two key effects:
35-
* - Lets you drag beyond the boundaries of the plot itself without
36-
* dropping (but if you drag all the way out of the browser window the
37-
* interaction will end)
38-
* - Freezes the cursor: whatever mouse cursor the drag element had when the
39-
* interaction started gets copied to the coverSlip for use until mouseup
4032
*
4133
* @param {object} options with keys:
4234
* element (required) the DOM element to drag
@@ -65,19 +57,14 @@ dragElement.init = function init(options) {
6557
startY,
6658
newMouseDownTime,
6759
cursor,
68-
dragCover,
6960
initialTarget;
7061

7162
if(!gd._mouseDownTime) gd._mouseDownTime = 0;
7263

7364
options.element.style.pointerEvents = 'all';
7465

75-
if(hasHover) {
76-
options.element.onmousedown = onStart;
77-
}
78-
else {
79-
options.element.ontouchstart = onStart;
80-
}
66+
options.element.onmousedown = onStart;
67+
options.element.ontouchstart = onStart;
8168

8269
function onStart(e) {
8370
// make dragging and dragged into properties of gd
@@ -102,24 +89,16 @@ dragElement.init = function init(options) {
10289

10390
if(options.prepFn) options.prepFn(e, startX, startY);
10491

105-
if(hasHover) {
106-
dragCover = coverSlip();
107-
dragCover.addEventListener('mousemove', onMove);
108-
dragCover.addEventListener('mouseup', onDone);
109-
dragCover.addEventListener('mouseout', onDone);
110-
111-
dragCover.style.cursor = window.getComputedStyle(options.element).cursor;
112-
}
11392

11493
// document acts as a dragcover for mobile, bc we can't create dragcover dynamically
115-
else {
116-
dragCover = document;
117-
document.addEventListener('touchmove', onMove);
118-
document.addEventListener('touchend', onDone);
94+
document.addEventListener('mousemove', onMove);
95+
document.addEventListener('mouseup', onDone);
96+
document.addEventListener('mouseout', onDone);
97+
document.addEventListener('touchmove', onMove);
98+
document.addEventListener('touchend', onDone);
11999

120-
cursor = window.getComputedStyle(document.documentElement).cursor;
121-
document.documentElement.style.cursor = window.getComputedStyle(options.element).cursor;
122-
}
100+
cursor = window.getComputedStyle(document.documentElement).cursor;
101+
document.documentElement.style.cursor = window.getComputedStyle(options.element).cursor;
123102

124103

125104
return Lib.pauseEvent(e);
@@ -144,25 +123,17 @@ dragElement.init = function init(options) {
144123
}
145124

146125
function onDone(e) {
147-
if(hasHover) {
148-
dragCover.removeEventListener('mousemove', onMove);
149-
dragCover.removeEventListener('mouseup', onDone);
150-
dragCover.removeEventListener('mouseout', onDone);
151-
152-
Lib.removeElement(dragCover);
126+
document.removeEventListener('mousemove', onMove);
127+
document.removeEventListener('mouseup', onDone);
128+
document.removeEventListener('mouseout', onDone);
129+
document.removeEventListener('touchmove', onMove);
130+
document.removeEventListener('touchend', onDone);
131+
132+
if(cursor) {
133+
document.documentElement.style.cursor = cursor;
134+
cursor = null;
153135
}
154136

155-
else {
156-
dragCover.removeEventListener('touchmove', onMove);
157-
dragCover.removeEventListener('touchend', onDone);
158-
159-
if(cursor) {
160-
dragCover.documentElement.style.cursor = cursor;
161-
cursor = null;
162-
}
163-
}
164-
165-
166137
if(!gd._dragging) {
167138
gd._dragged = false;
168139
return;

test/jasmine/assets/touch_event.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
var Lib = require('../../../src/lib');
2+
3+
module.exports = function(type, x, y, opts) {
4+
var el = (opts && opts.element) || document.elementFromPoint(x, y),
5+
ev;
6+
7+
var touchObj = new Touch({
8+
identifier: Date.now(),
9+
target: el,
10+
clientX: x,
11+
clientY: y,
12+
radiusX: 2.5,
13+
radiusY: 2.5,
14+
rotationAngle: 10,
15+
force: 0.5,
16+
});
17+
18+
var fullOpts = {
19+
touches: [touchObj],
20+
targetTouches: [],
21+
changedTouches: [touchObj],
22+
bubbles: true
23+
};
24+
25+
if(opts && opts.altKey) {
26+
fullOpts.altKey = opts.altKey;
27+
}
28+
if(opts && opts.ctrlKey) {
29+
fullOpts.ctrlKey = opts.ctrlKey;
30+
}
31+
if(opts && opts.metaKey) {
32+
fullOpts.metaKey = opts.metaKey;
33+
}
34+
if(opts && opts.shiftKey) {
35+
fullOpts.shiftKey = opts.shiftKey;
36+
}
37+
38+
39+
ev = new window.TouchEvent(type, Lib.extendFlat({}, fullOpts, opts));
40+
41+
el.dispatchEvent(ev);
42+
43+
return el;
44+
};

test/jasmine/tests/select_test.js

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ var doubleClick = require('../assets/double_click');
77
var createGraphDiv = require('../assets/create_graph_div');
88
var destroyGraphDiv = require('../assets/destroy_graph_div');
99
var mouseEvent = require('../assets/mouse_event');
10+
var touchEvent = require('../assets/touch_event');
1011
var customMatchers = require('../assets/custom_matchers');
1112

1213

@@ -22,9 +23,23 @@ describe('select box and lasso', function() {
2223

2324
afterEach(destroyGraphDiv);
2425

25-
function drag(path) {
26+
function drag(path, options) {
2627
var len = path.length;
2728

29+
if(!options) options = {type: 'mouse'};
30+
31+
if(options.type === 'touch') {
32+
touchEvent('touchstart', path[0][0], path[0][1]);
33+
34+
path.slice(1, len).forEach(function(pt) {
35+
touchEvent('touchmove', pt[0], pt[1]);
36+
});
37+
38+
touchEvent('touchend', path[len - 1][0], path[len - 1][1]);
39+
40+
return;
41+
}
42+
2843
mouseEvent('mousemove', path[0][0], path[0][1]);
2944
mouseEvent('mousedown', path[0][0], path[0][1]);
3045

@@ -299,6 +314,50 @@ describe('select box and lasso', function() {
299314
done();
300315
});
301316
});
317+
318+
it('should trigger selecting/selected/deselect events for touches', function(done) {
319+
var selectingCnt = 0,
320+
selectingData;
321+
gd.on('plotly_selecting', function(data) {
322+
selectingCnt++;
323+
selectingData = data;
324+
});
325+
326+
var selectedCnt = 0,
327+
selectedData;
328+
gd.on('plotly_selected', function(data) {
329+
selectedCnt++;
330+
selectedData = data;
331+
});
332+
333+
var doubleClickData;
334+
gd.on('plotly_deselect', function(data) {
335+
doubleClickData = data;
336+
});
337+
338+
drag(lassoPath, {type: 'touch'});
339+
340+
expect(selectingCnt).toEqual(3, 'with the correct selecting count');
341+
assertEventData(selectingData.points, [{
342+
curveNumber: 0,
343+
pointNumber: 10,
344+
x: 0.099,
345+
y: 2.75
346+
}], 'with the correct selecting points (1)');
347+
348+
expect(selectedCnt).toEqual(1, 'with the correct selected count');
349+
assertEventData(selectedData.points, [{
350+
curveNumber: 0,
351+
pointNumber: 10,
352+
x: 0.099,
353+
y: 2.75,
354+
}], 'with the correct selected points (2)');
355+
356+
doubleClick(250, 200).then(function() {
357+
expect(doubleClickData).toBe(null, 'with the correct deselect data');
358+
done();
359+
});
360+
});
302361
});
303362

304363
it('should skip over non-visible traces', function(done) {

0 commit comments

Comments
 (0)