Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions draftlogs/8167_fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Fix `rangebreaks` when one break overlaps two other breaks, which hid the plot or drew later data over earlier data [[#8167](https://github.com/plotly/plotly.js/pull/8167)]
26 changes: 14 additions & 12 deletions src/plots/cartesian/set_convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -774,22 +774,24 @@ module.exports = function setConvert(ax, fullLayout) {
max = Lib.constrain(max, r0, r1);
if(min === max) return;

var isNewBreak = true;
for(var j = 0; j < rangebreaksOut.length; j++) {
var brkj = rangebreaksOut[j];
let merged;
for(let j = 0; j < rangebreaksOut.length; j++) {
const brkj = rangebreaksOut[j];
if(min < brkj.max && max >= brkj.min) {
if(min < brkj.min) {
brkj.min = min;
}
if(max > brkj.max) {
brkj.max = max;
if(merged) {
// The axis code sums the break lengths, so the located breaks must not overlap.
merged.min = Math.min(merged.min, brkj.min);
merged.max = Math.max(merged.max, brkj.max);
rangebreaksOut.splice(j, 1);
j--;
} else {
merged = brkj;
merged.min = Math.min(merged.min, min);
merged.max = Math.max(merged.max, max);
}
isNewBreak = false;
}
}
if(isNewBreak) {
rangebreaksOut.push({min: min, max: max});
}
if(!merged) rangebreaksOut.push({min, max});
};

for(i = 0; i < rangebreaksIn.length; i++) {
Expand Down
59 changes: 58 additions & 1 deletion test/jasmine/tests/axes_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ var Cartesian = require('../../../src/plots/cartesian');
var Axes = require('../../../src/plots/cartesian/axes');
var Fx = require('../../../src/components/fx');
var supplyLayoutDefaults = require('../../../src/plots/cartesian/layout_defaults');
const {BADNUM, MINUS_SIGN, ONEDAY, ONEWEEK} = require('../../../src/constants/numerical');
const {BADNUM, MINUS_SIGN, ONEDAY, ONEHOUR, ONEWEEK} = require('../../../src/constants/numerical');

var createGraphDiv = require('../assets/create_graph_div');
var destroyGraphDiv = require('../assets/destroy_graph_div');
Expand Down Expand Up @@ -6062,6 +6062,63 @@ describe('Test axes', function() {
})
.then(done, done.fail);
});

it('should merge a holiday rangebreak that overlaps two located breaks', (done) => {
const assertBreaks = (msg, exp) => {
const xa = gd._fullLayout.xaxis;
const brks = xa._rangebreaks.map((brk) => [brk.min, brk.max]);

for(let i = 1; i < brks.length; i++) {
expect(brks[i][0])
.withContext(`${msg} | break ${i} starts before break ${i - 1} ends`)
.not.toBeLessThan(brks[i - 1][1]);
}
expect(brks).withContext(`${msg} | merged break`).toContain(exp.merged.map(Lib.dateTime2ms));
expect(xa._lBreaks).withContext(`${msg} | total break length`).toBe(exp.lBreaks);
expect(xa._m2).withContext(`${msg} | l2p slope`).toBeGreaterThan(0);
};
const layout = (range, rangebreaks) => ({xaxis: {range, rangebreaks}});

// Thanksgiving 2023 is a Thursday. Its break bridges the overnight breaks before and after it.
const thanksgivingRange = ['2023-11-20 09:30', '2023-11-24 13:00'];
const thanksgiving = [
{pattern: 'day of week', bounds: [6, 1]},
{pattern: 'hour', bounds: [16, 9.5]},
{values: ['2023-11-23']}
];
const thanksgivingBreaks = {
merged: ['2023-11-22 16:00', '2023-11-24 09:30'],
lBreaks: 76.5 * ONEHOUR
};

// Christmas 2020 is a Friday. Its break bridges the Thursday overnight break and the weekend break.
const christmasRange = ['2020-12-14 09:00', '2020-12-31 15:00'];
const christmas = [
{pattern: 'hour', bounds: [15, 9]},
{pattern: 'day of week', bounds: [6, 1]},
{values: ['2020-12-25']}
];

Plotly.newPlot(gd, [{x: thanksgivingRange}], layout(thanksgivingRange, thanksgiving))
.then(() => {
assertBreaks('Thanksgiving', thanksgivingBreaks);

const reversed = thanksgiving.slice().reverse();
return Plotly.react(gd, [{x: thanksgivingRange}], layout(thanksgivingRange, reversed));
})
.then(() => {
assertBreaks('Thanksgiving, reversed rangebreaks', thanksgivingBreaks);

return Plotly.react(gd, [{x: christmasRange}], layout(christmasRange, christmas));
})
.then(() => {
assertBreaks('Christmas', {
merged: ['2020-12-24 15:00', '2020-12-28 09:00'],
lBreaks: 336 * ONEHOUR
});
})
.then(done, done.fail);
});
});

describe('during calcTicks', function() {
Expand Down