diff --git a/draftlogs/7009_change.md b/draftlogs/7009_change.md new file mode 100644 index 00000000000..f804cd26073 --- /dev/null +++ b/draftlogs/7009_change.md @@ -0,0 +1 @@ +- Make offsetgroup work with barmode 'stacked' and 'relative' for bar traces [[#7009](https://github.com/plotly/plotly.js/pull/7009)] \ No newline at end of file diff --git a/src/traces/bar/cross_trace_calc.js b/src/traces/bar/cross_trace_calc.js index 61df5cf4d23..ea1757df2f1 100644 --- a/src/traces/bar/cross_trace_calc.js +++ b/src/traces/bar/cross_trace_calc.js @@ -75,7 +75,7 @@ function setGroupPositions(gd, pa, sa, calcTraces, opts) { switch(opts.mode) { case 'overlay': - setGroupPositionsInOverlayMode(pa, sa, calcTraces, opts); + setGroupPositionsInOverlayMode(gd, pa, sa, calcTraces, opts); break; case 'group': @@ -94,7 +94,7 @@ function setGroupPositions(gd, pa, sa, calcTraces, opts) { setGroupPositionsInGroupMode(gd, pa, sa, included, opts); } if(excluded.length) { - setGroupPositionsInOverlayMode(pa, sa, excluded, opts); + setGroupPositionsInOverlayMode(gd, pa, sa, excluded, opts); } break; @@ -119,7 +119,7 @@ function setGroupPositions(gd, pa, sa, calcTraces, opts) { setGroupPositionsInStackOrRelativeMode(gd, pa, sa, included, opts); } if(excluded.length) { - setGroupPositionsInOverlayMode(pa, sa, excluded, opts); + setGroupPositionsInOverlayMode(gd, pa, sa, excluded, opts); } break; } @@ -217,7 +217,7 @@ function initBase(sa, calcTraces) { } } -function setGroupPositionsInOverlayMode(pa, sa, calcTraces, opts) { +function setGroupPositionsInOverlayMode(gd, pa, sa, calcTraces, opts) { // update position axis and set bar offsets and widths for(var i = 0; i < calcTraces.length; i++) { var calcTrace = calcTraces[i]; @@ -229,7 +229,7 @@ function setGroupPositionsInOverlayMode(pa, sa, calcTraces, opts) { }); // set bar offsets and widths, and update position axis - setOffsetAndWidth(pa, sieve, opts); + setOffsetAndWidth(gd, pa, sieve, opts); // set bar bases and sizes, and update size axis // @@ -253,7 +253,7 @@ function setGroupPositionsInGroupMode(gd, pa, sa, calcTraces, opts) { }); // set bar offsets and widths, and update position axis - setOffsetAndWidthInGroupMode(gd, pa, sieve, opts); + setOffsetAndWidth(gd, pa, sieve, opts); // relative-stack bars within the same trace that would otherwise // be hidden @@ -276,7 +276,7 @@ function setGroupPositionsInStackOrRelativeMode(gd, pa, sa, calcTraces, opts) { }); // set bar offsets and widths, and update position axis - setOffsetAndWidth(pa, sieve, opts); + setOffsetAndWidth(gd, pa, sieve, opts); // set bar bases and sizes, and update size axis stackBars(sa, sieve, opts); @@ -284,12 +284,12 @@ function setGroupPositionsInStackOrRelativeMode(gd, pa, sa, calcTraces, opts) { // flag the outmost bar (for text display purposes) for(var i = 0; i < calcTraces.length; i++) { var calcTrace = calcTraces[i]; - + var offsetIndex = calcTrace[0].t.offsetindex; for(var j = 0; j < calcTrace.length; j++) { var bar = calcTrace[j]; if(bar.s !== BADNUM) { - var isOutmostBar = ((bar.b + bar.s) === sieve.get(bar.p, bar.s)); + var isOutmostBar = ((bar.b + bar.s) === sieve.get(bar.p, offsetIndex, bar.s)); if(isOutmostBar) bar._outmost = true; } } @@ -300,43 +300,19 @@ function setGroupPositionsInStackOrRelativeMode(gd, pa, sa, calcTraces, opts) { if(opts.norm) normalizeBars(sa, sieve, opts); } -function setOffsetAndWidth(pa, sieve, opts) { - var minDiff = sieve.minDiff; - var calcTraces = sieve.traces; - - // set bar offsets and widths - var barGroupWidth = minDiff * (1 - opts.gap); - var barWidthPlusGap = barGroupWidth; - var barWidth = barWidthPlusGap * (1 - (opts.groupgap || 0)); - - // computer bar group center and bar offset - var offsetFromCenter = -barWidth / 2; - - for(var i = 0; i < calcTraces.length; i++) { - var calcTrace = calcTraces[i]; - var t = calcTrace[0].t; - - // store bar width and offset for this trace - t.barwidth = barWidth; - t.poffset = offsetFromCenter; - t.bargroupwidth = barGroupWidth; - t.bardelta = minDiff; - } - - // stack bars that only differ by rounding - sieve.binWidth = calcTraces[0][0].t.barwidth / 100; - - // if defined, apply trace offset and width - applyAttributes(sieve); - - // store the bar center in each calcdata item - setBarCenterAndWidth(pa, sieve); - - // update position axes - updatePositionAxis(pa, sieve); -} - -function setOffsetAndWidthInGroupMode(gd, pa, sieve, opts) { +/** + * Mode group: Traces should be offsetted to other traces at the same position if they have a + * different offsetgroup or if no offsetgroups are specified. + * If there are no other traces at the same position, the trace will not be offsetted and it + * can occupy the whole width. + * If two traces share an offsetgroup, they should overlap. + * Mode overlay/stack/relative: Traces should be offseted to other traces at the same position if + * they have a different offsetgroup. + * If two traces share an offsetgroup or if no offsetgroups are specified, they should instead + * overlap/stack. + * Angular axes (for barpolar type) don't support group offsets. + */ +function setOffsetAndWidth(gd, pa, sieve, opts) { var fullLayout = gd._fullLayout; var positions = sieve.positions; var distinctPositions = sieve.distinctPositions; @@ -347,38 +323,48 @@ function setOffsetAndWidthInGroupMode(gd, pa, sieve, opts) { // if there aren't any overlapping positions, // let them have full width even if mode is group var overlap = (positions.length !== distinctPositions.length); - var barGroupWidth = minDiff * (1 - opts.gap); - var groupId = getAxisGroup(fullLayout, pa._id) + calcTraces[0][0].trace.orientation; - var alignmentGroups = fullLayout._alignmentOpts[groupId] || {}; + var barGroupWidth = minDiff * (1 - opts.gap); + var barWidthPlusGap; + var barWidth; + var offsetFromCenter; + var alignmentGroups; + if(pa._id === 'angularaxis') { + barWidthPlusGap = barGroupWidth; + barWidth = barWidthPlusGap * (1 - (opts.groupgap || 0)); + offsetFromCenter = -barWidth / 2; + } else { // collect groups and calculate values in loop below + var groupId = getAxisGroup(fullLayout, pa._id) + calcTraces[0][0].trace.orientation; + alignmentGroups = fullLayout._alignmentOpts[groupId] || {}; + } for(var i = 0; i < nTraces; i++) { var calcTrace = calcTraces[i]; var trace = calcTrace[0].trace; + if(pa._id !== 'angularaxis') { + var alignmentGroupOpts = alignmentGroups[trace.alignmentgroup] || {}; + var nOffsetGroups = Object.keys(alignmentGroupOpts.offsetGroups || {}).length; - var alignmentGroupOpts = alignmentGroups[trace.alignmentgroup] || {}; - var nOffsetGroups = Object.keys(alignmentGroupOpts.offsetGroups || {}).length; - - var barWidthPlusGap; - if(nOffsetGroups) { - barWidthPlusGap = barGroupWidth / nOffsetGroups; - } else { - barWidthPlusGap = overlap ? barGroupWidth / nTraces : barGroupWidth; - } + if(nOffsetGroups) { + barWidthPlusGap = barGroupWidth / nOffsetGroups; + } else { + barWidthPlusGap = overlap ? barGroupWidth / nTraces : barGroupWidth; + } - var barWidth = barWidthPlusGap * (1 - (opts.groupgap || 0)); + barWidth = barWidthPlusGap * (1 - (opts.groupgap || 0)); - var offsetFromCenter; - if(nOffsetGroups) { - offsetFromCenter = ((2 * trace._offsetIndex + 1 - nOffsetGroups) * barWidthPlusGap - barWidth) / 2; - } else { - offsetFromCenter = overlap ? - ((2 * i + 1 - nTraces) * barWidthPlusGap - barWidth) / 2 : - -barWidth / 2; + if(nOffsetGroups) { + offsetFromCenter = ((2 * trace._offsetIndex + 1 - nOffsetGroups) * barWidthPlusGap - barWidth) / 2; + } else { + offsetFromCenter = overlap ? + ((2 * i + 1 - nTraces) * barWidthPlusGap - barWidth) / 2 : + -barWidth / 2; + } } var t = calcTrace[0].t; t.barwidth = barWidth; + t.offsetindex = trace._offsetIndex || 0; t.poffset = offsetFromCenter; t.bargroupwidth = barGroupWidth; t.bardelta = minDiff; @@ -394,7 +380,11 @@ function setOffsetAndWidthInGroupMode(gd, pa, sieve, opts) { setBarCenterAndWidth(pa, sieve); // update position axes - updatePositionAxis(pa, sieve, overlap); + if(pa._id === 'angularaxis') { + updatePositionAxis(pa, sieve); + } else { + updatePositionAxis(pa, sieve, overlap); + } } function applyAttributes(sieve) { @@ -592,18 +582,20 @@ function stackBars(sa, sieve, opts) { var isFunnel; var i, j; var bar; + var offsetIndex; for(i = 0; i < calcTraces.length; i++) { calcTrace = calcTraces[i]; fullTrace = calcTrace[0].trace; if(fullTrace.type === 'funnel') { + offsetIndex = calcTrace[0].t.offsetindex; for(j = 0; j < calcTrace.length; j++) { bar = calcTrace[j]; if(bar.s !== BADNUM) { // create base of funnels - sieve.put(bar.p, -0.5 * bar.s); + sieve.put(bar.p, offsetIndex, -0.5 * bar.s); } } } @@ -615,6 +607,8 @@ function stackBars(sa, sieve, opts) { isFunnel = (fullTrace.type === 'funnel'); + offsetIndex = fullTrace.type === 'barpolar' ? 0 : calcTrace[0].t.offsetindex; + var pts = []; for(j = 0; j < calcTrace.length; j++) { @@ -629,8 +623,7 @@ function stackBars(sa, sieve, opts) { value = bar.s + bar.b; } - var base = sieve.put(bar.p, value); - + var base = sieve.put(bar.p, offsetIndex, value); var top = base + value; // store the bar base and top in each calcdata item @@ -663,12 +656,12 @@ function sieveBars(sieve) { for(var i = 0; i < calcTraces.length; i++) { var calcTrace = calcTraces[i]; - + var offsetIndex = calcTrace[0].t.offsetindex; for(var j = 0; j < calcTrace.length; j++) { var bar = calcTrace[j]; if(bar.s !== BADNUM) { - sieve.put(bar.p, bar.b + bar.s); + sieve.put(bar.p, offsetIndex, bar.b + bar.s); } } } @@ -680,6 +673,7 @@ function unhideBarsWithinTrace(sieve, pa) { for(var i = 0; i < calcTraces.length; i++) { var calcTrace = calcTraces[i]; var fullTrace = calcTrace[0].trace; + var offsetIndex = calcTrace[0].t.offsetindex; if(fullTrace.base === undefined) { var inTraceSieve = new Sieve([calcTrace], { @@ -693,7 +687,7 @@ function unhideBarsWithinTrace(sieve, pa) { if(bar.p !== BADNUM) { // stack current bar and get previous sum - var base = inTraceSieve.put(bar.p, bar.b + bar.s); + var base = inTraceSieve.put(bar.p, offsetIndex, bar.b + bar.s); // if previous sum if non-zero, this means: // multiple bars have same starting point are potentially hidden, @@ -726,6 +720,7 @@ function normalizeBars(sa, sieve, opts) { for(var i = 0; i < calcTraces.length; i++) { var calcTrace = calcTraces[i]; + var offsetIndex = calcTrace[0].t.offsetindex; var fullTrace = calcTrace[0].trace; var pts = []; var tozero = false; @@ -735,7 +730,7 @@ function normalizeBars(sa, sieve, opts) { var bar = calcTrace[j]; if(bar.s !== BADNUM) { - var scale = Math.abs(sTop / sieve.get(bar.p, bar.s)); + var scale = Math.abs(sTop / sieve.get(bar.p, offsetIndex, bar.s)); bar.b *= scale; bar.s *= scale; diff --git a/src/traces/bar/defaults.js b/src/traces/bar/defaults.js index b969e30b1ee..66cd408b06f 100644 --- a/src/traces/bar/defaults.js +++ b/src/traces/bar/defaults.js @@ -80,9 +80,7 @@ function crossTraceDefaults(fullData, fullLayout) { traceOut.marker.cornerradius = validateCornerradius(r); } - if(fullLayout.barmode === 'group') { - handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce); - } + handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce, fullLayout.barmode); } } } diff --git a/src/traces/bar/layout_defaults.js b/src/traces/bar/layout_defaults.js index bebe022d8a6..47f417d6326 100644 --- a/src/traces/bar/layout_defaults.js +++ b/src/traces/bar/layout_defaults.js @@ -19,6 +19,7 @@ module.exports = function(layoutIn, layoutOut, fullData) { var usedSubplots = {}; var mode = coerce('barmode'); + var isGroup = mode === 'group'; for(var i = 0; i < fullData.length; i++) { var trace = fullData[i]; @@ -27,10 +28,17 @@ module.exports = function(layoutIn, layoutOut, fullData) { // if we have at least 2 grouped bar traces on the same subplot, // we should default to a gap anyway, even if the data is histograms - if(mode === 'group') { - var subploti = trace.xaxis + trace.yaxis; + var subploti = trace.xaxis + trace.yaxis; + if(isGroup) { + // with barmode group, bars are grouped next to each other when sharing the same axes if(usedSubplots[subploti]) gappedAnyway = true; usedSubplots[subploti] = true; + } else { + // with other barmodes bars are grouped next to each other when sharing the same axes + // and using different offsetgroups + subploti += trace._input.offsetgroup; + if(usedSubplots.length > 0 && !usedSubplots[subploti]) gappedAnyway = true; + usedSubplots[subploti] = true; } if(trace.visible && trace.type === 'histogram') { diff --git a/src/traces/bar/sieve.js b/src/traces/bar/sieve.js index 54dc5a74b25..1af738edff9 100644 --- a/src/traces/bar/sieve.js +++ b/src/traces/bar/sieve.js @@ -66,11 +66,12 @@ function Sieve(traces, opts) { * * @method * @param {number} position + * @param {number} group * @param {number} value * @returns {number} Previous bin value */ -Sieve.prototype.put = function put(position, value) { - var label = this.getLabel(position, value); +Sieve.prototype.put = function put(position, group, value) { + var label = this.getLabel(position, group, value); var oldValue = this.bins[label] || 0; this.bins[label] = oldValue + value; @@ -83,12 +84,13 @@ Sieve.prototype.put = function put(position, value) { * * @method * @param {number} position Position of datum + * @param {number} group * @param {number} [value] Value of datum * (required if this.sepNegVal is true) * @returns {number} Current bin value */ -Sieve.prototype.get = function get(position, value) { - var label = this.getLabel(position, value); +Sieve.prototype.get = function get(position, group, value) { + var label = this.getLabel(position, group, value); return this.bins[label] || 0; }; @@ -97,16 +99,17 @@ Sieve.prototype.get = function get(position, value) { * * @method * @param {number} position Position of datum + * @param {number} group * @param {number} [value] Value of datum * (required if this.sepNegVal is true) * @returns {string} Bin label * (prefixed with a 'v' if value is negative and this.sepNegVal is * true; otherwise prefixed with '^') */ -Sieve.prototype.getLabel = function getLabel(position, value) { +Sieve.prototype.getLabel = function getLabel(position, group, value) { var prefix = (value < 0 && this.sepNegVal) ? 'v' : '^'; var label = (this.overlapNoMerge) ? position : Math.round(position / this.binWidth); - return prefix + label; + return prefix + label + 'g' + group; }; diff --git a/src/traces/box/defaults.js b/src/traces/box/defaults.js index 0e9a5a71591..8241e0cb140 100644 --- a/src/traces/box/defaults.js +++ b/src/traces/box/defaults.js @@ -303,8 +303,9 @@ function crossTraceDefaults(fullData, fullLayout) { if(traceType === 'box' || traceType === 'violin') { traceIn = traceOut._input; - if(fullLayout[traceType + 'mode'] === 'group') { - handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce); + var mode = fullLayout[traceType + 'mode']; + if(mode === 'group') { + handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce, mode); } } } diff --git a/src/traces/funnel/defaults.js b/src/traces/funnel/defaults.js index b8bd941f68e..02a7ad47efa 100644 --- a/src/traces/funnel/defaults.js +++ b/src/traces/funnel/defaults.js @@ -77,12 +77,11 @@ function crossTraceDefaults(fullData, fullLayout) { return Lib.coerce(traceOut._input, traceOut, attributes, attr); } - if(fullLayout.funnelmode === 'group') { - for(var i = 0; i < fullData.length; i++) { - traceOut = fullData[i]; + for(var i = 0; i < fullData.length; i++) { + traceOut = fullData[i]; + if(traceOut.type === 'funnel') { traceIn = traceOut._input; - - handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce); + handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce, fullLayout.funnelmode); } } } diff --git a/src/traces/histogram/cross_trace_defaults.js b/src/traces/histogram/cross_trace_defaults.js index d389c095b68..7342360af0f 100644 --- a/src/traces/histogram/cross_trace_defaults.js +++ b/src/traces/histogram/cross_trace_defaults.js @@ -112,7 +112,7 @@ module.exports = function crossTraceDefaults(fullData, fullLayout) { // N.B. need to coerce *alignmentgroup* before *bingroup*, as traces // in same alignmentgroup "have to match" if(!traceIs(traceOut, '2dMap')) { - handleGroupingDefaults(traceOut._input, traceOut, fullLayout, coerce); + handleGroupingDefaults(traceOut._input, traceOut, fullLayout, coerce, fullLayout.barmode); } } } diff --git a/src/traces/scatter/cross_trace_defaults.js b/src/traces/scatter/cross_trace_defaults.js index 6505c6573d7..2b97dc39532 100644 --- a/src/traces/scatter/cross_trace_defaults.js +++ b/src/traces/scatter/cross_trace_defaults.js @@ -7,6 +7,7 @@ var attributes = require('./attributes'); // remove opacity for any trace that has a fill or is filled to module.exports = function crossTraceDefaults(fullData, fullLayout) { var traceIn, traceOut, i; + var scattermode = fullLayout.scattermode; function coerce(attr) { return Lib.coerce(traceOut._input, traceOut, attributes, attr); @@ -15,10 +16,10 @@ module.exports = function crossTraceDefaults(fullData, fullLayout) { if(fullLayout.scattermode === 'group') { for(i = 0; i < fullData.length; i++) { traceOut = fullData[i]; - + if(traceOut.type === 'scatter') { traceIn = traceOut._input; - handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce); + handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce, scattermode); } } } diff --git a/src/traces/scatter/grouping_defaults.js b/src/traces/scatter/grouping_defaults.js index de957569108..3c3f488ec86 100644 --- a/src/traces/scatter/grouping_defaults.js +++ b/src/traces/scatter/grouping_defaults.js @@ -2,7 +2,7 @@ var getAxisGroup = require('../../plots/cartesian/constraints').getAxisGroup; -module.exports = function handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce) { +module.exports = function handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce, barmode) { var orientation = traceOut.orientation; // N.B. grouping is done across all trace types that support it var posAxId = traceOut[{v: 'x', h: 'y'}[orientation] + 'axis']; @@ -26,11 +26,13 @@ module.exports = function handleGroupingDefaults(traceIn, traceOut, fullLayout, }; } - var offsetgroup = coerce('offsetgroup'); + var offsetgroup = coerce('offsetgroup') || ''; var offsetGroups = alignmentGroupOpts.offsetGroups; var offsetGroupOpts = offsetGroups[offsetgroup]; - - if(offsetgroup) { + // in barmode 'group', traces without offsetgroup receive their own offsetgroup + // in other barmodes, traces without offsetgroup are assigned to the same offset group + traceOut._offsetIndex = 0; + if(barmode !== 'group' || offsetgroup) { if(!offsetGroupOpts) { offsetGroupOpts = offsetGroups[offsetgroup] = { offsetIndex: Object.keys(offsetGroups).length diff --git a/src/traces/waterfall/defaults.js b/src/traces/waterfall/defaults.js index 067d8aded90..3df93af6f5d 100644 --- a/src/traces/waterfall/defaults.js +++ b/src/traces/waterfall/defaults.js @@ -85,13 +85,12 @@ function crossTraceDefaults(fullData, fullLayout) { function coerce(attr) { return Lib.coerce(traceOut._input, traceOut, attributes, attr); } - if(fullLayout.waterfallmode === 'group') { for(var i = 0; i < fullData.length; i++) { traceOut = fullData[i]; traceIn = traceOut._input; - handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce); + handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce, fullLayout.waterfallmode); } } } diff --git a/test/image/baselines/funnel_attrs.png b/test/image/baselines/funnel_attrs.png index 7d951f1f448..80e74a1ab55 100644 Binary files a/test/image/baselines/funnel_attrs.png and b/test/image/baselines/funnel_attrs.png differ diff --git a/test/image/baselines/legendgroup_bar-stack.png b/test/image/baselines/legendgroup_bar-stack.png index 8d9567907d6..6fad6a2b8a2 100644 Binary files a/test/image/baselines/legendgroup_bar-stack.png and b/test/image/baselines/legendgroup_bar-stack.png differ diff --git a/test/image/baselines/zzz_bar_relative_offsetgroup.png b/test/image/baselines/zzz_bar_relative_offsetgroup.png new file mode 100644 index 00000000000..a95edace642 Binary files /dev/null and b/test/image/baselines/zzz_bar_relative_offsetgroup.png differ diff --git a/test/image/mocks/zzz_bar_relative_offsetgroup.json b/test/image/mocks/zzz_bar_relative_offsetgroup.json new file mode 100644 index 00000000000..9c9df9097f4 --- /dev/null +++ b/test/image/mocks/zzz_bar_relative_offsetgroup.json @@ -0,0 +1,47 @@ +{ + "data": [ + { + "type": "bar", + "x": [ "A", "B", "C"], + "y": [ 10, 10, 10 ], + "offsetgroup": 1, + "hovertext": "offsetgroup: 1" + }, + { + "type": "bar", + "x": [ "A", "B", "C"], + "y": [ 20, 20, 20 ], + "offsetgroup": 1, + "hovertext": "offsetgroup: 1" + }, + { + "type": "bar", + "x": [ "A", "B", "C"], + "y": [ 30, 30, 30 ], + "offsetgroup": 2, + "hovertext": "offsetgroup: 2" + }, + { + "type": "bar", + "x": [ "A", "B", "C"], + "y": [ 40, 40, 40 ], + "offsetgroup": 2, + "hovertext": "offsetgroup: 2" + }, + { + "type": "bar", + "x": [ "A", "B", "C"], + "y": [ -50, 50, 50 ], + "offsetgroup": 2, + "hovertext": "offsetgroup: 2" + } + ], + "layout": { + "width": 600, + "showlegend": false, + "barmode": "relative", + "title": { + "text": "Separately stacked bars with barmode 'relative'" + } + } + } diff --git a/test/jasmine/tests/bar_test.js b/test/jasmine/tests/bar_test.js index 4ddd88c65e8..fc6c5bb8c80 100644 --- a/test/jasmine/tests/bar_test.js +++ b/test/jasmine/tests/bar_test.js @@ -243,7 +243,7 @@ describe('Bar.supplyDefaults', function() { expect(traceOut.ycalendar).toBe('ethiopian'); }); - it('should not include alignmentgroup/offsetgroup when barmode is not *group*', function() { + it('should include alignmentgroup/offsetgroup regardless of barmode', function() { var gd = { data: [{type: 'bar', y: [1], alignmentgroup: 'a', offsetgroup: '1'}], layout: {barmode: 'group'} @@ -255,8 +255,8 @@ describe('Bar.supplyDefaults', function() { gd.layout.barmode = 'stack'; supplyAllDefaults(gd); - expect(gd._fullData[0].alignmentgroup).toBe(undefined, 'alignementgroup'); - expect(gd._fullData[0].offsetgroup).toBe(undefined, 'offsetgroup'); + expect(gd._fullData[0].alignmentgroup).toBe('a', 'alignementgroup'); + expect(gd._fullData[0].offsetgroup).toBe('1', 'offsetgroup'); }); it('should have a barmode only if it contains bars', function() { diff --git a/test/jasmine/tests/funnel_test.js b/test/jasmine/tests/funnel_test.js index b28642fe560..295eea9478d 100644 --- a/test/jasmine/tests/funnel_test.js +++ b/test/jasmine/tests/funnel_test.js @@ -244,7 +244,7 @@ describe('Funnel.supplyDefaults', function() { expect(traceOut.ycalendar).toBe('ethiopian'); }); - it('should not include alignementgroup/offsetgroup when funnelmode is not *group*', function() { + it('should include alignementgroup/offsetgroup regardless of the funnelmode', function() { var gd = { data: [{type: 'funnel', y: [1], alignmentgroup: 'a', offsetgroup: '1'}], layout: {funnelmode: 'group'} @@ -256,8 +256,8 @@ describe('Funnel.supplyDefaults', function() { gd.layout.funnelmode = 'stack'; supplyAllDefaults(gd); - expect(gd._fullData[0].alignmentgroup).toBe(undefined, 'alignementgroup'); - expect(gd._fullData[0].offsetgroup).toBe(undefined, 'offsetgroup'); + expect(gd._fullData[0].alignmentgroup).toBe('a', 'alignementgroup'); + expect(gd._fullData[0].offsetgroup).toBe('1', 'offsetgroup'); }); });