Skip to content

Allow controlling pan/zoom range entry. #1389

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/plot_api/plot_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ module.exports = {
// new users see some hints about interactivity
showTips: true,

// enable axis pan/zoom drag handles
showAxisDragHandles: true,

// enable direct range entry at the pan/zoom drag points (drag handles must be enabled above)
showAxisRangeEntryBoxes: true,

// link to open this plot in plotly
showLink: false,

Expand Down
32 changes: 17 additions & 15 deletions src/plots/cartesian/dragbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -353,21 +353,23 @@ module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) {
}
else if(ew === 'e') hAlign = 'right';

dragger3
.call(svgTextUtils.makeEditable, null, {
immediate: true,
background: fullLayout.paper_bgcolor,
text: String(initialText),
fill: ax.tickfont ? ax.tickfont.color : '#444',
horizontalAlign: hAlign,
verticalAlign: vAlign
})
.on('edit', function(text) {
var v = ax.d2r(text);
if(v !== undefined) {
Plotly.relayout(gd, attrStr, v);
}
});
if(gd._context.showAxisRangeEntryBoxes) {
dragger3
.call(svgTextUtils.makeEditable, null, {
immediate: true,
background: fullLayout.paper_bgcolor,
text: String(initialText),
fill: ax.tickfont ? ax.tickfont.color : '#444',
horizontalAlign: hAlign,
verticalAlign: vAlign
})
.on('edit', function(text) {
var v = ax.d2r(text);
if(v !== undefined) {
Plotly.relayout(gd, attrStr, v);
}
});
}
}
}

Expand Down
61 changes: 32 additions & 29 deletions src/plots/cartesian/graph_interact.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,36 +153,39 @@ fx.init = function(gd) {
};

// corner draggers
dragBox(gd, plotinfo, -DRAGGERSIZE, -DRAGGERSIZE,
DRAGGERSIZE, DRAGGERSIZE, 'n', 'w');
dragBox(gd, plotinfo, xa._length, -DRAGGERSIZE,
DRAGGERSIZE, DRAGGERSIZE, 'n', 'e');
dragBox(gd, plotinfo, -DRAGGERSIZE, ya._length,
DRAGGERSIZE, DRAGGERSIZE, 's', 'w');
dragBox(gd, plotinfo, xa._length, ya._length,
DRAGGERSIZE, DRAGGERSIZE, 's', 'e');
}

// x axis draggers - if you have overlaid plots,
// these drag each axis separately
if(isNumeric(y0)) {
if(xa.anchor === 'free') y0 -= fullLayout._size.h * (1 - ya.domain[1]);
dragBox(gd, plotinfo, xa._length * 0.1, y0,
xa._length * 0.8, DRAGGERSIZE, '', 'ew');
dragBox(gd, plotinfo, 0, y0,
xa._length * 0.1, DRAGGERSIZE, '', 'w');
dragBox(gd, plotinfo, xa._length * 0.9, y0,
xa._length * 0.1, DRAGGERSIZE, '', 'e');
if(gd._context.showAxisDragHandles) {
dragBox(gd, plotinfo, -DRAGGERSIZE, -DRAGGERSIZE,
DRAGGERSIZE, DRAGGERSIZE, 'n', 'w');
dragBox(gd, plotinfo, xa._length, -DRAGGERSIZE,
DRAGGERSIZE, DRAGGERSIZE, 'n', 'e');
dragBox(gd, plotinfo, -DRAGGERSIZE, ya._length,
DRAGGERSIZE, DRAGGERSIZE, 's', 'w');
dragBox(gd, plotinfo, xa._length, ya._length,
DRAGGERSIZE, DRAGGERSIZE, 's', 'e');
}
}
// y axis draggers
if(isNumeric(x0)) {
if(ya.anchor === 'free') x0 -= fullLayout._size.w * xa.domain[0];
dragBox(gd, plotinfo, x0, ya._length * 0.1,
DRAGGERSIZE, ya._length * 0.8, 'ns', '');
dragBox(gd, plotinfo, x0, ya._length * 0.9,
DRAGGERSIZE, ya._length * 0.1, 's', '');
dragBox(gd, plotinfo, x0, 0,
DRAGGERSIZE, ya._length * 0.1, 'n', '');
if(gd._context.showAxisDragHandles) {
Copy link
Contributor

@etpinard etpinard Feb 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! Before merging, we'll need to add a few test cases to 🔒 this down.

In test/jasmine/config_test.js, call Plotly.plot with the a config object that set both new options to false and make sure that the corresponding handle and range entry boxes don't show up in the DOM. The showLink test case should serve as a good example.

Let me know if you have any questions!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got some tests added.

// x axis draggers - if you have overlaid plots,
// these drag each axis separately
if(isNumeric(y0)) {
if(xa.anchor === 'free') y0 -= fullLayout._size.h * (1 - ya.domain[1]);
dragBox(gd, plotinfo, xa._length * 0.1, y0,
xa._length * 0.8, DRAGGERSIZE, '', 'ew');
dragBox(gd, plotinfo, 0, y0,
xa._length * 0.1, DRAGGERSIZE, '', 'w');
dragBox(gd, plotinfo, xa._length * 0.9, y0,
xa._length * 0.1, DRAGGERSIZE, '', 'e');
}
// y axis draggers
if(isNumeric(x0)) {
if(ya.anchor === 'free') x0 -= fullLayout._size.w * xa.domain[0];
dragBox(gd, plotinfo, x0, ya._length * 0.1,
DRAGGERSIZE, ya._length * 0.8, 'ns', '');
dragBox(gd, plotinfo, x0, ya._length * 0.9,
DRAGGERSIZE, ya._length * 0.1, 's', '');
dragBox(gd, plotinfo, x0, 0,
DRAGGERSIZE, ya._length * 0.1, 'n', '');
}
}
});

