Skip to content

Rotate hover labels in a few more scenarios #3043

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 25, 2018
Merged
Show file tree
Hide file tree
Changes from 2 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
14 changes: 11 additions & 3 deletions src/components/fx/hover.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,10 @@ function _hover(gd, evt, subplot, noHoverEvent) {
vLinePoint: null
};

// does subplot have one (or more) horizontal traces,
// (to determine whether we rotate the labels or not)
var hasOneHorizontalTrace = false;

// Figure out what we're hovering on:
// mouse location or user-supplied data

Expand All @@ -256,6 +260,9 @@ function _hover(gd, evt, subplot, noHoverEvent) {
trace = cd[0].trace;
if(trace.hoverinfo !== 'skip' && helpers.isTraceInSubplots(trace, subplots)) {
searchData.push(cd);
if(trace.orientation === 'h') {
hasOneHorizontalTrace = true;
}
}
}

Expand Down Expand Up @@ -577,9 +584,10 @@ function _hover(gd, evt, subplot, noHoverEvent) {

gd._hoverdata = newhoverdata;

// if there's more than one horz bar trace,
// rotate the labels so they don't overlap
var rotateLabels = hovermode === 'y' && searchData.length > 1;
var rotateLabels = (
(hovermode === 'y' && (searchData.length > 1 || hoverData.length > 1)) ||
(hovermode === 'closest' && hasOneHorizontalTrace)
);

var bgColor = Color.combine(
fullLayout.plot_bgcolor || Color.background,
Expand Down
51 changes: 31 additions & 20 deletions test/jasmine/assets/custom_assertions.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ function count(selector) {
* - nums {string || array of strings}
* - name {string || array of strings}
* - axis {string}
* - vOrder {array of number}
* - hOrder {array of number}
* - isRotated {boolean}
* @param {string} msg
*/
exports.assertHoverLabelContent = function(expectation, msg) {
Expand All @@ -103,17 +106,22 @@ exports.assertHoverLabelContent = function(expectation, msg) {
var axMsg = 'common axis hover label';
var axCnt = count(axSelector);

var reRotate = /(\brotate\(.*?\);?)/;

if(ptCnt === 1) {
assertLabelContent(
d3.select(ptSelector + '> text.nums'),
expectation.nums,
ptMsg + ' (nums)'
);
assertLabelContent(
d3.select(ptSelector + '> text.name'),
expectation.name,
ptMsg + ' (name)'
);
var g = d3.select(ptSelector);
var numsSel = g.select('text.nums');
var nameSel = g.select('text.name');

assertLabelContent(numsSel, expectation.nums, ptMsg + ' (nums)');
assertLabelContent(nameSel, expectation.name, ptMsg + ' (name)');

if('isRotated' in expectation) {
expect(g.attr('transform').match(reRotate))
.negateIf(expectation.isRotated)
.toBe(null, ptMsg + ' should be rotated');

}
} else if(ptCnt > 1) {
if(!Array.isArray(expectation.nums) || !Array.isArray(expectation.name)) {
fail(ptMsg + ': expecting more than 1 labels.');
Expand All @@ -124,16 +132,19 @@ exports.assertHoverLabelContent = function(expectation, msg) {

var bboxes = [];
d3.selectAll(ptSelector).each(function(_, i) {
assertLabelContent(
d3.select(this).select('text.nums'),
expectation.nums[i],
ptMsg + ' (nums ' + i + ')'
);
assertLabelContent(
d3.select(this).select('text.name'),
expectation.name[i],
ptMsg + ' (name ' + i + ')'
);
var g = d3.select(this);
var numsSel = g.select('text.nums');
var nameSel = g.select('text.name');

assertLabelContent(numsSel, expectation.nums[i], ptMsg + ' (nums ' + i + ')');
assertLabelContent(nameSel, expectation.name[i], ptMsg + ' (name ' + i + ')');

if('isRotated' in expectation) {
expect(g.attr('transform').match(reRotate))
.negateIf(expectation.isRotated)
.toBe(null, ptMsg + ' ' + i + ' should be rotated');
}

bboxes.push({bbox: this.getBoundingClientRect(), index: i});
});
if(expectation.vOrder) {
Expand Down
45 changes: 45 additions & 0 deletions test/jasmine/tests/violin_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,51 @@ describe('Test violin hover:', function() {
nums: 'x: 42.43046, kde: 0.083',
name: '',
axis: 'Saturday'
}, {
desc: 'single horizontal violin',
mock: require('@mocks/violin_non-linear.json'),
pos: [310, 160],
nums: ['median: C', 'min: A', 'q1: B', 'q3: D', 'max: G', 'upper fence: D', 'x: C, kde: 1.005'],
name: ['categories', '', '', '', '', '', ''],
axis: 'categories',
hOrder: [4, 5, 3, 6, 0, 2, 1],
isRotated: true
}, {
desc: 'multiple horizontal violins',
mock: require('@mocks/box_grouped_horz.json'),
patch: function(fig) {
fig.data.forEach(function(t) {
t.type = 'violin';
t.hoveron = 'violins';
});
fig.layout.violinmode = 'group';
return fig;
},
nums: ['median: 0.4', 'min: 0.1', 'q1: 0.2', 'q3: 0.7', 'max: 0.9'],
name: ['kale', '', '', '', ''],
axis: 'day 2',
hOrder: [4, 3, 0, 2, 1],
isRotated: true
}, {
desc: 'multiple horizontal violins (under hovermode:closest)',
mock: require('@mocks/box_grouped_horz.json'),
patch: function(fig) {
fig.data.forEach(function(t) {
t.type = 'violin';
t.hoveron = 'violins';
});
fig.layout.violinmode = 'group';
fig.layout.hovermode = 'closest';
return fig;
},
pos: [200, 175],
nums: [
'(median: 0.7, day 2)', '(min: 0.2, day 2)', '(q1: 0.5, day 2)',
'(q3: 0.8, day 2)', '(max: 0.9, day 2)'
],
name: ['radishes', '', '', '', ''],
hOrder: [4, 3, 0, 2, 1],
isRotated: true
}]
.forEach(function(specs) {
it('should generate correct hover labels ' + specs.desc, function(done) {
Expand Down