From 51f13afdc9441c26b34000fdb5318fba03507f97 Mon Sep 17 00:00:00 2001 From: etienne Date: Fri, 16 Feb 2018 16:38:14 -0500 Subject: [PATCH 1/5] implement 'cliponaxis: false' for bar text nodes --- src/components/drawing/index.js | 6 +- src/plot_api/subroutines.js | 2 +- src/plots/cartesian/dragbox.js | 3 + src/traces/bar/attributes.js | 9 ++ src/traces/bar/defaults.js | 1 + src/traces/bar/plot.js | 13 ++- test/image/baselines/bar_cliponaxis-false.png | Bin 0 -> 22480 bytes test/image/mocks/bar_cliponaxis-false.json | 82 +++++++++++++++ test/jasmine/tests/bar_test.js | 94 ++++++++++++++++++ 9 files changed, 206 insertions(+), 4 deletions(-) create mode 100644 test/image/baselines/bar_cliponaxis-false.png create mode 100644 test/image/mocks/bar_cliponaxis-false.json diff --git a/src/components/drawing/index.js b/src/components/drawing/index.js index 9904121f5b0..77767079e08 100644 --- a/src/components/drawing/index.js +++ b/src/components/drawing/index.js @@ -100,9 +100,11 @@ drawing.hideOutsideRangePoint = function(d, sel, xa, ya, xcalendar, ycalendar) { ); }; -drawing.hideOutsideRangePoints = function(traceGroups, subplot) { +drawing.hideOutsideRangePoints = function(traceGroups, subplot, selector) { if(!subplot._hasClipOnAxisFalse) return; + selector = selector || '.point,textpoint'; + var xa = subplot.xaxis; var ya = subplot.yaxis; @@ -111,7 +113,7 @@ drawing.hideOutsideRangePoints = function(traceGroups, subplot) { var xcalendar = trace.xcalendar; var ycalendar = trace.ycalendar; - traceGroups.selectAll('.point,.textpoint').each(function(d) { + traceGroups.selectAll(selector).each(function(d) { drawing.hideOutsideRangePoint(d, d3.select(this), xa, ya, xcalendar, ycalendar); }); }); diff --git a/src/plot_api/subroutines.js b/src/plot_api/subroutines.js index 18a5a807959..2df2985554d 100644 --- a/src/plot_api/subroutines.js +++ b/src/plot_api/subroutines.js @@ -216,7 +216,7 @@ exports.lsInner = function(gd) { for(i = 0; i < cartesianConstants.traceLayerClasses.length; i++) { var layer = cartesianConstants.traceLayerClasses[i]; - if(layer !== 'scatterlayer') { + if(layer !== 'scatterlayer' && layer !== 'barlayer') { plotinfo.plot.selectAll('g.' + layer).call(Drawing.setClipUrl, layerClipId); } } diff --git a/src/plots/cartesian/dragbox.js b/src/plots/cartesian/dragbox.js index 3ded8e18b47..90c32556a7b 100644 --- a/src/plots/cartesian/dragbox.js +++ b/src/plots/cartesian/dragbox.js @@ -793,6 +793,9 @@ function makeDragBox(gd, plotinfo, x, y, w, h, ns, ew) { .call(Drawing.setTextPointsScale, xScaleFactor2, yScaleFactor2); traceGroups .call(Drawing.hideOutsideRangePoints, subplot); + + subplot.plot.selectAll('.barlayer .trace') + .call(Drawing.hideOutsideRangePoints, subplot, '.bartext'); } } diff --git a/src/traces/bar/attributes.js b/src/traces/bar/attributes.js index fcb644e77ea..0d3d131224e 100644 --- a/src/traces/bar/attributes.js +++ b/src/traces/bar/attributes.js @@ -104,6 +104,15 @@ module.exports = { ].join(' ') }, + cliponaxis: extendFlat({}, scatterAttrs.cliponaxis, { + description: [ + 'Determines whether the text nodes', + 'are clipped about the subplot axes.', + 'To show the text nodes above axis lines and tick labels,', + 'make sure to set `xaxis.layer` and `yaxis.layer` to *below traces*.' + ].join(' ') + }), + orientation: { valType: 'enumerated', role: 'info', diff --git a/src/traces/bar/defaults.js b/src/traces/bar/defaults.js index b1d6767a1ac..04096b33ff4 100644 --- a/src/traces/bar/defaults.js +++ b/src/traces/bar/defaults.js @@ -51,6 +51,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout coerce('constraintext'); coerce('selected.textfont.color'); coerce('unselected.textfont.color'); + coerce('cliponaxis'); } handleStyleDefaults(traceIn, traceOut, coerce, defaultColor, layout); diff --git a/src/traces/bar/plot.js b/src/traces/bar/plot.js index 766b27cfd8e..c18d036c0d0 100644 --- a/src/traces/bar/plot.js +++ b/src/traces/bar/plot.js @@ -138,15 +138,26 @@ module.exports = function plot(gd, plotinfo, cdbar) { bar.append('path') .style('vector-effect', 'non-scaling-stroke') .attr('d', - 'M' + x0 + ',' + y0 + 'V' + y1 + 'H' + x1 + 'V' + y0 + 'Z'); + 'M' + x0 + ',' + y0 + 'V' + y1 + 'H' + x1 + 'V' + y0 + 'Z') + .call(Drawing.setClipUrl, plotinfo.layerClipId); appendBarText(gd, bar, d, i, x0, x1, y0, y1); + + if(plotinfo.layerClipId) { + Drawing.hideOutsideRangePoint(d[i], bar.select('text'), xa, ya, trace.xcalendar, trace.ycalendar); + } }); }); // error bars are on the top bartraces.call(ErrorBars.plot, plotinfo); + // lastly, clip points groups of `cliponaxis !== false` traces + // on `plotinfo._hasClipOnAxisFalse === true` subplots + bartraces.each(function(d) { + var hasClipOnAxisFalse = d[0].trace.cliponaxis === false; + Drawing.setClipUrl(d3.select(this), hasClipOnAxisFalse ? null : plotinfo.layerClipId); + }); }; function appendBarText(gd, bar, calcTrace, i, x0, x1, y0, y1) { diff --git a/test/image/baselines/bar_cliponaxis-false.png b/test/image/baselines/bar_cliponaxis-false.png new file mode 100644 index 0000000000000000000000000000000000000000..1fbbcb499d7dbc449214e20a48c55057f4a14797 GIT binary patch literal 22480 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 literal 0 HcmV?d00001 diff --git a/test/image/mocks/bar_cliponaxis-false.json b/test/image/mocks/bar_cliponaxis-false.json new file mode 100644 index 00000000000..374094e2647 --- /dev/null +++ b/test/image/mocks/bar_cliponaxis-false.json @@ -0,0 +1,82 @@ +{ + "data": [ + { + "type": "bar", + "name": "not clipped", + "x": ["apple", "banana", "clementine"], + "y": [1.9, 2, 2.1], + "text": ["apple", "banana", "x"], + "textposition": "outside", + "cliponaxis": false, + "textfont": { + "size": [60, 40, 20] + } + }, + { + "type": "bar", + "name": "same but clipped", + "x": ["apple", "banana", "clementine"], + "y": [1.9, 2, 2.1], + "text": ["apple", "banana", "clementine"], + "textposition": "outside", + "cliponaxis": true, + "textfont": { + "size": [60, 40, 20] + }, + "xaxis": "x2", + "yaxis": "y2" + }, + { + "type": "bar", + "name": "should not see text", + "x": ["banana"], + "y": [2], + "text": ["X"], + "textposition": "outside", + "cliponaxis": true, + "textfont": {"size": [20]}, + "marker": {"opacity": 0.3} + } + ], + "layout": { + "barmode": "overlay", + "legend": { + "x": 0.5, + "xanchor": "center", + "y": -0.05, + "yanchor": "top" + }, + "xaxis": { + "showline": true, + "showticklabels": false, + "mirror": true, + "layer": "below traces", + "domain": [0, 0.48] + }, + "xaxis2": { + "anchor": "y2", + "showline": true, + "showticklabels": false, + "mirror": true, + "layer": "below traces", + "domain": [0.52, 1] + }, + "yaxis": { + "showline": true, + "mirror": true, + "layer": "below traces", + "range": [0, 2] + }, + "yaxis2": { + "anchor": "x2", + "showline": true, + "mirror": true, + "layer": "below traces", + "range": [0, 2] + }, + "width": 700, + "height": 400, + "margin": {"t": 40}, + "dragmode": "pan" + } +} diff --git a/test/jasmine/tests/bar_test.js b/test/jasmine/tests/bar_test.js index 756f678dcca..1dea938d0d7 100644 --- a/test/jasmine/tests/bar_test.js +++ b/test/jasmine/tests/bar_test.js @@ -13,6 +13,10 @@ var fail = require('../assets/fail_test'); var checkTicks = require('../assets/custom_assertions').checkTicks; var supplyAllDefaults = require('../assets/supply_defaults'); +var customAssertions = require('../assets/custom_assertions'); +var assertClip = customAssertions.assertClip; +var assertNodeDisplay = customAssertions.assertNodeDisplay; + var d3 = require('d3'); describe('Bar.supplyDefaults', function() { @@ -1509,6 +1513,96 @@ describe('bar hover', function() { .then(done); }); }); + + it('should show/hide text in clipped and non-clipped layers', function(done) { + var fig = Lib.extendDeep({}, require('@mocks/bar_cliponaxis-false.json')); + gd = createGraphDiv(); + + // only show one trace + fig.data = [fig.data[0]]; + + function _assert(layerClips, barDisplays, barTextDisplays, barClips) { + var subplotLayer = d3.select('.plot'); + var barLayer = subplotLayer.select('.barlayer'); + + assertClip(subplotLayer, layerClips[0], 1, 'subplot layer'); + assertClip(subplotLayer.select('.maplayer'), layerClips[1], 1, 'some other trace layer'); + assertClip(barLayer, layerClips[2], 1, 'bar layer'); + + assertNodeDisplay( + barLayer.selectAll('.point'), + barDisplays, + 'bar points (never hidden by display attr)' + ); + assertNodeDisplay( + barLayer.selectAll('.bartext'), + barTextDisplays, + 'bar text' + ); + + assertClip( + barLayer.selectAll('.point > path'), + barClips[0], barClips[1], + 'bar clips' + ); + } + + Plotly.newPlot(gd, fig).then(function() { + _assert( + [false, true, false], + [null, null, null], + [null, null, 'none'], + [true, 3] + ); + return Plotly.restyle(gd, 'visible', false); + }) + .then(function() { + _assert( + [true, false, false], + [], + [], + [false, 0] + ); + return Plotly.restyle(gd, {visible: true, cliponaxis: null}); + }) + .then(function() { + _assert( + [true, false, false], + [null, null, null], + [null, null, null], + [false, 3] + ); + return Plotly.restyle(gd, 'cliponaxis', false); + }) + .then(function() { + _assert( + [false, true, false], + [null, null, null], + [null, null, 'none'], + [true, 3] + ); + return Plotly.relayout(gd, 'yaxis.range', [0, 1]); + }) + .then(function() { + _assert( + [false, true, false], + [null, null, null], + ['none', 'none', 'none'], + [true, 3] + ); + return Plotly.relayout(gd, 'yaxis.range', [0, 4]); + }) + .then(function() { + _assert( + [false, true, false], + [null, null, null], + [null, null, null], + [true, 3] + ); + }) + .catch(fail) + .then(done); + }); }); function mockBarPlot(dataWithoutTraceType, layout) { From 210da2e24355afd3e3b3b210246746688a793bd4 Mon Sep 17 00:00:00 2001 From: etienne Date: Fri, 16 Feb 2018 16:39:25 -0500 Subject: [PATCH 2/5] adapt scatter `cliponaxis: false` ... now that the barlayer also supports `cliponaxis: false` we let bar/plot.js handle clipping per trace. --- test/jasmine/tests/scatter_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jasmine/tests/scatter_test.js b/test/jasmine/tests/scatter_test.js index 063b65ea6a4..1f6fdb97b3f 100644 --- a/test/jasmine/tests/scatter_test.js +++ b/test/jasmine/tests/scatter_test.js @@ -1189,7 +1189,7 @@ describe('Test scatter *clipnaxis*:', function() { var scatterLayer = subplotLayer.select('.scatterlayer'); assertClip(subplotLayer, layerClips[0], 1, 'subplot layer'); - assertClip(subplotLayer.select('.barlayer'), layerClips[1], 1, 'bar layer'); + assertClip(subplotLayer.select('.maplayer'), layerClips[1], 1, 'some other trace layer'); assertClip(scatterLayer, layerClips[2], 1, 'scatter layer'); assertNodeDisplay( From 2ed58799b727eba9ebe63cd96c2d79d5aeda971c Mon Sep 17 00:00:00 2001 From: etienne Date: Fri, 16 Feb 2018 18:03:41 -0500 Subject: [PATCH 3/5] clean up maindrag pan test --- test/jasmine/tests/cartesian_interact_test.js | 51 ++++++++----------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/test/jasmine/tests/cartesian_interact_test.js b/test/jasmine/tests/cartesian_interact_test.js index 72bf3ce45bc..d215aff5702 100644 --- a/test/jasmine/tests/cartesian_interact_test.js +++ b/test/jasmine/tests/cartesian_interact_test.js @@ -63,49 +63,24 @@ describe('zoom box element', function() { describe('main plot pan', function() { - var mock = require('@mocks/10.json'); var gd, modeBar, relayoutCallback; - beforeEach(function(done) { + beforeEach(function() { gd = createGraphDiv(); - - Plotly.plot(gd, mock.data, mock.layout).then(function() { - - modeBar = gd._fullLayout._modeBar; - relayoutCallback = jasmine.createSpy('relayoutCallback'); - - gd.on('plotly_relayout', relayoutCallback); - }) - .catch(failTest) - .then(done); }); afterEach(destroyGraphDiv); it('should respond to pan interactions', function(done) { - + var mock = require('@mocks/10.json'); var precision = 5; - var buttonPan = selectButton(modeBar, 'pan2d'); - var originalX = [-0.6225, 5.5]; var originalY = [-1.6340975059013805, 7.166241526218911]; var newX = [-2.0255729166666665, 4.096927083333333]; var newY = [-0.3769062155984817, 8.42343281652181]; - expect(gd.layout.xaxis.range).toBeCloseToArray(originalX, precision); - expect(gd.layout.yaxis.range).toBeCloseToArray(originalY, precision); - - // Switch to pan mode - expect(buttonPan.isActive()).toBe(false); // initially, zoom is active - buttonPan.click(); - expect(buttonPan.isActive()).toBe(true); // switched on dragmode - - // Switching mode must not change visible range - expect(gd.layout.xaxis.range).toBeCloseToArray(originalX, precision); - expect(gd.layout.yaxis.range).toBeCloseToArray(originalY, precision); - function _drag(x0, y0, x1, y1) { mouseEvent('mousedown', x0, y0); mouseEvent('mousemove', x1, y1); @@ -143,9 +118,27 @@ describe('main plot pan', function() { _checkAxes(xr0, yr0); } - delay(MODEBAR_DELAY)() - .then(function() { + Plotly.plot(gd, mock.data, mock.layout).then(function() { + modeBar = gd._fullLayout._modeBar; + relayoutCallback = jasmine.createSpy('relayoutCallback'); + gd.on('plotly_relayout', relayoutCallback); + + var buttonPan = selectButton(modeBar, 'pan2d'); + + expect(gd.layout.xaxis.range).toBeCloseToArray(originalX, precision); + expect(gd.layout.yaxis.range).toBeCloseToArray(originalY, precision); + + // Switch to pan mode + expect(buttonPan.isActive()).toBe(false); // initially, zoom is active + buttonPan.click(); + expect(buttonPan.isActive()).toBe(true); // switched on dragmode + // Switching mode must not change visible range + expect(gd.layout.xaxis.range).toBeCloseToArray(originalX, precision); + expect(gd.layout.yaxis.range).toBeCloseToArray(originalY, precision); + }) + .then(delay(MODEBAR_DELAY)) + .then(function() { expect(relayoutCallback).toHaveBeenCalledTimes(1); relayoutCallback.calls.reset(); _runDrag(originalX, newX, originalY, newY); From b9513a22396454123649581c38903e802bceefa3 Mon Sep 17 00:00:00 2001 From: etienne Date: Fri, 16 Feb 2018 18:04:05 -0500 Subject: [PATCH 4/5] fixup and :lock: `cliponaxis: false` pan interactions --- src/components/drawing/index.js | 2 +- test/jasmine/tests/cartesian_interact_test.js | 91 ++++++++++++++++++- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/src/components/drawing/index.js b/src/components/drawing/index.js index 77767079e08..bf185066f85 100644 --- a/src/components/drawing/index.js +++ b/src/components/drawing/index.js @@ -103,7 +103,7 @@ drawing.hideOutsideRangePoint = function(d, sel, xa, ya, xcalendar, ycalendar) { drawing.hideOutsideRangePoints = function(traceGroups, subplot, selector) { if(!subplot._hasClipOnAxisFalse) return; - selector = selector || '.point,textpoint'; + selector = selector || '.point,.textpoint'; var xa = subplot.xaxis; var ya = subplot.yaxis; diff --git a/test/jasmine/tests/cartesian_interact_test.js b/test/jasmine/tests/cartesian_interact_test.js index d215aff5702..bb9d6c3073b 100644 --- a/test/jasmine/tests/cartesian_interact_test.js +++ b/test/jasmine/tests/cartesian_interact_test.js @@ -14,6 +14,9 @@ var doubleClick = require('../assets/double_click'); var getNodeCoords = require('../assets/get_node_coords'); var delay = require('../assets/delay'); +var customAssertions = require('../assets/custom_assertions'); +var assertNodeDisplay = customAssertions.assertNodeDisplay; + var MODEBAR_DELAY = 500; describe('zoom box element', function() { @@ -62,7 +65,6 @@ describe('zoom box element', function() { describe('main plot pan', function() { - var gd, modeBar, relayoutCallback; beforeEach(function() { @@ -183,6 +185,93 @@ describe('main plot pan', function() { .catch(failTest) .then(done); }); + + it('should show/hide `cliponaxis: false` pts according to range', function(done) { + function _assert(markerDisplay, textDisplay, barTextDisplay) { + var gd3 = d3.select(gd); + + assertNodeDisplay( + gd3.select('.scatterlayer').selectAll('.point'), + markerDisplay, + 'marker pts' + ); + assertNodeDisplay( + gd3.select('.scatterlayer').selectAll('.textpoint'), + textDisplay, + 'text pts' + ); + assertNodeDisplay( + gd3.select('.barlayer').selectAll('.bartext'), + barTextDisplay, + 'bar text' + ); + } + + function _run(p0, p1, markerDisplay, textDisplay, barTextDisplay) { + mouseEvent('mousedown', p0[0], p0[1]); + mouseEvent('mousemove', p1[0], p1[1]); + + _assert(markerDisplay, textDisplay, barTextDisplay); + + mouseEvent('mouseup', p1[0], p1[1]); + } + + Plotly.newPlot(gd, [{ + mode: 'markers+text', + x: [1, 2, 3], + y: [1, 2, 3], + text: ['a', 'b', 'c'], + cliponaxis: false + }, { + type: 'bar', + x: [1, 2, 3], + y: [1, 2, 3], + text: ['a', 'b', 'c'], + textposition: 'outside', + cliponaxis: false + }], { + xaxis: {range: [0, 4]}, + yaxis: {range: [0, 4]}, + width: 500, + height: 500, + dragmode: 'pan' + }) + .then(function() { + _assert( + [null, null, null], + [null, null, null], + [null, null, null] + ); + }) + .then(function() { + _run( + [250, 250], [250, 150], + [null, null, 'none'], + [null, null, 'none'], + [null, null, 'none'] + ); + expect(gd._fullLayout.yaxis.range[1]).toBeLessThan(3); + }) + .then(function() { + _run( + [250, 250], [150, 250], + ['none', null, 'none'], + ['none', null, 'none'], + ['none', null, 'none'] + ); + expect(gd._fullLayout.xaxis.range[0]).toBeGreaterThan(1); + }) + .then(function() { + _run( + [250, 250], [350, 350], + [null, null, null], + [null, null, null], + [null, null, null] + ); + }) + .catch(failTest) + .then(done); + }); }); describe('axis zoom/pan and main plot zoom', function() { From 8406b1fdf2784acc3ee61d5bbb5f866c2f26086a Mon Sep 17 00:00:00 2001 From: etienne Date: Fri, 16 Feb 2018 18:04:15 -0500 Subject: [PATCH 5/5] add a couple more @flaky tags --- test/jasmine/tests/select_test.js | 2 +- test/jasmine/tests/shapes_test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/jasmine/tests/select_test.js b/test/jasmine/tests/select_test.js index eb92824a06a..644a7d6a4c6 100644 --- a/test/jasmine/tests/select_test.js +++ b/test/jasmine/tests/select_test.js @@ -554,7 +554,7 @@ describe('@flaky Test select box and lasso in general:', function() { }); }); -describe('Test select box and lasso per trace:', function() { +describe('@flaky Test select box and lasso per trace:', function() { var gd; beforeEach(function() { diff --git a/test/jasmine/tests/shapes_test.js b/test/jasmine/tests/shapes_test.js index fb9e1247dd3..d68230c145d 100644 --- a/test/jasmine/tests/shapes_test.js +++ b/test/jasmine/tests/shapes_test.js @@ -629,7 +629,7 @@ describe('Test shapes: a plot with shapes and an overlaid axis', function() { }); }); -describe('Test shapes', function() { +describe('@flaky Test shapes', function() { 'use strict'; var gd, data, layout, config;