From 9faea167cd6a92f6b5dd6a8f234a78cf84ad82f8 Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Wed, 25 Mar 2020 15:39:37 -0400 Subject: [PATCH 1/9] unified hover: use hoverlabel.bgcolor or legend.bgcolor or paperbg_color --- src/components/fx/hover.js | 2 +- src/components/fx/hoverlabel_defaults.js | 5 +++ test/jasmine/tests/hover_label_test.js | 49 ++++++++++++++++++++++-- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/components/fx/hover.js b/src/components/fx/hover.js index c30114408d4..eb6b89b5f4b 100644 --- a/src/components/fx/hover.js +++ b/src/components/fx/hover.js @@ -991,7 +991,7 @@ function createHoverText(hoverData, opts, gd) { legend: { title: {text: t0, font: fullLayout.font}, font: fullLayout.font, - bgcolor: fullLayout.paper_bgcolor, + bgcolor: fullLayout.hoverlabel.bgcolor, borderwidth: 1, tracegroupgap: 7, traceorder: fullLayout.legend ? fullLayout.legend.traceorder : undefined, diff --git a/src/components/fx/hoverlabel_defaults.js b/src/components/fx/hoverlabel_defaults.js index 55305b5fb0f..c2839232ca1 100644 --- a/src/components/fx/hoverlabel_defaults.js +++ b/src/components/fx/hoverlabel_defaults.js @@ -9,10 +9,15 @@ 'use strict'; var Lib = require('../../lib'); +var isUnifiedHover = require('./helpers').isUnifiedHover; module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts) { opts = opts || {}; + if(contIn && isUnifiedHover(contIn.hovermode)) { + opts.bgcolor = contIn.legend ? contIn.legend.bgcolor : contIn.paper_bgcolor; + } + coerce('hoverlabel.bgcolor', opts.bgcolor); coerce('hoverlabel.bordercolor', opts.bordercolor); coerce('hoverlabel.namelength', opts.namelength); diff --git a/test/jasmine/tests/hover_label_test.js b/test/jasmine/tests/hover_label_test.js index 342301787d9..f22ae9c397f 100644 --- a/test/jasmine/tests/hover_label_test.js +++ b/test/jasmine/tests/hover_label_test.js @@ -4316,15 +4316,56 @@ describe('hovermode: (x|y)unified', function() { .then(done); }); - it('label should have color of paper_bgcolor', function(done) { + it('label should have color of hoverlabel.bgcolor or legend.bgcolor or paper_bgcolor', function(done) { var mockCopy = Lib.extendDeep({}, mock); - var bgcolor = 'rgb(15, 200, 85)'; - mockCopy.layout.paper_bgcolor = bgcolor; + var bgcolor = [ + 'rgb(10, 10, 10)', + 'rgb(20, 20, 20)', + 'rgb(30, 30, 30)', + 'rgb(40, 40, 40)' + ]; + + // Set paper_bgcolor + mockCopy.layout.paper_bgcolor = bgcolor[0]; Plotly.newPlot(gd, mockCopy) .then(function(gd) { _hover(gd, { xval: 3 }); - assertBgcolor(bgcolor); + assertBgcolor(bgcolor[0]); + + // Set legend.bgcolor which should win over paper_bgcolor + return Plotly.relayout(gd, { + 'showlegend': true, + 'legend.bgcolor': bgcolor[1] + }); + }) + .then(function(gd) { + _hover(gd, { xval: 3 }); + + assertBgcolor(bgcolor[1]); + + // Set hoverlabel.bgcolor which should win over legend.bgcolor + return Plotly.relayout(gd, 'hoverlabel.bgcolor', bgcolor[2]); + }) + .then(function(gd) { + _hover(gd, { xval: 3 }); + + assertBgcolor(bgcolor[2]); + + // Finally, check that a hoverlabel.bgcolor defined in template wins + delete mockCopy.layout; + mockCopy.layout = { + hovermode: 'x unified', + template: { layout: { hoverlabel: { bgcolor: bgcolor[3] } } }, + legend: { bgcolor: bgcolor[1] } + }; + + return Plotly.newPlot(gd, mockCopy); + }) + .then(function(gd) { + _hover(gd, { xval: 3 }); + + assertBgcolor(bgcolor[3]); }) .catch(failTest) .then(done); From 576ac600a834ecbd5dca1196e5ce9bbe259247f4 Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Wed, 25 Mar 2020 16:57:10 -0400 Subject: [PATCH 2/9] unified hover: honor hoverlabel.font, then legend.font, then layout.font --- src/components/fx/hover.js | 4 +- src/components/fx/hoverlabel_defaults.js | 4 +- test/jasmine/tests/hover_label_test.js | 80 ++++++++++++++++++++++-- 3 files changed, 79 insertions(+), 9 deletions(-) diff --git a/src/components/fx/hover.js b/src/components/fx/hover.js index eb6b89b5f4b..75d2dba8c1b 100644 --- a/src/components/fx/hover.js +++ b/src/components/fx/hover.js @@ -989,8 +989,8 @@ function createHoverText(hoverData, opts, gd) { var mockLayoutIn = { showlegend: true, legend: { - title: {text: t0, font: fullLayout.font}, - font: fullLayout.font, + title: {text: t0, font: fullLayout.hoverlabel.font}, + font: fullLayout.hoverlabel.font, bgcolor: fullLayout.hoverlabel.bgcolor, borderwidth: 1, tracegroupgap: 7, diff --git a/src/components/fx/hoverlabel_defaults.js b/src/components/fx/hoverlabel_defaults.js index c2839232ca1..46fe0a420db 100644 --- a/src/components/fx/hoverlabel_defaults.js +++ b/src/components/fx/hoverlabel_defaults.js @@ -15,7 +15,9 @@ module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts opts = opts || {}; if(contIn && isUnifiedHover(contIn.hovermode)) { - opts.bgcolor = contIn.legend ? contIn.legend.bgcolor : contIn.paper_bgcolor; + if(!opts.bgcolor) opts.bgcolor = contIn.legend ? contIn.legend.bgcolor : contIn.paper_bgcolor; + // Merge in decreasing order of importance layout.font, layout.legend.font and hoverlabel.font + opts.font = Lib.extendFlat({}, contIn.font, contIn.legend ? contIn.legend.font : {}, opts.font); } coerce('hoverlabel.bgcolor', opts.bgcolor); diff --git a/test/jasmine/tests/hover_label_test.js b/test/jasmine/tests/hover_label_test.js index f22ae9c397f..e7bcabba0b3 100644 --- a/test/jasmine/tests/hover_label_test.js +++ b/test/jasmine/tests/hover_label_test.js @@ -3988,14 +3988,18 @@ describe('hovermode: (x|y)unified', function() { Lib.clearThrottle(); } + function getHoverLabel() { + var hoverLayer = d3.select('g.hoverlayer'); + return hoverLayer.select('g.legend'); + } + function assertElementCount(selector, size) { var g = d3.selectAll(selector); expect(g.size()).toBe(size); } function assertLabel(expectation) { - var hoverLayer = d3.select('g.hoverlayer'); - var hover = hoverLayer.select('g.legend'); + var hover = getHoverLabel(); var title = hover.select('text.legendtitletext'); var traces = hover.selectAll('g.traces'); @@ -4011,15 +4015,13 @@ describe('hovermode: (x|y)unified', function() { } function assertBgcolor(color) { - var hoverLayer = d3.select('g.hoverlayer'); - var hover = hoverLayer.select('g.legend'); + var hover = getHoverLabel(); var bg = hover.select('rect.bg'); expect(bg.node().style.fill).toBe(color); } function assertSymbol(exp) { - var hoverLayer = d3.select('g.hoverlayer'); - var hover = hoverLayer.select('g.legend'); + var hover = getHoverLabel(); var traces = hover.selectAll('g.traces'); expect(traces.size()).toBe(exp.length); @@ -4034,6 +4036,17 @@ describe('hovermode: (x|y)unified', function() { }); } + function assertFont(fontFamily, fontSize, fontColor) { + var hover = getHoverLabel(); + var text = hover.select('text.legendtext'); + var node = text.node(); + + var textStyle = window.getComputedStyle(node); + expect(textStyle.fontFamily.split(',')[0]).toBe(fontFamily, 'wrong font family'); + expect(textStyle.fontSize).toBe(fontSize, 'wrong font size'); + expect(textStyle.fill).toBe(fontColor, 'wrong font color'); + } + it('set smart defaults for spikeline in x unified', function(done) { Plotly.newPlot(gd, [{y: [4, 6, 5]}], {'hovermode': 'x unified', 'xaxis': {'color': 'red'}}) .then(function(gd) { @@ -4371,6 +4384,61 @@ describe('hovermode: (x|y)unified', function() { .then(done); }); + it('should use hoverlabel.font or legend.font or layout.font', function(done) { + var mockCopy = Lib.extendDeep({}, mock); + + // Set layout.font + mockCopy.layout.font = {size: 20, family: 'Mono', color: 'rgb(10, 10, 10)'}; + Plotly.newPlot(gd, mockCopy) + .then(function(gd) { + _hover(gd, { xval: 3}); + + assertFont('Mono', '20px', 'rgb(10, 10, 10)'); + + // Set legend.font which should win over layout font + return Plotly.relayout(gd, { + 'showlegend': true, + 'legend.font.size': 15, + 'legend.font.family': 'Helvetica', + 'legend.font.color': 'rgb(20, 20, 20)' + }); + }) + .then(function(gd) { + _hover(gd, { xval: 3 }); + + assertFont('Helvetica', '15px', 'rgb(20, 20, 20)'); + + // Set hoverlabel.font which should win over legend.font + return Plotly.relayout(gd, { + 'hoverlabel.font.size': 22, + 'hoverlabel.font.family': 'Arial', + 'hoverlabel.font.color': 'rgb(30, 30, 30)' + }); + }) + .then(function() { + _hover(gd, { xval: 3 }); + + assertFont('Arial', '22px', 'rgb(30, 30, 30)'); + + // Finally, check that a hoverlabel.font defined in template wins + delete mockCopy.layout; + mockCopy.layout = { + hovermode: 'x unified', + template: { layout: { hoverlabel: { font: {family: 'Mono', size: 30, color: 'red'}}}}, + legend: {font: {size: 20, family: 'Mono', color: 'rgb(10, 10, 10)'}} + }; + + return Plotly.newPlot(gd, mockCopy); + }) + .then(function() { + _hover(gd, { xval: 3 }); + + assertFont('Mono', '30px', 'rgb(255, 0, 0)'); + }) + .catch(failTest) + .then(done); + }); + it('should work with hovertemplate', function(done) { var mockCopy = Lib.extendDeep({}, mock); mockCopy.data[0].hovertemplate = 'hovertemplate: %{y:0.2f}'; From 76a04885fd127d86b5ad54dc2db642fbb18c77e5 Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Wed, 25 Mar 2020 18:06:24 -0400 Subject: [PATCH 3/9] unified hover: fix for unspecified layout.paperbg_color --- src/components/fx/hover.js | 2 +- src/components/fx/hoverlabel_defaults.js | 3 ++- test/jasmine/tests/hover_label_test.js | 10 ++++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/components/fx/hover.js b/src/components/fx/hover.js index 75d2dba8c1b..a727c528ba7 100644 --- a/src/components/fx/hover.js +++ b/src/components/fx/hover.js @@ -991,7 +991,7 @@ function createHoverText(hoverData, opts, gd) { legend: { title: {text: t0, font: fullLayout.hoverlabel.font}, font: fullLayout.hoverlabel.font, - bgcolor: fullLayout.hoverlabel.bgcolor, + bgcolor: fullLayout.hoverlabel.bgcolor || fullLayout.paper_bgcolor, borderwidth: 1, tracegroupgap: 7, traceorder: fullLayout.legend ? fullLayout.legend.traceorder : undefined, diff --git a/src/components/fx/hoverlabel_defaults.js b/src/components/fx/hoverlabel_defaults.js index 46fe0a420db..5989b6e9a7c 100644 --- a/src/components/fx/hoverlabel_defaults.js +++ b/src/components/fx/hoverlabel_defaults.js @@ -14,8 +14,9 @@ var isUnifiedHover = require('./helpers').isUnifiedHover; module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts) { opts = opts || {}; + // In unified hover, inherit from legend if available if(contIn && isUnifiedHover(contIn.hovermode)) { - if(!opts.bgcolor) opts.bgcolor = contIn.legend ? contIn.legend.bgcolor : contIn.paper_bgcolor; + if(!opts.bgcolor && contIn.legend) opts.bgcolor = contIn.legend.bgcolor; // Merge in decreasing order of importance layout.font, layout.legend.font and hoverlabel.font opts.font = Lib.extendFlat({}, contIn.font, contIn.legend ? contIn.legend.font : {}, opts.font); } diff --git a/test/jasmine/tests/hover_label_test.js b/test/jasmine/tests/hover_label_test.js index e7bcabba0b3..04492a07f59 100644 --- a/test/jasmine/tests/hover_label_test.js +++ b/test/jasmine/tests/hover_label_test.js @@ -4338,9 +4338,15 @@ describe('hovermode: (x|y)unified', function() { 'rgb(40, 40, 40)' ]; - // Set paper_bgcolor - mockCopy.layout.paper_bgcolor = bgcolor[0]; Plotly.newPlot(gd, mockCopy) + .then(function(gd) { + _hover(gd, { xval: 3 }); + + assertBgcolor('rgb(255, 255, 255)'); + + // Set paper_bgcolor + return Plotly.relayout(gd, 'paper_bgcolor', bgcolor[0]); + }) .then(function(gd) { _hover(gd, { xval: 3 }); From 531fe79de9f74bdc4394a38d2fc4b07d807657bf Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Wed, 25 Mar 2020 18:21:38 -0400 Subject: [PATCH 4/9] unified hover: honor hoverlabel.bordercolor, then legend.bordercolor --- src/components/fx/hover.js | 1 + src/components/fx/hoverlabel_defaults.js | 1 + test/jasmine/tests/hover_label_test.js | 29 ++++++++++++++---------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/components/fx/hover.js b/src/components/fx/hover.js index a727c528ba7..e17139f3da8 100644 --- a/src/components/fx/hover.js +++ b/src/components/fx/hover.js @@ -992,6 +992,7 @@ function createHoverText(hoverData, opts, gd) { title: {text: t0, font: fullLayout.hoverlabel.font}, font: fullLayout.hoverlabel.font, bgcolor: fullLayout.hoverlabel.bgcolor || fullLayout.paper_bgcolor, + bordercolor: fullLayout.hoverlabel.bordercolor, borderwidth: 1, tracegroupgap: 7, traceorder: fullLayout.legend ? fullLayout.legend.traceorder : undefined, diff --git a/src/components/fx/hoverlabel_defaults.js b/src/components/fx/hoverlabel_defaults.js index 5989b6e9a7c..8069c4ca8a2 100644 --- a/src/components/fx/hoverlabel_defaults.js +++ b/src/components/fx/hoverlabel_defaults.js @@ -17,6 +17,7 @@ module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts // In unified hover, inherit from legend if available if(contIn && isUnifiedHover(contIn.hovermode)) { if(!opts.bgcolor && contIn.legend) opts.bgcolor = contIn.legend.bgcolor; + if(!opts.bordercolor && contIn.legend) opts.bordercolor = contIn.legend.bordercolor; // Merge in decreasing order of importance layout.font, layout.legend.font and hoverlabel.font opts.font = Lib.extendFlat({}, contIn.font, contIn.legend ? contIn.legend.font : {}, opts.font); } diff --git a/test/jasmine/tests/hover_label_test.js b/test/jasmine/tests/hover_label_test.js index 04492a07f59..1af114c8fb7 100644 --- a/test/jasmine/tests/hover_label_test.js +++ b/test/jasmine/tests/hover_label_test.js @@ -4014,10 +4014,11 @@ describe('hovermode: (x|y)unified', function() { }); } - function assertBgcolor(color) { + function assertRectColor(color, bordercolor) { var hover = getHoverLabel(); var bg = hover.select('rect.bg'); - expect(bg.node().style.fill).toBe(color); + if(color) expect(bg.node().style.fill).toBe(color); + if(bordercolor) expect(bg.node().style.stroke).toBe(bordercolor); } function assertSymbol(exp) { @@ -4329,7 +4330,7 @@ describe('hovermode: (x|y)unified', function() { .then(done); }); - it('label should have color of hoverlabel.bgcolor or legend.bgcolor or paper_bgcolor', function(done) { + it('label should have bgcolor/bordercolor from hoverlabel or legend or paper_bgcolor', function(done) { var mockCopy = Lib.extendDeep({}, mock); var bgcolor = [ 'rgb(10, 10, 10)', @@ -4342,7 +4343,7 @@ describe('hovermode: (x|y)unified', function() { .then(function(gd) { _hover(gd, { xval: 3 }); - assertBgcolor('rgb(255, 255, 255)'); + assertRectColor('rgb(255, 255, 255)', 'rgb(68, 68, 68)'); // Set paper_bgcolor return Plotly.relayout(gd, 'paper_bgcolor', bgcolor[0]); @@ -4350,33 +4351,37 @@ describe('hovermode: (x|y)unified', function() { .then(function(gd) { _hover(gd, { xval: 3 }); - assertBgcolor(bgcolor[0]); + assertRectColor(bgcolor[0]); // Set legend.bgcolor which should win over paper_bgcolor return Plotly.relayout(gd, { 'showlegend': true, - 'legend.bgcolor': bgcolor[1] + 'legend.bgcolor': bgcolor[1], + 'legend.bordercolor': bgcolor[1] }); }) .then(function(gd) { _hover(gd, { xval: 3 }); - assertBgcolor(bgcolor[1]); + assertRectColor(bgcolor[1], bgcolor[1]); // Set hoverlabel.bgcolor which should win over legend.bgcolor - return Plotly.relayout(gd, 'hoverlabel.bgcolor', bgcolor[2]); + return Plotly.relayout(gd, { + 'hoverlabel.bgcolor': bgcolor[2], + 'hoverlabel.bordercolor': bgcolor[2] + }); }) .then(function(gd) { _hover(gd, { xval: 3 }); - assertBgcolor(bgcolor[2]); + assertRectColor(bgcolor[2], bgcolor[2]); // Finally, check that a hoverlabel.bgcolor defined in template wins delete mockCopy.layout; mockCopy.layout = { hovermode: 'x unified', - template: { layout: { hoverlabel: { bgcolor: bgcolor[3] } } }, - legend: { bgcolor: bgcolor[1] } + template: { layout: { hoverlabel: { bgcolor: bgcolor[3], bordercolor: bgcolor[3] } } }, + legend: { bgcolor: bgcolor[1], bordercolor: bgcolor[1] } }; return Plotly.newPlot(gd, mockCopy); @@ -4384,7 +4389,7 @@ describe('hovermode: (x|y)unified', function() { .then(function(gd) { _hover(gd, { xval: 3 }); - assertBgcolor(bgcolor[3]); + assertRectColor(bgcolor[3], bgcolor[3]); }) .catch(failTest) .then(done); From 4ef8205120ced0858f0f2e7b2afc9a2347975f1d Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Wed, 25 Mar 2020 18:27:19 -0400 Subject: [PATCH 5/9] unified hover: remove extendFlat to handle falsy value for hoverlabel --- src/components/fx/hoverlabel_defaults.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/fx/hoverlabel_defaults.js b/src/components/fx/hoverlabel_defaults.js index 8069c4ca8a2..dd57605f145 100644 --- a/src/components/fx/hoverlabel_defaults.js +++ b/src/components/fx/hoverlabel_defaults.js @@ -19,7 +19,12 @@ module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts if(!opts.bgcolor && contIn.legend) opts.bgcolor = contIn.legend.bgcolor; if(!opts.bordercolor && contIn.legend) opts.bordercolor = contIn.legend.bordercolor; // Merge in decreasing order of importance layout.font, layout.legend.font and hoverlabel.font - opts.font = Lib.extendFlat({}, contIn.font, contIn.legend ? contIn.legend.font : {}, opts.font); + + var l = contIn.legend; + if(!opts.font) opts.font = {}; + if(!opts.font.size) opts.font.size = l && l.size ? l.size : contIn.font.size; + if(!opts.font.family) opts.font.family = l && l.family ? l.family : contIn.font.family; + if(!opts.font.color) opts.font.color = l && l.color ? l.color : contIn.font.color; } coerce('hoverlabel.bgcolor', opts.bgcolor); From 6483ac908864a5b749656d4d5dec2d82726ca965 Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Wed, 25 Mar 2020 18:41:49 -0400 Subject: [PATCH 6/9] unified hover: fix inheritance of font attributes --- src/components/fx/hoverlabel_defaults.js | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/components/fx/hoverlabel_defaults.js b/src/components/fx/hoverlabel_defaults.js index dd57605f145..ad692eac646 100644 --- a/src/components/fx/hoverlabel_defaults.js +++ b/src/components/fx/hoverlabel_defaults.js @@ -14,17 +14,25 @@ var isUnifiedHover = require('./helpers').isUnifiedHover; module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts) { opts = opts || {}; + function inheritFontAttr(attr) { + if(!opts.font[attr]) { + if(contIn.legend && contIn.legend.font && contIn.legend.font[attr]) { + opts.font[attr] = contIn.legend.font[attr]; + } else if(contIn.font && contIn.font[attr]) { + opts.font[attr] = contIn.font[attr]; + } + } + } + // In unified hover, inherit from legend if available if(contIn && isUnifiedHover(contIn.hovermode)) { - if(!opts.bgcolor && contIn.legend) opts.bgcolor = contIn.legend.bgcolor; - if(!opts.bordercolor && contIn.legend) opts.bordercolor = contIn.legend.bordercolor; - // Merge in decreasing order of importance layout.font, layout.legend.font and hoverlabel.font - - var l = contIn.legend; if(!opts.font) opts.font = {}; - if(!opts.font.size) opts.font.size = l && l.size ? l.size : contIn.font.size; - if(!opts.font.family) opts.font.family = l && l.family ? l.family : contIn.font.family; - if(!opts.font.color) opts.font.color = l && l.color ? l.color : contIn.font.color; + inheritFontAttr('size'); + inheritFontAttr('family'); + inheritFontAttr('color'); + + if(!opts.bgcolor && contIn.legend && contIn.legend.bgcolor) opts.bgcolor = contIn.legend.bgcolor; + if(!opts.bordercolor && contIn.legend && contIn.legend.bordercolor) opts.bordercolor = contIn.legend.bordercolor; } coerce('hoverlabel.bgcolor', opts.bgcolor); From dfd73b86ab1ebcf8448245583035396a43c71b07 Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Thu, 26 Mar 2020 12:45:01 -0400 Subject: [PATCH 7/9] set Fx defaults after legend defaults so unified hover label can inherit --- src/components/fx/hover.js | 2 +- src/components/fx/hoverlabel_defaults.js | 18 +++++++------- src/components/fx/layout_defaults.js | 3 +++ src/core.js | 2 +- test/jasmine/tests/hover_label_test.js | 30 +++++++++++++++++++++++- 5 files changed, 43 insertions(+), 12 deletions(-) diff --git a/src/components/fx/hover.js b/src/components/fx/hover.js index e17139f3da8..45617636789 100644 --- a/src/components/fx/hover.js +++ b/src/components/fx/hover.js @@ -991,7 +991,7 @@ function createHoverText(hoverData, opts, gd) { legend: { title: {text: t0, font: fullLayout.hoverlabel.font}, font: fullLayout.hoverlabel.font, - bgcolor: fullLayout.hoverlabel.bgcolor || fullLayout.paper_bgcolor, + bgcolor: fullLayout.hoverlabel.bgcolor, bordercolor: fullLayout.hoverlabel.bordercolor, borderwidth: 1, tracegroupgap: 7, diff --git a/src/components/fx/hoverlabel_defaults.js b/src/components/fx/hoverlabel_defaults.js index ad692eac646..59a80378bba 100644 --- a/src/components/fx/hoverlabel_defaults.js +++ b/src/components/fx/hoverlabel_defaults.js @@ -16,23 +16,23 @@ module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts function inheritFontAttr(attr) { if(!opts.font[attr]) { - if(contIn.legend && contIn.legend.font && contIn.legend.font[attr]) { - opts.font[attr] = contIn.legend.font[attr]; - } else if(contIn.font && contIn.font[attr]) { - opts.font[attr] = contIn.font[attr]; - } + opts.font[attr] = contOut.legend ? contOut.legend.font[attr] : contOut.font[attr]; } } - // In unified hover, inherit from legend if available - if(contIn && isUnifiedHover(contIn.hovermode)) { + // In unified hover, inherit from layout.legend if available or layout + if(contOut && isUnifiedHover(contOut.hovermode)) { if(!opts.font) opts.font = {}; inheritFontAttr('size'); inheritFontAttr('family'); inheritFontAttr('color'); - if(!opts.bgcolor && contIn.legend && contIn.legend.bgcolor) opts.bgcolor = contIn.legend.bgcolor; - if(!opts.bordercolor && contIn.legend && contIn.legend.bordercolor) opts.bordercolor = contIn.legend.bordercolor; + if(contOut.legend) { + if(!opts.bgcolor) opts.bgcolor = contOut.legend.bgcolor; + if(!opts.bordercolor) opts.bordercolor = contOut.legend.bordercolor; + } else { + if(!opts.bgcolor) opts.bgcolor = contOut.paper_bgcolor; + } } coerce('hoverlabel.bgcolor', opts.bgcolor); diff --git a/src/components/fx/layout_defaults.js b/src/components/fx/layout_defaults.js index 80755253736..15d6a7f11f6 100644 --- a/src/components/fx/layout_defaults.js +++ b/src/components/fx/layout_defaults.js @@ -12,6 +12,7 @@ var Lib = require('../../lib'); var isUnifiedHover = require('./helpers').isUnifiedHover; var layoutAttributes = require('./layout_attributes'); var handleHoverModeDefaults = require('./hovermode_defaults'); +var handleHoverLabelDefaults = require('./hoverlabel_defaults'); module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { function coerce(attr, dflt) { @@ -40,4 +41,6 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { )) { layoutOut.dragmode = 'pan'; } + + handleHoverLabelDefaults(layoutIn, layoutOut, coerce); }; diff --git a/src/core.js b/src/core.js index eb45036dbd0..2e67fa8dd4d 100644 --- a/src/core.js +++ b/src/core.js @@ -42,8 +42,8 @@ register(require('./traces/scatter')); // register all registrable components modules register([ - require('./components/fx'), require('./components/legend'), + require('./components/fx'), require('./components/annotations'), require('./components/annotations3d'), require('./components/shapes'), diff --git a/test/jasmine/tests/hover_label_test.js b/test/jasmine/tests/hover_label_test.js index 1af114c8fb7..b599afb25b0 100644 --- a/test/jasmine/tests/hover_label_test.js +++ b/test/jasmine/tests/hover_label_test.js @@ -4376,7 +4376,21 @@ describe('hovermode: (x|y)unified', function() { assertRectColor(bgcolor[2], bgcolor[2]); - // Finally, check that a hoverlabel.bgcolor defined in template wins + // Check that a legend.bgcolor defined in template works + delete mockCopy.layout; + mockCopy.layout = { + hovermode: 'x unified', + template: { layout: { legend: { bgcolor: bgcolor[1], bordercolor: bgcolor[1] } } } + }; + + return Plotly.newPlot(gd, mockCopy); + }) + .then(function(gd) { + _hover(gd, { xval: 3 }); + + assertRectColor(bgcolor[1], bgcolor[1]); + + // Check that a hoverlabel.bgcolor defined in template wins delete mockCopy.layout; mockCopy.layout = { hovermode: 'x unified', @@ -4431,6 +4445,20 @@ describe('hovermode: (x|y)unified', function() { assertFont('Arial', '22px', 'rgb(30, 30, 30)'); + // Check that a legend.font defined in template wins + delete mockCopy.layout; + mockCopy.layout = { + hovermode: 'x unified', + template: { layout: { legend: {font: {size: 5, family: 'Mono', color: 'rgb(5, 5, 5)'}}}}, + }; + + return Plotly.newPlot(gd, mockCopy); + }) + .then(function() { + _hover(gd, { xval: 3 }); + + assertFont('Mono', '5px', 'rgb(5, 5, 5)'); + // Finally, check that a hoverlabel.font defined in template wins delete mockCopy.layout; mockCopy.layout = { From cc8ca1c3071565a5ad2b3fda1907ebd170b1419b Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Thu, 26 Mar 2020 13:41:42 -0400 Subject: [PATCH 8/9] default unified hoverlabel.bgcolor combines legend.bgcolor and paper_bgcolor --- src/components/fx/hoverlabel_defaults.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/fx/hoverlabel_defaults.js b/src/components/fx/hoverlabel_defaults.js index 59a80378bba..22f80c5fced 100644 --- a/src/components/fx/hoverlabel_defaults.js +++ b/src/components/fx/hoverlabel_defaults.js @@ -9,6 +9,7 @@ 'use strict'; var Lib = require('../../lib'); +var Color = require('../color'); var isUnifiedHover = require('./helpers').isUnifiedHover; module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts) { @@ -28,7 +29,7 @@ module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts inheritFontAttr('color'); if(contOut.legend) { - if(!opts.bgcolor) opts.bgcolor = contOut.legend.bgcolor; + if(!opts.bgcolor) opts.bgcolor = Color.combine(contOut.legend.bgcolor, contOut.paper_bgcolor); if(!opts.bordercolor) opts.bordercolor = contOut.legend.bordercolor; } else { if(!opts.bgcolor) opts.bgcolor = contOut.paper_bgcolor; From 0d406a02fd927cbba70cd3b9a5be58b265cae3cc Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Thu, 26 Mar 2020 15:32:40 -0400 Subject: [PATCH 9/9] add comment stating that fx defaults should be set after legend defaults --- src/core.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core.js b/src/core.js index 2e67fa8dd4d..47bb61ee918 100644 --- a/src/core.js +++ b/src/core.js @@ -43,7 +43,7 @@ register(require('./traces/scatter')); // register all registrable components modules register([ require('./components/legend'), - require('./components/fx'), + require('./components/fx'), // fx needs to come after legend require('./components/annotations'), require('./components/annotations3d'), require('./components/shapes'),