From 5645787eb11706b619e6f010ab4fd596fe8b4e37 Mon Sep 17 00:00:00 2001 From: Robert Paskowitz Date: Thu, 16 Feb 2017 14:40:48 -0800 Subject: [PATCH 1/3] Allow controlling pan/zoom range entry. For either UI appearance reasons, or because the range entry doesn't work as one might expect (for example, on http://localhost:3000/devtools/test_dashboard/#axes_category_categoryarray, which should maybe be addressed in addition), allow people to disable the entry. Default to on so that introduction of the option is backwards compatible. --- src/plot_api/plot_config.js | 3 +++ src/plots/cartesian/dragbox.js | 32 +++++++++++++++++--------------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/plot_api/plot_config.js b/src/plot_api/plot_config.js index d54dd1a05a6..c0ce4ea4f13 100644 --- a/src/plot_api/plot_config.js +++ b/src/plot_api/plot_config.js @@ -48,6 +48,9 @@ module.exports = { // new users see some hints about interactivity showTips: true, + // enable/disable direct range entry at the pan/zoom drag points + enableRangeEntry: true, + // link to open this plot in plotly showLink: false, diff --git a/src/plots/cartesian/dragbox.js b/src/plots/cartesian/dragbox.js index 22a253f287e..1342d9759cf 100644 --- a/src/plots/cartesian/dragbox.js +++ b/src/plots/cartesian/dragbox.js @@ -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.enableRangeEntry) { + 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); + } + }); + } } } From 540994d8dd527f65160a5d56ddec73eca2106b7a Mon Sep 17 00:00:00 2001 From: Robert Paskowitz Date: Tue, 21 Feb 2017 09:16:46 -0800 Subject: [PATCH 2/3] Allow disabling the drag handles Also renamed the range entry option as per PR. --- src/plot_api/plot_config.js | 7 ++- src/plots/cartesian/dragbox.js | 2 +- src/plots/cartesian/graph_interact.js | 61 ++++++++++++++------------- 3 files changed, 38 insertions(+), 32 deletions(-) diff --git a/src/plot_api/plot_config.js b/src/plot_api/plot_config.js index c0ce4ea4f13..71871dad6be 100644 --- a/src/plot_api/plot_config.js +++ b/src/plot_api/plot_config.js @@ -48,8 +48,11 @@ module.exports = { // new users see some hints about interactivity showTips: true, - // enable/disable direct range entry at the pan/zoom drag points - enableRangeEntry: 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, diff --git a/src/plots/cartesian/dragbox.js b/src/plots/cartesian/dragbox.js index 1342d9759cf..dd46b9037be 100644 --- a/src/plots/cartesian/dragbox.js +++ b/src/plots/cartesian/dragbox.js @@ -353,7 +353,7 @@ module.exports = function dragBox(gd, plotinfo, x, y, w, h, ns, ew) { } else if(ew === 'e') hAlign = 'right'; - if(gd._context.enableRangeEntry) { + if(gd._context.showAxisRangeEntryBoxes) { dragger3 .call(svgTextUtils.makeEditable, null, { immediate: true, diff --git a/src/plots/cartesian/graph_interact.js b/src/plots/cartesian/graph_interact.js index 835873e5e39..6075ebd66d0 100644 --- a/src/plots/cartesian/graph_interact.js +++ b/src/plots/cartesian/graph_interact.js @@ -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) { + // 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', ''); + } } }); From 89605c55f0d4cb41d593a75925e9024ca501c9a4 Mon Sep 17 00:00:00 2001 From: Robert Paskowitz Date: Thu, 23 Feb 2017 22:01:01 -0800 Subject: [PATCH 3/3] Add test cases for new config settings --- test/jasmine/tests/config_test.js | 117 ++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/test/jasmine/tests/config_test.js b/test/jasmine/tests/config_test.js index f066d4a1f07..9181e56d4e5 100644 --- a/test/jasmine/tests/config_test.js +++ b/test/jasmine/tests/config_test.js @@ -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() { @@ -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(); + }); + + + }); });