Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 0dc3613

Browse filesBrowse files
authored
Merge pull request plotly#728 from plotly/robust-dragbox-fixedrange
Make dragmode 'lasso' & 'select' work with fixedrange axes
2 parents b753de6 + 7f9bc9c commit 0dc3613
Copy full SHA for 0dc3613

File tree

Expand file treeCollapse file tree

4 files changed

+148
-87
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+148
-87
lines changed

‎src/components/modebar/buttons.js

Copy file name to clipboardExpand all lines: src/components/modebar/buttons.js
+1-20Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
var Plotly = require('../../plotly');
1313
var Lib = require('../../lib');
14-
var setCursor = require('../../lib/setcursor');
1514
var downloadImage = require('../../snapshot/download');
1615
var Icons = require('../../../build/ploticon');
1716

@@ -171,13 +170,6 @@ modeBarButtons.hoverCompareCartesian = {
171170
click: handleCartesian
172171
};
173172

174-
var DRAGCURSORS = {
175-
pan: 'move',
176-
zoom: 'crosshair',
177-
select: 'crosshair',
178-
lasso: 'crosshair'
179-
};
180-
181173
function handleCartesian(gd, ev) {
182174
var button = ev.currentTarget,
183175
astr = button.getAttribute('data-attr'),
@@ -227,18 +219,7 @@ function handleCartesian(gd, ev) {
227219
aobj[astr] = val;
228220
}
229221

230-
Plotly.relayout(gd, aobj).then(function() {
231-
if(astr === 'dragmode') {
232-
if(fullLayout._has('cartesian')) {
233-
setCursor(
234-
fullLayout._paper.select('.nsewdrag'),
235-
DRAGCURSORS[val]
236-
);
237-
}
238-
Plotly.Fx.supplyLayoutDefaults(gd.layout, fullLayout, gd._fullData);
239-
Plotly.Fx.init(gd);
240-
}
241-
});
222+
Plotly.relayout(gd, aobj);
242223
}
243224

