Skip to content

Commit 6cd54ae

Browse files
committed
add hoverlabel.align
- with values 'left', 'right' and 'auto' (the dflt and current behavior)
1 parent f20ef2c commit 6cd54ae

File tree

7 files changed

+87
-11
lines changed

7 files changed

+87
-11
lines changed

src/components/fx/attributes.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
var fontAttrs = require('../../plots/font_attributes');
1212
var hoverLabelAttrs = require('./layout_attributes').hoverlabel;
13-
var extendFlat = require('../../extend').extendFlat;
13+
var extendFlat = require('../../lib/extend').extendFlat;
1414

1515
module.exports = {
1616
hoverlabel: {
@@ -27,6 +27,7 @@ module.exports = {
2727
editType: 'none',
2828
description: 'Sets the font used in hover labels.'
2929
}),
30+
align: extendFlat({}, hoverLabelAttrs.align, {arrayOk: true}),
3031
namelength: extendFlat({}, hoverLabelAttrs.namelength, {arrayOk: true}),
3132
editType: 'none'
3233
}

src/components/fx/calc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ module.exports = function calc(gd) {
4444
fillFn(trace.hoverlabel.font.color, cd, 'htc');
4545
fillFn(trace.hoverlabel.font.family, cd, 'htf');
4646
fillFn(trace.hoverlabel.namelength, cd, 'hnl');
47+
fillFn(trace.hoverlabel.align, cd, 'hta');
4748
}
4849
};
4950

