diff --git a/draftlogs/7571_fix.md b/draftlogs/7571_fix.md new file mode 100644 index 00000000000..c672c3db524 --- /dev/null +++ b/draftlogs/7571_fix.md @@ -0,0 +1 @@ +- Fix `layout.title.subtitle` does not properly clear/remove from the chart when `subtitle` object is not in place, or `subtitle.text` set to `null`, empty string, or whitespace-only values. [[#7571](https://github.com/plotly/plotly.js/pull/7571)] diff --git a/src/components/titles/index.js b/src/components/titles/index.js index 6637343cdad..8a360a5153c 100644 --- a/src/components/titles/index.js +++ b/src/components/titles/index.js @@ -81,7 +81,7 @@ function draw(gd, titleClass, options) { var subtitleEnabled = !!subtitleProp; var subtitlePlaceholder = options.subtitlePlaceholder; var subtitle = (cont.title || {}).subtitle || {text: '', font: {}}; - var subtitleTxt = subtitle.text.trim(); + var subtitleTxt = (subtitle.text || '').trim(); var subtitleIsPlaceholder = false; var subtitleOpacity = 1; @@ -160,7 +160,7 @@ function draw(gd, titleClass, options) { var subtitleClass = titleClass + '-subtitle'; var subtitleElShouldExist = subtitleTxt || editable; - if(subtitleEnabled && subtitleElShouldExist) { + if(subtitleEnabled) { subtitleEl = group.selectAll('text.' + subtitleClass) .data(subtitleElShouldExist ? [0] : []); subtitleEl.enter().append('text'); @@ -231,7 +231,7 @@ function draw(gd, titleClass, options) { .attr(attributes) .call(svgTextUtils.convertToTspans, gd, adjustSubtitlePosition); - if(subtitleEl) { + if(subtitleEl && !subtitleEl.empty()) { // Set subtitle y position based on bottom of title // We need to check the Mathjax group as well, in case the Mathjax // has already rendered @@ -405,7 +405,7 @@ function draw(gd, titleClass, options) { } el.classed('js-placeholder', titleIsPlaceholder); - if(subtitleEl) subtitleEl.classed('js-placeholder', subtitleIsPlaceholder); + if(subtitleEl && !subtitleEl.empty()) subtitleEl.classed('js-placeholder', subtitleIsPlaceholder); return group; } diff --git a/test/jasmine/tests/titles_test.js b/test/jasmine/tests/titles_test.js index 68772a00ffc..9744a517248 100644 --- a/test/jasmine/tests/titles_test.js +++ b/test/jasmine/tests/titles_test.js @@ -1027,6 +1027,98 @@ describe('Title automargining', function() { }); }); +describe("Subtitle clearing via relayout", function () { + "use strict"; + + var data = [{ x: [1, 2, 3], y: [1, 2, 3] }]; + var gd; + + beforeEach(function () { + gd = createGraphDiv(); + }); + + afterEach(destroyGraphDiv); + + it("should properly clear subtitle when set to null", function (done) { + Plotly.newPlot(gd, data, { + title: { + text: "Main Title", + subtitle: { text: "Subtitle Text" }, + }, + }) + .then(function () { + var subtitleSel = d3Select(".gtitle-subtitle"); + expect(subtitleSel.empty()).toBe( + false, + "Subtitle should exist initially" + ); + expect(subtitleSel.text()).toBe("Subtitle Text"); + + return Plotly.relayout(gd, { "title.subtitle.text": null }); + }) + .then(function () { + var subtitleSel = d3Select(".gtitle-subtitle"); + expect(subtitleSel.empty()).toBe( + true, + "Subtitle should be removed when set to null" + ); + }) + .then(done, done.fail); + }); + + it("should properly clear subtitle when set to empty string", function (done) { + Plotly.newPlot(gd, data, { + title: { + text: "Main Title", + subtitle: { text: "Subtitle Text" }, + }, + }) + .then(function () { + var subtitleSel = d3Select(".gtitle-subtitle"); + expect(subtitleSel.empty()).toBe( + false, + "Subtitle should exist initially" + ); + + return Plotly.relayout(gd, { "title.subtitle.text": "" }); + }) + .then(function () { + var subtitleSel = d3Select(".gtitle-subtitle"); + expect(subtitleSel.empty()).toBe( + true, + "Subtitle should be removed when set to empty string" + ); + }) + .then(done, done.fail); + }); + + it("should properly clear subtitle when set to whitespace", function (done) { + Plotly.newPlot(gd, data, { + title: { + text: "Main Title", + subtitle: { text: "Subtitle Text" }, + }, + }) + .then(function () { + var subtitleSel = d3Select(".gtitle-subtitle"); + expect(subtitleSel.empty()).toBe( + false, + "Subtitle should exist initially" + ); + + return Plotly.relayout(gd, { "title.subtitle.text": " " }); + }) + .then(function () { + var subtitleSel = d3Select(".gtitle-subtitle"); + expect(subtitleSel.empty()).toBe( + true, + "Subtitle should be removed when set to whitespace" + ); + }) + .then(done, done.fail); + }); +}); + function expectTitle(expTitle) { expectTitleFn(expTitle)(); }