From 90e99f465c4d3b0e6fd22378f914ffa75b01dacb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 4 Jul 2019 16:18:33 -0400 Subject: [PATCH 1/6] stash node3 on calcdata[i][0] of SVG during makeTraceGroup - which is a more centralised DRY place - use nodeRangePlot3 for range-plot trace, that way we don't override node3 when plotting a trace in a range-plot --- src/lib/make_trace_groups.js | 8 +++++++- src/plots/cartesian/index.js | 3 ++- src/traces/bar/plot.js | 2 -- src/traces/barpolar/plot.js | 4 ++-- src/traces/box/plot.js | 1 - src/traces/choropleth/plot.js | 2 +- src/traces/ohlc/plot.js | 1 - src/traces/scatter/plot.js | 2 +- src/traces/scattergeo/plot.js | 2 +- src/traces/violin/plot.js | 1 - 10 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/lib/make_trace_groups.js b/src/lib/make_trace_groups.js index ddc542fbe7b..31ccac53a55 100644 --- a/src/lib/make_trace_groups.js +++ b/src/lib/make_trace_groups.js @@ -6,9 +6,10 @@ * LICENSE file in the root directory of this source tree. */ - 'use strict'; +var d3 = require('d3'); + /** * General helper to manage trace groups based on calcdata * @@ -31,5 +32,10 @@ module.exports = function makeTraceGroups(traceLayer, cdModule, cls) { traces.order(); + // stash ref node to trace group in calcdata, + // useful for (fast) styleOnSelect + var k = traceLayer.classed('rangeplot') ? 'nodeRangePlot3' : 'node3'; + traces.each(function(cd) { cd[0][k] = d3.select(this); }); + return traces; }; diff --git a/src/plots/cartesian/index.js b/src/plots/cartesian/index.js index 29aa0f73c3b..9b46d2ce4d0 100644 --- a/src/plots/cartesian/index.js +++ b/src/plots/cartesian/index.js @@ -239,7 +239,8 @@ function plotOne(gd, plotinfo, cdSubplot, transitionOpts, makeOnCompleteCallback layers.enter().append('g') .attr('class', function(d) { return d.className; }) - .classed('mlayer', true); + .classed('mlayer', true) + .classed('rangeplot', plotinfo.isRangePlot); layers.exit().remove(); diff --git a/src/traces/bar/plot.js b/src/traces/bar/plot.js index 778ac7ebd0b..90c5fb2e46d 100644 --- a/src/traces/bar/plot.js +++ b/src/traces/bar/plot.js @@ -78,8 +78,6 @@ function plot(gd, plotinfo, cdModule, traceLayer, opts) { var isHorizontal = (trace.orientation === 'h'); - if(!plotinfo.isRangePlot) cd[0].node3 = plotGroup; - var pointGroup = Lib.ensureSingle(plotGroup, 'g', 'points'); var bars = pointGroup.selectAll('g.point').data(Lib.identity); diff --git a/src/traces/barpolar/plot.js b/src/traces/barpolar/plot.js index a627c07cdfb..256348eca03 100644 --- a/src/traces/barpolar/plot.js +++ b/src/traces/barpolar/plot.js @@ -23,8 +23,8 @@ module.exports = function plot(gd, subplot, cdbar) { var pathFn = makePathFn(subplot); var barLayer = subplot.layers.frontplot.select('g.barlayer'); - Lib.makeTraceGroups(barLayer, cdbar, 'trace bars').each(function(cd) { - var plotGroup = cd[0].node3 = d3.select(this); + Lib.makeTraceGroups(barLayer, cdbar, 'trace bars').each(function() { + var plotGroup = d3.select(this); var pointGroup = Lib.ensureSingle(plotGroup, 'g', 'points'); var bars = pointGroup.selectAll('g.point').data(Lib.identity); diff --git a/src/traces/box/plot.js b/src/traces/box/plot.js index 6d7f03715aa..3a1eefdfa85 100644 --- a/src/traces/box/plot.js +++ b/src/traces/box/plot.js @@ -26,7 +26,6 @@ function plot(gd, plotinfo, cdbox, boxLayer) { var cd0 = cd[0]; var t = cd0.t; var trace = cd0.trace; - if(!plotinfo.isRangePlot) cd0.node3 = plotGroup; // whisker width t.wdPos = t.bdPos * trace.whiskerwidth; diff --git a/src/traces/choropleth/plot.js b/src/traces/choropleth/plot.js index 62a80b65278..dfb2762fdef 100644 --- a/src/traces/choropleth/plot.js +++ b/src/traces/choropleth/plot.js @@ -24,7 +24,7 @@ function plot(gd, geo, calcData) { var choroplethLayer = geo.layers.backplot.select('.choroplethlayer'); Lib.makeTraceGroups(choroplethLayer, calcData, 'trace choropleth').each(function(calcTrace) { - var sel = calcTrace[0].node3 = d3.select(this); + var sel = d3.select(this); var paths = sel.selectAll('path.choroplethlocation') .data(Lib.identity); diff --git a/src/traces/ohlc/plot.js b/src/traces/ohlc/plot.js index 80ef9dc048b..33822bb8ed4 100644 --- a/src/traces/ohlc/plot.js +++ b/src/traces/ohlc/plot.js @@ -21,7 +21,6 @@ module.exports = function plot(gd, plotinfo, cdOHLC, ohlcLayer) { var cd0 = cd[0]; var t = cd0.t; var trace = cd0.trace; - if(!plotinfo.isRangePlot) cd0.node3 = plotGroup; if(trace.visible !== true || t.empty) { plotGroup.remove(); diff --git a/src/traces/scatter/plot.js b/src/traces/scatter/plot.js index f0713e03eb8..735784f18cc 100644 --- a/src/traces/scatter/plot.js +++ b/src/traces/scatter/plot.js @@ -152,7 +152,7 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition if(ownFillDir !== 'x' && ownFillDir !== 'y') ownFillDir = ''; // store node for tweaking by selectPoints - if(!plotinfo.isRangePlot) cdscatter[0].node3 = tr; + cdscatter[0][plotinfo.isRangePlot ? 'nodeRangePlot3' : 'node3'] = tr; var prevRevpath = ''; var prevPolygons = []; diff --git a/src/traces/scattergeo/plot.js b/src/traces/scattergeo/plot.js index aa73745c55b..224ddd9903d 100644 --- a/src/traces/scattergeo/plot.js +++ b/src/traces/scattergeo/plot.js @@ -37,7 +37,7 @@ module.exports = function plot(gd, geo, calcData) { gTraces.selectAll('*').remove(); gTraces.each(function(calcTrace) { - var s = calcTrace[0].node3 = d3.select(this); + var s = d3.select(this); var trace = calcTrace[0].trace; if(subTypes.hasLines(trace) || trace.fill !== 'none') { diff --git a/src/traces/violin/plot.js b/src/traces/violin/plot.js index 1b1b7a148c2..a109fd6cab9 100644 --- a/src/traces/violin/plot.js +++ b/src/traces/violin/plot.js @@ -38,7 +38,6 @@ module.exports = function plot(gd, plotinfo, cdViolins, violinLayer) { var cd0 = cd[0]; var t = cd0.t; var trace = cd0.trace; - if(!plotinfo.isRangePlot) cd0.node3 = plotGroup; if(trace.visible !== true || t.empty) { plotGroup.remove(); From 9c4d1c3994ee73f6588c80b34158b1903b0d1905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 4 Jul 2019 16:45:19 -0400 Subject: [PATCH 2/6] use styleOnSelect in scatterpolar and barpolar - to improve selection perf. --- src/traces/barpolar/index.js | 2 ++ src/traces/scatterpolar/index.js | 1 + 2 files changed, 3 insertions(+) diff --git a/src/traces/barpolar/index.js b/src/traces/barpolar/index.js index 6ebc187a476..e3f300f5ab9 100644 --- a/src/traces/barpolar/index.js +++ b/src/traces/barpolar/index.js @@ -24,7 +24,9 @@ module.exports = { plot: require('./plot'), colorbar: require('../scatter/marker_colorbar'), + style: require('../bar/style').style, + styleOnSelect: require('../bar/style').styleOnSelect, hoverPoints: require('./hover'), selectPoints: require('../bar/select'), diff --git a/src/traces/scatterpolar/index.js b/src/traces/scatterpolar/index.js index 1d27bc52de6..856f76d63b6 100644 --- a/src/traces/scatterpolar/index.js +++ b/src/traces/scatterpolar/index.js @@ -20,6 +20,7 @@ module.exports = { calc: require('./calc'), plot: require('./plot'), style: require('../scatter/style').style, + styleOnSelect: require('../scatter/style').styleOnSelect, hoverPoints: require('./hover').hoverPoints, selectPoints: require('../scatter/select'), From 1f59d532e0bbb4e98af72df236c0478590ceff1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 4 Jul 2019 16:53:15 -0400 Subject: [PATCH 3/6] no need to handle _module.style(gd, cd) signature ... for modules that define a _module.styleOnSelect method --- src/traces/bar/style.js | 4 ++-- src/traces/scatter/style.js | 4 ++-- src/traces/violin/style.js | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/traces/bar/style.js b/src/traces/bar/style.js index 0c96de18145..55ea1f4d5bd 100644 --- a/src/traces/bar/style.js +++ b/src/traces/bar/style.js @@ -20,8 +20,8 @@ var attributeInsideTextFont = attributes.insidetextfont; var attributeOutsideTextFont = attributes.outsidetextfont; var helpers = require('./helpers'); -function style(gd, cd) { - var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.barlayer').selectAll('g.trace'); +function style(gd) { + var s = d3.select(gd).selectAll('g.barlayer').selectAll('g.trace'); var barcount = s.size(); var fullLayout = gd._fullLayout; diff --git a/src/traces/scatter/style.js b/src/traces/scatter/style.js index 1ec69c3a27e..e4328cd2eb8 100644 --- a/src/traces/scatter/style.js +++ b/src/traces/scatter/style.js @@ -13,8 +13,8 @@ var d3 = require('d3'); var Drawing = require('../../components/drawing'); var Registry = require('../../registry'); -function style(gd, cd) { - var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.trace.scatter'); +function style(gd) { + var s = d3.select(gd).selectAll('g.trace.scatter'); s.style('opacity', function(d) { return d[0].trace.opacity; diff --git a/src/traces/violin/style.js b/src/traces/violin/style.js index 6863dc78dab..5d3155fed9c 100644 --- a/src/traces/violin/style.js +++ b/src/traces/violin/style.js @@ -12,8 +12,8 @@ var d3 = require('d3'); var Color = require('../../components/color'); var stylePoints = require('../scatter/style').stylePoints; -module.exports = function style(gd, cd) { - var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.trace.violins'); +module.exports = function style(gd) { + var s = d3.select(gd).selectAll('g.trace.violins'); s.style('opacity', function(d) { return d[0].trace.opacity; }); From 8dfb0c119c1756c8648753d34ee79e5189426914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 4 Jul 2019 16:58:48 -0400 Subject: [PATCH 4/6] rename mapbox traces' style method -> styleOnSelect - as they're only meant to be used on select! --- src/traces/choroplethmapbox/index.js | 2 +- src/traces/scattermapbox/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/traces/choroplethmapbox/index.js b/src/traces/choroplethmapbox/index.js index ca86e51ee44..9da1ee7b0f5 100644 --- a/src/traces/choroplethmapbox/index.js +++ b/src/traces/choroplethmapbox/index.js @@ -18,7 +18,7 @@ module.exports = { eventData: require('../choropleth/event_data'), selectPoints: require('../choropleth/select'), - style: function(_, cd) { + styleOnSelect: function(_, cd) { if(cd) { var trace = cd[0].trace; trace._glTrace.updateOnSelect(cd); diff --git a/src/traces/scattermapbox/index.js b/src/traces/scattermapbox/index.js index f1193815a2e..279b1bad81e 100644 --- a/src/traces/scattermapbox/index.js +++ b/src/traces/scattermapbox/index.js @@ -18,7 +18,7 @@ module.exports = { eventData: require('./event_data'), selectPoints: require('./select'), - style: function(_, cd) { + styleOnSelect: function(_, cd) { if(cd) { var trace = cd[0].trace; trace._glTrace.update(cd); From 6c030c08eb953d3cc1741e9e04e1b066d8d342d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Fri, 5 Jul 2019 11:26:25 -0400 Subject: [PATCH 5/6] use DESELECTDIM constant to style waterfall/funnel pts on-selection --- src/traces/funnel/style.js | 3 ++- src/traces/waterfall/style.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/traces/funnel/style.js b/src/traces/funnel/style.js index b63967684c8..f072bcb581b 100644 --- a/src/traces/funnel/style.js +++ b/src/traces/funnel/style.js @@ -12,6 +12,7 @@ var d3 = require('d3'); var Drawing = require('../../components/drawing'); var Color = require('../../components/color'); +var DESELECTDIM = require('../../constants/interactions').DESELECTDIM; var styleTextPoints = require('../bar/style').styleTextPoints; @@ -32,7 +33,7 @@ function style(gd, cd) { .call(Color.fill, di.mc || cont.color) .call(Color.stroke, di.mlc || cont.line.color) .call(Drawing.dashLine, cont.line.dash, di.mlw || cont.line.width) - .style('opacity', trace.selectedpoints && !di.selected ? 0.3 : 1); + .style('opacity', trace.selectedpoints && !di.selected ? DESELECTDIM : 1); } }); diff --git a/src/traces/waterfall/style.js b/src/traces/waterfall/style.js index 2e33d32d9f6..acacc4ae93a 100644 --- a/src/traces/waterfall/style.js +++ b/src/traces/waterfall/style.js @@ -12,6 +12,7 @@ var d3 = require('d3'); var Drawing = require('../../components/drawing'); var Color = require('../../components/color'); +var DESELECTDIM = require('../../constants/interactions').DESELECTDIM; var styleTextPoints = require('../bar/style').styleTextPoints; @@ -32,7 +33,7 @@ function style(gd, cd) { .call(Color.fill, cont.color) .call(Color.stroke, cont.line.color) .call(Drawing.dashLine, cont.line.dash, cont.line.width) - .style('opacity', trace.selectedpoints && !di.selected ? 0.3 : 1); + .style('opacity', trace.selectedpoints && !di.selected ? DESELECTDIM : 1); } }); From 3e1762706b629930fe36d8607c1156f26adfd687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Thu, 4 Jul 2019 17:05:49 -0400 Subject: [PATCH 6/6] fix #3957 - call _module.style(onSelect) passing rangePlot ... during selection mousemove. To do so, - make _module.styleOnSelect handle a 3rd argument (in practice, a d3 selection of of the main plot OR the range plot) - similarly for _module.style methods that get called during selections - N.B. has to "fix" one (wrong) finance select assertion --- src/plots/cartesian/select.js | 5 +- src/traces/bar/style.js | 10 ++- src/traces/box/style.js | 9 ++- src/traces/funnel/style.js | 4 +- src/traces/ohlc/style.js | 4 +- src/traces/scatter/style.js | 11 ++-- src/traces/waterfall/style.js | 4 +- test/jasmine/tests/scatter_test.js | 2 +- test/jasmine/tests/select_test.js | 97 +++++++++++++++++++++++++++++- 9 files changed, 120 insertions(+), 26 deletions(-) diff --git a/src/plots/cartesian/select.js b/src/plots/cartesian/select.js index ea704fad597..f49cc390164 100644 --- a/src/plots/cartesian/select.js +++ b/src/plots/cartesian/select.js @@ -734,7 +734,10 @@ function updateSelectedState(gd, searchTraces, eventData) { var _module = searchInfo._module; var fn = _module.styleOnSelect || _module.style; - if(fn) fn(gd, cd); + if(fn) { + fn(gd, cd, cd[0].node3); + if(cd[0].nodeRangePlot3) fn(gd, cd, cd[0].nodeRangePlot3); + } } if(hasRegl) { diff --git a/src/traces/bar/style.js b/src/traces/bar/style.js index 55ea1f4d5bd..b781d301854 100644 --- a/src/traces/bar/style.js +++ b/src/traces/bar/style.js @@ -62,16 +62,14 @@ function styleTextPoints(sel, trace, gd) { }); } -function styleOnSelect(gd, cd) { - var s = cd[0].node3; +function styleOnSelect(gd, cd, sel) { var trace = cd[0].trace; if(trace.selectedpoints) { - stylePointsInSelectionMode(s, trace, gd); + stylePointsInSelectionMode(sel, trace, gd); } else { - stylePoints(s, trace, gd); - - Registry.getComponentMethod('errorbars', 'style')(s); + stylePoints(sel, trace, gd); + Registry.getComponentMethod('errorbars', 'style')(sel); } } diff --git a/src/traces/box/style.js b/src/traces/box/style.js index d7851411177..e14f45ec78a 100644 --- a/src/traces/box/style.js +++ b/src/traces/box/style.js @@ -12,8 +12,8 @@ var d3 = require('d3'); var Color = require('../../components/color'); var Drawing = require('../../components/drawing'); -function style(gd, cd) { - var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.trace.boxes'); +function style(gd, cd, sel) { + var s = sel ? sel : d3.select(gd).selectAll('g.trace.boxes'); s.style('opacity', function(d) { return d[0].trace.opacity; }); @@ -55,10 +55,9 @@ function style(gd, cd) { }); } -function styleOnSelect(gd, cd) { - var s = cd[0].node3; +function styleOnSelect(gd, cd, sel) { var trace = cd[0].trace; - var pts = s.selectAll('path.point'); + var pts = sel.selectAll('path.point'); if(trace.selectedpoints) { Drawing.selectedPointStyle(pts, trace); diff --git a/src/traces/funnel/style.js b/src/traces/funnel/style.js index f072bcb581b..e59c81fe864 100644 --- a/src/traces/funnel/style.js +++ b/src/traces/funnel/style.js @@ -16,8 +16,8 @@ var DESELECTDIM = require('../../constants/interactions').DESELECTDIM; var styleTextPoints = require('../bar/style').styleTextPoints; -function style(gd, cd) { - var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.funnellayer').selectAll('g.trace'); +function style(gd, cd, sel) { + var s = sel ? sel : d3.select(gd).selectAll('g.funnellayer').selectAll('g.trace'); s.style('opacity', function(d) { return d[0].trace.opacity; }); diff --git a/src/traces/ohlc/style.js b/src/traces/ohlc/style.js index a708d108b1f..7b04ff1e802 100644 --- a/src/traces/ohlc/style.js +++ b/src/traces/ohlc/style.js @@ -12,8 +12,8 @@ var d3 = require('d3'); var Drawing = require('../../components/drawing'); var Color = require('../../components/color'); -module.exports = function style(gd, cd) { - var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.ohlclayer').selectAll('g.trace'); +module.exports = function style(gd, cd, sel) { + var s = sel ? sel : d3.select(gd).selectAll('g.ohlclayer').selectAll('g.trace'); s.style('opacity', function(d) { return d[0].trace.opacity; diff --git a/src/traces/scatter/style.js b/src/traces/scatter/style.js index e4328cd2eb8..ea2c1bc50e2 100644 --- a/src/traces/scatter/style.js +++ b/src/traces/scatter/style.js @@ -49,16 +49,15 @@ function styleText(sel, trace, gd) { Drawing.textPointStyle(sel.selectAll('text'), trace, gd); } -function styleOnSelect(gd, cd) { - var s = cd[0].node3; +function styleOnSelect(gd, cd, sel) { var trace = cd[0].trace; if(trace.selectedpoints) { - Drawing.selectedPointStyle(s.selectAll('path.point'), trace); - Drawing.selectedTextStyle(s.selectAll('text'), trace); + Drawing.selectedPointStyle(sel.selectAll('path.point'), trace); + Drawing.selectedTextStyle(sel.selectAll('text'), trace); } else { - stylePoints(s, trace, gd); - styleText(s, trace, gd); + stylePoints(sel, trace, gd); + styleText(sel, trace, gd); } } diff --git a/src/traces/waterfall/style.js b/src/traces/waterfall/style.js index acacc4ae93a..8026fb28176 100644 --- a/src/traces/waterfall/style.js +++ b/src/traces/waterfall/style.js @@ -16,8 +16,8 @@ var DESELECTDIM = require('../../constants/interactions').DESELECTDIM; var styleTextPoints = require('../bar/style').styleTextPoints; -function style(gd, cd) { - var s = cd ? cd[0].node3 : d3.select(gd).selectAll('g.waterfalllayer').selectAll('g.trace'); +function style(gd, cd, sel) { + var s = sel ? sel : d3.select(gd).selectAll('g.waterfalllayer').selectAll('g.trace'); s.style('opacity', function(d) { return d[0].trace.opacity; }); diff --git a/test/jasmine/tests/scatter_test.js b/test/jasmine/tests/scatter_test.js index a20945e303d..1c24d177a3b 100644 --- a/test/jasmine/tests/scatter_test.js +++ b/test/jasmine/tests/scatter_test.js @@ -1452,7 +1452,7 @@ describe('Test Scatter.style', function() { // make sure styleOnSelect (called during selection) // gives same results as restyle gd.calcdata.forEach(function(cd) { - Scatter.styleOnSelect(gd, cd); + Scatter.styleOnSelect(gd, cd, cd[0].node3); }); assertPts(attr, getterFn, expectation, ' (' + msg + ' via Scatter.styleOnSelect)'); }); diff --git a/test/jasmine/tests/select_test.js b/test/jasmine/tests/select_test.js index a8fb7f7050d..3437485e91a 100644 --- a/test/jasmine/tests/select_test.js +++ b/test/jasmine/tests/select_test.js @@ -2802,7 +2802,7 @@ describe('Test select box and lasso per trace:', function() { [tv, bv, bv, tv, tv] ]); expect(countUnSelectedPaths('.cartesianlayer .trace path')).toBe(2); - expect(countUnSelectedPaths('.rangeslider-rangeplot .trace path')).toBe(0); + expect(countUnSelectedPaths('.rangeslider-rangeplot .trace path')).toBe(2); }, null, LASSOEVENTS, type + ' lasso' ); @@ -3123,6 +3123,101 @@ describe('Test that selections persist:', function() { }); }); +describe('Test that selection styles propagate to range-slider plot:', function() { + var gd; + + beforeEach(function() { + gd = createGraphDiv(); + }); + + afterEach(destroyGraphDiv); + + function makeAssertFn(query) { + return function(msg, expected) { + var gd3 = d3.select(gd); + var mainPlot3 = gd3.select('.cartesianlayer'); + var rangePlot3 = gd3.select('.rangeslider-rangeplot'); + + mainPlot3.selectAll(query).each(function(_, i) { + expect(this.style.opacity).toBe(String(expected[i]), msg + ' opacity for mainPlot pt ' + i); + }); + rangePlot3.selectAll(query).each(function(_, i) { + expect(this.style.opacity).toBe(String(expected[i]), msg + ' opacity for rangePlot pt ' + i); + }); + }; + } + + it('- svg points case', function(done) { + var _assert = makeAssertFn('path.point,.point>path'); + + Plotly.plot(gd, [ + { mode: 'markers', x: [1], y: [1] }, + { type: 'bar', x: [2], y: [2], }, + { type: 'histogram', x: [3, 3, 3] }, + { type: 'box', x: [4], y: [4], boxpoints: 'all' }, + { type: 'violin', x: [5], y: [5], points: 'all' }, + { type: 'waterfall', x: [6], y: [6]}, + { type: 'funnel', x: [7], y: [7], orientation: 'v'} + ], { + dragmode: 'select', + xaxis: { rangeslider: {visible: true} }, + width: 500, + height: 500, + margin: {l: 10, t: 10, r: 10, b: 10}, + showlegend: false + }) + .then(function() { + _assert('base', [1, 1, 1, 1, 1, 1, 1]); + }) + .then(function() { + resetEvents(gd); + drag([[20, 20], [40, 40]]); + return selectedPromise; + }) + .then(function() { + _assert('after empty selection', [0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2]); + }) + .then(function() { return doubleClick(200, 200); }) + .then(function() { + _assert('after double-click reset', [1, 1, 1, 1, 1, 1, 1]); + }) + .catch(failTest) + .then(done); + }); + + it('- svg finance case', function(done) { + var _assert = makeAssertFn('path.box,.ohlc>path'); + + Plotly.plot(gd, [ + { type: 'ohlc', x: [6], open: [6], high: [6], low: [6], close: [6] }, + { type: 'candlestick', x: [7], open: [7], high: [7], low: [7], close: [7] }, + ], { + dragmode: 'select', + width: 500, + height: 500, + margin: {l: 10, t: 10, r: 10, b: 10}, + showlegend: false + }) + .then(function() { + _assert('base', [1, 1]); + }) + .then(function() { + resetEvents(gd); + drag([[20, 20], [40, 40]]); + return selectedPromise; + }) + .then(function() { + _assert('after empty selection', [0.3, 0.3]); + }) + .then(function() { return doubleClick(200, 200); }) + .then(function() { + _assert('after double-click reset', [1, 1]); + }) + .catch(failTest) + .then(done); + }); +}); + // to make sure none of the above tests fail with extraneous invisible traces, // add a bunch of them here function addInvisible(fig, canHaveLegend) {