diff --git a/src/traces/bar/cross_trace_calc.js b/src/traces/bar/cross_trace_calc.js index 3762c4f341d..a50a4d41228 100644 --- a/src/traces/bar/cross_trace_calc.js +++ b/src/traces/bar/cross_trace_calc.js @@ -47,6 +47,14 @@ function crossTraceCalc(gd, plotinfo) { } else { calcTracesVert.push(calcTraces[i]); } + + if(fullTrace._computePh) { + var cd = gd.calcdata[i]; + for(var j = 0; j < cd.length; j++) { + if(typeof cd[j].ph0 === 'function') cd[j].ph0 = cd[j].ph0(); + if(typeof cd[j].ph1 === 'function') cd[j].ph1 = cd[j].ph1(); + } + } } } diff --git a/src/traces/histogram/calc.js b/src/traces/histogram/calc.js index a1c450d76c7..540813836aa 100644 --- a/src/traces/histogram/calc.js +++ b/src/traces/histogram/calc.js @@ -102,12 +102,21 @@ function calc(gd, trace) { }; } + // stash left and right gaps by group + if(!gd._fullLayout._roundFnOpts) gd._fullLayout._roundFnOpts = {}; + var groupName = trace['_' + mainData + 'bingroup']; + var roundFnOpts = {leftGap: Infinity, rightGap: Infinity}; + if(groupName) { + if(!gd._fullLayout._roundFnOpts[groupName]) gd._fullLayout._roundFnOpts[groupName] = roundFnOpts; + roundFnOpts = gd._fullLayout._roundFnOpts[groupName]; + } + // bin the data // and make histogram-specific pt-number-to-cd-index map object var nMax = size.length; var uniqueValsPerBin = true; - var leftGap = Infinity; - var rightGap = Infinity; + var leftGap = roundFnOpts.leftGap; + var rightGap = roundFnOpts.rightGap; var ptNumber2cdIndex = {}; for(i = 0; i < pos0.length; i++) { var posi = pos0[i]; @@ -124,10 +133,21 @@ function calc(gd, trace) { rightGap = Math.min(rightGap, binEdges[n + 1] - posi); } } + roundFnOpts.leftGap = leftGap; + roundFnOpts.rightGap = rightGap; var roundFn; if(!uniqueValsPerBin) { - roundFn = getBinSpanLabelRound(leftGap, rightGap, binEdges, pa, calendar); + roundFn = function(v, isRightEdge) { + return function() { + var roundFnOpts = gd._fullLayout._roundFnOpts[groupName]; + return getBinSpanLabelRound( + roundFnOpts.leftGap, + roundFnOpts.rightGap, + binEdges, pa, calendar + )(v, isRightEdge); + }; + }; } // average and/or normalize the data, if needed @@ -173,6 +193,8 @@ function calc(gd, trace) { if(uniqueValsPerBin) { cdi.ph0 = cdi.ph1 = (inputPoints[i].length) ? pos0[inputPoints[i][0]] : pos[i]; } else { + // Defer evaluation of ph(0|1) in crossTraceCalc + trace._computePh = true; cdi.ph0 = roundFn(binEdges[i]); cdi.ph1 = roundFn(binEdges[i + 1], true); } diff --git a/test/jasmine/tests/histogram_test.js b/test/jasmine/tests/histogram_test.js index df31aa0a304..064cac6678a 100644 --- a/test/jasmine/tests/histogram_test.js +++ b/test/jasmine/tests/histogram_test.js @@ -585,6 +585,7 @@ describe('Test histogram', function() { // even though -0 === 0 out.forEach(function(cdi) { for(var key in cdi) { + if(typeof cdi[key] === 'function') cdi[key] = cdi[key](); if(cdi[key] === 0) cdi[key] = 0; } }); @@ -861,6 +862,23 @@ describe('Test histogram', function() { expect(calcPositions(trace2, [trace1])).toEqual([5, 7]); }); + it('harmonizes start/end value of bins when all traces are autobinned', function(done) { + var mock = require('@mocks/histogram_overlay-bingroup'); + var gd = createGraphDiv(); + Plotly.newPlot(gd, mock) + .then(function(gd) { + destroyGraphDiv(); + var cd0 = gd.calcdata[0]; + var cd1 = gd.calcdata[1]; + for(var i = 0; i < cd0.length && i < cd1.length; i++) { + expect(cd0[i].ph0).toBe(cd1[i].ph0); + expect(cd0[i].ph1).toBe(cd1[i].ph1); + } + }) + .catch(failTest) + .then(done); + }); + it('autobins all data as one', function() { // all integers, so all autobins should get shifted to start 0.5 lower // than they otherwise would.