src/components/fx/hover.js

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,20 +1281,18 @@ function alignHoverText(hoverLabels, rotateLabels) {
12811281
// box around it
12821282
hoverLabels.each(function(d) {
12831283
var g = d3.select(this);
1284-
if(d.del) {
1285-
g.remove();
1286-
return;
1287-
}
1284+
if(d.del) return g.remove();
12881285

1289-
var horzSign = d.anchor === 'end' ? -1 : 1;
12901286
var tx = g.select('text.nums');
1291-
var alignShift = {start: 1, end: -1, middle: 0}[d.anchor];
1287+
var anchor = d.anchor;
1288+
var horzSign = anchor === 'end' ? -1 : 1;
1289+
var alignShift = {start: 1, end: -1, middle: 0}[anchor];
12921290
var txx = alignShift * (HOVERARROWSIZE + HOVERTEXTPAD);
12931291
var tx2x = txx + alignShift * (d.txwidth + HOVERTEXTPAD);
12941292
var offsetX = 0;
12951293
var offsetY = d.offset;
12961294

1297-
if(d.anchor === 'middle') {
1295+
if(anchor === 'middle') {
12981296
txx -= d.tx2width / 2;
12991297
tx2x += d.txwidth / 2 + HOVERTEXTPAD;
13001298
}
@@ -1303,7 +1301,7 @@ function alignHoverText(hoverLabels, rotateLabels) {
13031301
offsetX = d.offset * YSHIFTX;
13041302
}
13051303

1306-
g.select('path').attr('d', d.anchor === 'middle' ?
1304+
g.select('path').attr('d', anchor === 'middle' ?
13071305
// middle aligned: rect centered on data
13081306
('M-' + (d.bx / 2 + d.tx2width / 2) + ',' + (offsetY - d.by / 2) +
13091307
'h' + d.bx + 'v' + d.by + 'h-' + d.bx + 'Z') :
@@ -1316,8 +1314,21 @@ function alignHoverText(hoverLabels, rotateLabels) {
13161314
'V' + (offsetY - HOVERARROWSIZE) +
13171315
'Z'));
13181316

1319-
tx.call(svgTextUtils.positionText,
1320-
txx + offsetX, offsetY + d.ty0 - d.by / 2 + HOVERTEXTPAD);
1317+
var posX = txx + offsetX;
1318+
var posY = offsetY + d.ty0 - d.by / 2 + HOVERTEXTPAD;
1319+
var textAlign = d.textAlign || 'auto';
1320+
1321+
if(textAlign !== 'auto') {
1322+
if(textAlign === 'left' && anchor !== 'start') {
1323+
tx.attr('text-anchor', 'start');
1324+
posX = -d.bx - HOVERTEXTPAD;
1325+
} else if(textAlign === 'right' && anchor !== 'end') {
1326+
tx.attr('text-anchor', 'end');
1327+
posX = d.bx + HOVERTEXTPAD;
1328+
}
1329+
}
1330+
1331+
tx.call(svgTextUtils.positionText, posX, posY);
13211332

13221333
if(d.tx2width) {
13231334
g.select('text.name')
@@ -1364,6 +1375,7 @@ function cleanPoint(d, hovermode) {
13641375
fill('fontSize', 'hts', 'hoverlabel.font.size');
13651376
fill('fontColor', 'htc', 'hoverlabel.font.color');
13661377
fill('nameLength', 'hnl', 'hoverlabel.namelength');
1378+
fill('textAlign', 'hta', 'hoverlabel.align');
13671379

13681380
d.posref = (hovermode === 'y' || (hovermode === 'closest' && trace.orientation === 'h')) ?
13691381
(d.xa._offset + (d.x0 + d.x1) / 2) :

src/components/fx/hoverlabel_defaults.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ module.exports = function handleHoverLabelDefaults(contIn, contOut, coerce, opts
1717
coerce('hoverlabel.bordercolor', opts.bordercolor);
1818
coerce('hoverlabel.namelength', opts.namelength);
1919
Lib.coerceFont(coerce, 'hoverlabel.font', opts.font);
20+
coerce('hoverlabel.align', opts.align);
2021
};

src/components/fx/layout_attributes.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,17 @@ module.exports = {
117117
].join(' ')
118118
},
119119
font: fontAttrs,
120+
align: {
121+
valType: 'enumerated',
122+
values: ['left', 'right', 'auto'],
123+
dflt: 'auto',
124+
role: 'style',
125+
editType: 'none',
126+
description: [
127+
'Sets the horizontal alignment of the text content within hover label box.',
128+
'Has an effect only if the hover label text spans more two or more lines'
129+
].join(' ')
130+
},
120131
namelength: {
121132
valType: 'integer',
122133
min: -1,

test/jasmine/tests/fx_test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ describe('Fx defaults', function() {
171171
size: 40,
172172
color: 'pink'
173173
},
174+
align: 'auto',
174175
namelength: 15
175176
});
176177

@@ -182,6 +183,7 @@ describe('Fx defaults', function() {
182183
size: 20,
183184
color: 'red'
184185
},
186+
align: 'auto',
185187
namelength: 15
186188
});
187189

test/jasmine/tests/hover_label_test.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2034,6 +2034,54 @@ describe('hover info', function() {
20342034
.catch(failTest)
20352035
.then(done);
20362036
});
2037+
2038+
it('should honor *hoverlabel.align', function(done) {
2039+
var gd = createGraphDiv();
2040+
2041+
function _assert(msg, exp) {
2042+
var tx = d3.select('g.hovertext').select('text');
2043+
expect(tx.attr('text-anchor')).toBe(exp.textAnchor, 'text anchor|' + msg);
2044+
expect(Number(tx.attr('x'))).toBeCloseTo(exp.posX, 2, 'x position|' + msg);
2045+
}
2046+
2047+
Plotly.plot(gd, [{
2048+
y: [1, 2, 1],
2049+
text: 'LONG TEXT'
2050+
}], {
2051+
xaxis: {range: [0, 2]},
2052+
margin: {l: 0, t: 0, b: 0, r: 0},
2053+
hovermode: 'closest',
2054+
width: 400,
2055+
height: 400
2056+
})
2057+
.then(function() { _hoverNatural(gd, 0, 395); })
2058+
.then(function() { _assert('base left pt', {textAnchor: 'start', posX: 9}); })
2059+
.then(function() { _hoverNatural(gd, 395, 395); })
2060+
.then(function() { _assert('base right pt', {textAnchor: 'end', posX: -9}); })
2061+
.then(function() {
2062+
return Plotly.relayout(gd, 'hoverlabel.align', 'left');
2063+
})
2064+
.then(function() { _hoverNatural(gd, 0, 395); })
2065+
.then(function() { _assert('align:left left pt', {textAnchor: 'start', posX: 9}); })
2066+
.then(function() { _hoverNatural(gd, 395, 395); })
2067+
.then(function() { _assert('align:left right pt', {textAnchor: 'start', posX: -84.73}); })
2068+
.then(function() {
2069+
return Plotly.restyle(gd, 'hoverlabel.align', 'right');
2070+
})
2071+
.then(function() { _hoverNatural(gd, 0, 395); })
2072+
.then(function() { _assert('align:right left pt', {textAnchor: 'end', posX: 84.73}); })
2073+
.then(function() { _hoverNatural(gd, 395, 395); })
2074+
.then(function() { _assert('align:right right pt', {textAnchor: 'end', posX: -9}); })
2075+
.then(function() {
2076+
return Plotly.restyle(gd, 'hoverlabel.align', [['right', 'auto', 'left']]);
2077+
})
2078+
.then(function() { _hoverNatural(gd, 0, 395); })
2079+
.then(function() { _assert('arrayOk align:right left pt', {textAnchor: 'end', posX: 84.73}); })
2080+
.then(function() { _hoverNatural(gd, 395, 395); })
2081+
.then(function() { _assert('arrayOk align:left right pt', {textAnchor: 'start', posX: -84.73}); })
2082+
.catch(failTest)
2083+
.then(done);
2084+
});
20372085
});
20382086

20392087
describe('hover info on stacked subplots', function() {

0 commit comments

Comments
 (0)