Expand Down
117 changes: 117 additions & 0 deletions test/jasmine/tests/config_test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
var Plotly = require('@lib/index');
var Plots = Plotly.Plots;
var Lib = require('@src/lib');
var createGraphDiv = require('../assets/create_graph_div');
var destroyGraphDiv = require('../assets/destroy_graph_div');
var click = require('../assets/click');
var mouseEvent = require('../assets/mouse_event');

describe('config argument', function() {
Expand Down Expand Up @@ -269,4 +271,119 @@ describe('config argument', function() {
});

});

describe('axis drag handles attribute', function() {
var mock = require('@mocks/14.json');

var gd;
var mockCopy;

beforeEach(function(done) {
gd = createGraphDiv();
mockCopy = Lib.extendDeep({}, mock);
done();
});

afterEach(destroyGraphDiv);

it('should have drag rectangles cursors by default', function() {
Plotly.plot(gd, mockCopy.data, {});

var nwdrag = document.getElementsByClassName('drag nwdrag');
expect(nwdrag.length).toBe(1);
var nedrag = document.getElementsByClassName('drag nedrag');
expect(nedrag.length).toBe(1);
var swdrag = document.getElementsByClassName('drag swdrag');
expect(swdrag.length).toBe(1);
var sedrag = document.getElementsByClassName('drag sedrag');
expect(sedrag.length).toBe(1);
var ewdrag = document.getElementsByClassName('drag ewdrag');
expect(ewdrag.length).toBe(1);
var wdrag = document.getElementsByClassName('drag wdrag');
expect(wdrag.length).toBe(1);
var edrag = document.getElementsByClassName('drag edrag');
expect(edrag.length).toBe(1);
var nsdrag = document.getElementsByClassName('drag nsdrag');
expect(nsdrag.length).toBe(1);
var sdrag = document.getElementsByClassName('drag sdrag');
expect(sdrag.length).toBe(1);
var ndrag = document.getElementsByClassName('drag ndrag');
expect(ndrag.length).toBe(1);

});

it('should not have drag rectangles when disabled', function() {
Plotly.plot(gd, mockCopy.data, {}, { showAxisDragHandles: false });

var nwdrag = document.getElementsByClassName('drag nwdrag');
expect(nwdrag.length).toBe(0);
var nedrag = document.getElementsByClassName('drag nedrag');
expect(nedrag.length).toBe(0);
var swdrag = document.getElementsByClassName('drag swdrag');
expect(swdrag.length).toBe(0);
var sedrag = document.getElementsByClassName('drag sedrag');
expect(sedrag.length).toBe(0);
var ewdrag = document.getElementsByClassName('drag ewdrag');
expect(ewdrag.length).toBe(0);
var wdrag = document.getElementsByClassName('drag wdrag');
expect(wdrag.length).toBe(0);
var edrag = document.getElementsByClassName('drag edrag');
expect(edrag.length).toBe(0);
var nsdrag = document.getElementsByClassName('drag nsdrag');
expect(nsdrag.length).toBe(0);
var sdrag = document.getElementsByClassName('drag sdrag');
expect(sdrag.length).toBe(0);
var ndrag = document.getElementsByClassName('drag ndrag');
expect(ndrag.length).toBe(0);
});

});

describe('axis range entry attribute', function() {
var mock = require('@mocks/14.json');

var gd;
var mockCopy;

beforeEach(function(done) {
gd = createGraphDiv();
mockCopy = Lib.extendDeep({}, mock);
done();
});

afterEach(destroyGraphDiv);

it('show allow axis range entry by default', function() {
Plotly.plot(gd, mockCopy.data, {});

var corner = document.getElementsByClassName('edrag')[0];

var cornerBox = corner.getBoundingClientRect(),
cornerX = cornerBox.left + cornerBox.width / 2,
cornerY = cornerBox.top + cornerBox.height / 2;

click(cornerX, cornerY);

var editBox = document.getElementsByClassName('plugin-editable editable')[0];
expect(editBox).toBeDefined();
expect(editBox.getAttribute('contenteditable')).toBe('true');
});

it('show not allow axis range entry when', function() {
Plotly.plot(gd, mockCopy.data, {}, { showAxisRangeEntryBoxes: false });

var corner = document.getElementsByClassName('edrag')[0];

var cornerBox = corner.getBoundingClientRect(),
cornerX = cornerBox.left + cornerBox.width / 2,
cornerY = cornerBox.top + cornerBox.height / 2;

click(cornerX, cornerY);

var editBox = document.getElementsByClassName('plugin-editable editable')[0];
expect(editBox).toBeUndefined();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow. Very nicely done!

});


});
});