244225
modeBarButtons.zoom3d = {

‎src/plot_api/plot_api.js

Copy file name to clipboardExpand all lines: src/plot_api/plot_api.js
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2429,6 +2429,9 @@ Plotly.relayout = function relayout(gd, astr, val) {
24292429
var subplotIds;
24302430
manageModeBar(gd);
24312431

2432+
Plotly.Fx.supplyLayoutDefaults(gd.layout, fullLayout, gd._fullData);
2433+
Plotly.Fx.init(gd);
2434+
24322435
subplotIds = Plots.getSubplotIds(fullLayout, 'gl3d');
24332436
for(i = 0; i < subplotIds.length; i++) {
24342437
scene = fullLayout[subplotIds[i]]._scene;

‎src/plots/cartesian/dragbox.js

Copy file name to clipboardExpand all lines: src/plots/cartesian/dragbox.js
+16-5Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) {
5252
pw = xa[0]._length,
5353
ph = ya[0]._length,
5454
MINDRAG = constants.MINDRAG,
55-
MINZOOM = constants.MINZOOM;
55+
MINZOOM = constants.MINZOOM,
56+
isMainDrag = (ns + ew === 'nsew');
5657

5758
for(var i = 1; i < subplots.length; i++) {
5859
var subplotXa = subplots[i].x(),
@@ -75,21 +76,24 @@ module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) {
7576
dragClass = ns + ew + 'drag';
7677

7778
var dragger3 = plotinfo.draglayer.selectAll('.' + dragClass).data([0]);
79+
7880
dragger3.enter().append('rect')
7981
.classed('drag', true)
8082
.classed(dragClass, true)
8183
.style({fill: 'transparent', 'stroke-width': 0})
8284
.attr('data-subplot', plotinfo.id);
85+
8386
dragger3.call(Drawing.setRect, x, y, w, h)
8487
.call(setCursor, cursor);
88+
8589
var dragger = dragger3.node();
8690

8791
// still need to make the element if the axes are disabled
8892
// but nuke its events (except for maindrag which needs them for hover)
8993
// and stop there
90-
if(!yActive && !xActive) {
94+
if(!yActive && !xActive && !isSelectOrLasso(fullLayout.dragmode)) {
9195
dragger.onmousedown = null;
92-
dragger.style.pointerEvents = (ns + ew === 'nsew') ? 'all' : 'none';
96+
dragger.style.pointerEvents = isMainDrag ? 'all' : 'none';
9397
return dragger;
9498
}
9599

@@ -107,7 +111,8 @@ module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) {
107111
doubleclick: doubleClick,
108112
prepFn: function(e, startX, startY) {
109113
var dragModeNow = gd._fullLayout.dragmode;
110-
if(ns + ew === 'nsew') {
114+
115+
if(isMainDrag) {
111116
// main dragger handles all drag modes, and changes
112117
// to pan (or to zoom if it already is pan) on shift
113118
if(e.shiftKey) {
@@ -131,7 +136,7 @@ module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) {
131136
dragOptions.doneFn = dragDone;
132137
clearSelect();
133138
}
134-
else if(dragModeNow === 'select' || dragModeNow === 'lasso') {
139+
else if(isSelectOrLasso(dragModeNow)) {
135140
prepSelect(e, startX, startY, dragOptions, dragModeNow);
136141
}
137142
}
@@ -668,3 +673,9 @@ function removeZoombox(gd) {
668673
.selectAll('.zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners')
669674
.remove();
670675
}
676+
677+
function isSelectOrLasso(dragmode) {
678+
var modes = ['lasso', 'select'];
679+
680+
return modes.indexOf(dragmode) !== -1;
681+
}

‎test/jasmine/tests/fx_test.js

Copy file name to clipboard
+128-62Lines changed: 128 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,135 @@
1-
var Fx = require('@src/plots/cartesian/graph_interact');
1+
var Plotly = require('@lib/index');
22
var Plots = require('@src/plots/plots');
33

4+
var Fx = require('@src/plots/cartesian/graph_interact');
5+
6+
var d3 = require('d3');
7+
var createGraphDiv = require('../assets/create_graph_div');
8+
var destroyGraphDiv = require('../assets/destroy_graph_div');
9+
10+
11+
describe('Fx defaults', function() {
12+
'use strict';
13+
14+
var layoutIn, layoutOut, fullData;
15+
16+
beforeEach(function() {
17+
layoutIn = {};
18+
layoutOut = {
19+
_has: Plots._hasPlotType
20+
};
21+
fullData = [{}];
22+
});
23+
24+
it('should default (blank version)', function() {
25+
Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData);
26+
expect(layoutOut.hovermode).toBe('closest', 'hovermode to closest');
27+
expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom');
28+
});
29+
30+
it('should default (cartesian version)', function() {
31+
layoutOut._basePlotModules = [{ name: 'cartesian' }];
32+
33+
Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData);
34+
expect(layoutOut.hovermode).toBe('x', 'hovermode to x');
35+
expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom');
36+
expect(layoutOut._isHoriz).toBe(false, 'isHoriz to false');
37+
});
38+
39+
it('should default (cartesian horizontal version)', function() {
40+
layoutOut._basePlotModules = [{ name: 'cartesian' }];
41+
fullData[0] = { orientation: 'h' };
42+
43+
Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData);
44+
expect(layoutOut.hovermode).toBe('y', 'hovermode to y');
45+
expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom');
46+
expect(layoutOut._isHoriz).toBe(true, 'isHoriz to true');
47+
});
48+
49+
it('should default (gl3d version)', function() {
50+
layoutOut._basePlotModules = [{ name: 'gl3d' }];
51+
52+
Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData);
53+
expect(layoutOut.hovermode).toBe('closest', 'hovermode to closest');
54+
expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom');
55+
});
56+
57+
it('should default (geo version)', function() {
58+
layoutOut._basePlotModules = [{ name: 'geo' }];
459

5-
describe('Test FX', function() {
60+
Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData);
61+
expect(layoutOut.hovermode).toBe('closest', 'hovermode to closest');
62+
expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom');
63+
});
64+
65+
it('should default (multi plot type version)', function() {
66+
layoutOut._basePlotModules = [{ name: 'cartesian' }, { name: 'gl3d' }];
67+
68+
Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData);
69+
expect(layoutOut.hovermode).toBe('x', 'hovermode to x');
70+
expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom');
71+
});
72+
});
73+
74+
describe('relayout', function() {
675
'use strict';
776

8-
describe('defaults', function() {
9-
10-
var layoutIn, layoutOut, fullData;
11-
12-
beforeEach(function() {
13-
layoutIn = {};
14-
layoutOut = {
15-
_has: Plots._hasPlotType
16-
};
17-
fullData = [{}];
18-
});
19-
20-
it('should default (blank version)', function() {
21-
Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData);
22-
expect(layoutOut.hovermode).toBe('closest', 'hovermode to closest');
23-
expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom');
24-
});
25-
26-
it('should default (cartesian version)', function() {
27-
layoutOut._basePlotModules = [{ name: 'cartesian' }];
28-
29-
Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData);
30-
expect(layoutOut.hovermode).toBe('x', 'hovermode to x');
31-
expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom');
32-
expect(layoutOut._isHoriz).toBe(false, 'isHoriz to false');
33-
});
34-
35-
it('should default (cartesian horizontal version)', function() {
36-
layoutOut._basePlotModules = [{ name: 'cartesian' }];
37-
fullData[0] = { orientation: 'h' };
38-
39-
Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData);
40-
expect(layoutOut.hovermode).toBe('y', 'hovermode to y');
41-
expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom');
42-
expect(layoutOut._isHoriz).toBe(true, 'isHoriz to true');
43-
});
44-
45-
it('should default (gl3d version)', function() {
46-
layoutOut._basePlotModules = [{ name: 'gl3d' }];
47-
48-
Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData);
49-
expect(layoutOut.hovermode).toBe('closest', 'hovermode to closest');
50-
expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom');
51-
});
52-
53-
it('should default (geo version)', function() {
54-
layoutOut._basePlotModules = [{ name: 'geo' }];
55-
56-
Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData);
57-
expect(layoutOut.hovermode).toBe('closest', 'hovermode to closest');
58-
expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom');
59-
});
60-
61-
it('should default (multi plot type version)', function() {
62-
layoutOut._basePlotModules = [{ name: 'cartesian' }, { name: 'gl3d' }];
63-
64-
Fx.supplyLayoutDefaults(layoutIn, layoutOut, fullData);
65-
expect(layoutOut.hovermode).toBe('x', 'hovermode to x');
66-
expect(layoutOut.dragmode).toBe('zoom', 'dragmode to zoom');
67-
});
77+
var gd;
78+
79+
beforeEach(function() {
80+
gd = createGraphDiv();
81+
});
82+
83+
afterEach(destroyGraphDiv);
84+
85+
it('should update main drag with correct', function(done) {
86+
87+
function assertMainDrag(cursor, isActive) {
88+
expect(d3.selectAll('rect.nsewdrag').size()).toEqual(1, 'number of nodes');
89+
var mainDrag = d3.select('rect.nsewdrag'),
90+
node = mainDrag.node();
91+
92+
expect(mainDrag.classed('cursor-' + cursor)).toBe(true, 'cursor ' + cursor);
93+
expect(mainDrag.style('pointer-events')).toEqual('all', 'pointer event');
94+
expect(!!node.onmousedown).toBe(isActive, 'mousedown handler');
95+
}
96+
97+
Plotly.plot(gd, [{
98+
y: [2, 1, 2]
99+
}]).then(function() {
100+
assertMainDrag('crosshair', true);
101+
102+
return Plotly.relayout(gd, 'dragmode', 'pan');
103+
}).then(function() {
104+
assertMainDrag('move', true);
105+
106+
return Plotly.relayout(gd, 'dragmode', 'drag');
107+
}).then(function() {
108+
assertMainDrag('crosshair', true);
109+
110+
return Plotly.relayout(gd, 'xaxis.fixedrange', true);
111+
}).then(function() {
112+
assertMainDrag('ns-resize', true);
113+
114+
return Plotly.relayout(gd, 'yaxis.fixedrange', true);
115+
}).then(function() {
116+
assertMainDrag('pointer', false);
117+
118+
return Plotly.relayout(gd, 'dragmode', 'drag');
119+
}).then(function() {
120+
assertMainDrag('pointer', false);
121+
122+
return Plotly.relayout(gd, 'dragmode', 'lasso');
123+
}).then(function() {
124+
assertMainDrag('pointer', true);
125+
126+
return Plotly.relayout(gd, 'dragmode', 'select');
127+
}).then(function() {
128+
assertMainDrag('pointer', true);
129+
130+
return Plotly.relayout(gd, 'xaxis.fixedrange', false);
131+
}).then(function() {
132+
assertMainDrag('ew-resize', true);
133+
}).then(done);
68134
});
69135
});

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.