Skip to content
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

Output bounding box to hover event data #5512

Merged
merged 19 commits into from
Aug 26, 2021
Merged
Show file tree
Hide file tree
Changes from 7 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/5512_add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Provide bounding box positions in hover event data [[#5512](https://github.com/plotly/plotly.js/pull/5512)]
5 changes: 5 additions & 0 deletions src/components/fx/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ exports.makeEventData = function(pt, trace, cd) {
if('yVal' in pt) out.y = pt.yVal;
else if('y' in pt) out.y = pt.y;

if('x0' in pt) out.x0 = pt.x0;
if('x1' in pt) out.x1 = pt.x1;
if('y0' in pt) out.y0 = pt.y0;
if('y1' in pt) out.y1 = pt.y1;

if(pt.xa) out.xaxis = pt.xa;
if(pt.ya) out.yaxis = pt.ya;
if(pt.zLabelVal !== undefined) out.z = pt.zLabelVal;
Expand Down
13 changes: 13 additions & 0 deletions src/components/fx/hover.js
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,12 @@ function _hover(gd, evt, subplot, noHoverEvent) {
var oldhoverdata = gd._hoverdata;
var newhoverdata = [];

// Top/left hover offsets relative to graph div. As long as hover content is
// a sibling of the graph div, it will be positioned correctly relative to
// the offset parent, whatever that may be.
var gTop = gd.offsetTop + gd.clientTop;
var gLeft = gd.offsetLeft + gd.clientLeft;

// pull out just the data that's useful to
// other people and send it to the event
for(itemnum = 0; itemnum < hoverData.length; itemnum++) {
Expand All @@ -746,6 +752,13 @@ function _hover(gd, evt, subplot, noHoverEvent) {
pt.hovertemplate = ht || pt.trace.hovertemplate || false;
}

var bbox = {};
if('x0' in pt) bbox.x0 = pt.x0 + pt.xa._offset + gLeft;
if('x1' in pt) bbox.x1 = pt.x1 + pt.xa._offset + gLeft;
if('y0' in pt) bbox.y0 = pt.y0 + pt.ya._offset + gTop;
if('y1' in pt) bbox.y1 = pt.y1 + pt.ya._offset + gTop;
eventData.bbox = bbox;

pt.eventData = [eventData];
newhoverdata.push(eventData);
}
Expand Down
5 changes: 5 additions & 0 deletions src/traces/bar/event_data.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ module.exports = function eventData(out, pt, trace) {
if(pt.xa) out.xaxis = pt.xa;
if(pt.ya) out.yaxis = pt.ya;

if('x0' in pt) out.x0 = pt.x0;
if('x1' in pt) out.x1 = pt.x1;
if('y0' in pt) out.y0 = pt.y0;
if('y1' in pt) out.y1 = pt.y1;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need x0 , x1, y0 and y1 in event data? Having bbox in not enough?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we concluded that more was better here, to make it easier for folks in Dash-land.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this correct? For vertical bars y0 is equal to y1 here and in the bbox.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't p0, p1, s0 and s1 used instead of (x|y) (0|1)?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For vertical bars y0 is equal to y1

Yes, y0===y1 for vertical bars. We want the label to be at the end of the bar, not in the middle.

Shouldn't p0, p1, s0 and s1 used instead

The final event data should contain x/y. p/s is not useful to the user for positioning other elements, and that's the purpose here.

if(trace.orientation === 'h') {
out.label = out.y;
out.value = out.x;
Expand Down
5 changes: 5 additions & 0 deletions src/traces/box/event_data.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,10 @@ module.exports = function eventData(out, pt) {
if(pt.xa) out.xaxis = pt.xa;
if(pt.ya) out.yaxis = pt.ya;

if('x0' in pt) out.x0 = pt.x0;
if('x1' in pt) out.x1 = pt.x1;
if('y0' in pt) out.y0 = pt.y0;
if('y1' in pt) out.y1 = pt.y1;

return out;
};
5 changes: 5 additions & 0 deletions src/traces/funnel/event_data.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,10 @@ module.exports = function eventData(out, pt /* , trace, cd, pointNumber */) {
if(pt.xa) out.xaxis = pt.xa;
if(pt.ya) out.yaxis = pt.ya;

if('x0' in pt) out.x0 = pt.x0;
if('x1' in pt) out.x1 = pt.x1;
if('y0' in pt) out.y0 = pt.y0;
if('y1' in pt) out.y1 = pt.y1;

return out;
};
5 changes: 5 additions & 0 deletions src/traces/histogram/event_data.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ module.exports = function eventData(out, pt, trace, cd, pointNumber) {
if(pt.xa) out.xaxis = pt.xa;
if(pt.ya) out.yaxis = pt.ya;

if('x0' in pt) out.x0 = pt.x0;
if('x1' in pt) out.x1 = pt.x1;
if('y0' in pt) out.y0 = pt.y0;
if('y1' in pt) out.y1 = pt.y1;

// specific to histogram - CDFs do not have pts (yet?)
if(!(trace.cumulative || {}).enabled) {
var pts = Array.isArray(pointNumber) ?
Expand Down
6 changes: 6 additions & 0 deletions src/traces/image/event_data.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
module.exports = function eventData(out, pt) {
if('xVal' in pt) out.x = pt.xVal;
if('yVal' in pt) out.y = pt.yVal;

if('x0' in pt) out.x0 = pt.x0;
if('x1' in pt) out.x1 = pt.x1;
if('y0' in pt) out.y0 = pt.y0;
if('y1' in pt) out.y1 = pt.y1;

if(pt.xa) out.xaxis = pt.xa;
if(pt.ya) out.yaxis = pt.ya;
out.color = pt.color;
Expand Down
11 changes: 10 additions & 1 deletion src/traces/pie/event_data.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,16 @@ module.exports = function eventData(pt, trace) {
text: pt.text,

// pt.v (and pt.i below) for backward compatibility
v: pt.v
v: pt.v,

// TODO: These coordinates aren't quite correct and don't take into account some offset
// I still haven't quite located (similar to xa._offset)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this doesn't work correctly yet, can we just drop it and leave pie as a TODO?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 03b22ec.

bbox: {
x0: pt.x0,
x1: pt.x1,
y0: pt.y0,
y1: pt.y1,
},
};

// Only include pointNumber if it's unambiguous
Expand Down
19 changes: 13 additions & 6 deletions src/traces/pie/plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -379,12 +379,19 @@ function attachFxHandlers(sliceTop, gd, cd) {

if(hoverinfo === 'all') hoverinfo = 'label+text+value+percent+name';

// If hoverinfo === 'none', we still want the *coordinates* of hover to be
// output, just not the hover to actually display
var rInscribed = pt.rInscribed || 0;
var hoverCenterX = cx + pt.pxmid[0] * (1 - rInscribed);
var hoverCenterY = cy + pt.pxmid[1] * (1 - rInscribed);
pt.x0 = hoverCenterX - rInscribed * cd0.r;
pt.x1 = hoverCenterX + rInscribed * cd0.r;
pt.y0 = hoverCenterY;
pt.y1 = hoverCenterY;

// in case we dragged over the pie from another subplot,
// or if hover is turned off
if(trace2.hovertemplate || (hoverinfo !== 'none' && hoverinfo !== 'skip' && hoverinfo)) {
var rInscribed = pt.rInscribed || 0;
var hoverCenterX = cx + pt.pxmid[0] * (1 - rInscribed);
var hoverCenterY = cy + pt.pxmid[1] * (1 - rInscribed);
var separators = fullLayout2.separators;
var text = [];

Expand All @@ -406,9 +413,9 @@ function attachFxHandlers(sliceTop, gd, cd) {

Fx.loneHover({
trace: trace,
x0: hoverCenterX - rInscribed * cd0.r,
x1: hoverCenterX + rInscribed * cd0.r,
y: hoverCenterY,
x0: pt.x0,
x1: pt.x1,
y: pt.y0,
text: text.join('<br>'),
name: (trace2.hovertemplate || hoverinfo.indexOf('name') !== -1) ? trace2.name : undefined,
idealAlign: pt.pxmid[0] < 0 ? 'left' : 'right',
Expand Down
5 changes: 5 additions & 0 deletions src/traces/scattercarpet/event_data.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,10 @@ module.exports = function eventData(out, pt, trace, cd, pointNumber) {
out.b = cdi.b;
out.y = cdi.y;

if('x0' in pt) out.x0 = pt.x0;
if('x1' in pt) out.x1 = pt.x1;
if('y0' in pt) out.y0 = pt.y0;
if('y1' in pt) out.y1 = pt.y1;

return out;
};
5 changes: 5 additions & 0 deletions src/traces/scatterternary/event_data.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ module.exports = function eventData(out, pt, trace, cd, pointNumber) {
if(pt.xa) out.xaxis = pt.xa;
if(pt.ya) out.yaxis = pt.ya;

if('x0' in pt) out.x0 = pt.x0;
if('x1' in pt) out.x1 = pt.x1;
if('y0' in pt) out.y0 = pt.y0;
if('y1' in pt) out.y1 = pt.y1;

if(cd[pointNumber]) {
var cdi = cd[pointNumber];

Expand Down
5 changes: 5 additions & 0 deletions src/traces/waterfall/event_data.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,10 @@ module.exports = function eventData(out, pt /* , trace, cd, pointNumber */) {
if(pt.xa) out.xaxis = pt.xa;
if(pt.ya) out.yaxis = pt.ya;

if('x0' in pt) out.x0 = pt.x0;
if('x1' in pt) out.x1 = pt.x1;
if('y0' in pt) out.y0 = pt.y0;
if('y1' in pt) out.y1 = pt.y1;

return out;
};
30 changes: 18 additions & 12 deletions test/jasmine/tests/click_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,11 @@ describe('Test click interactions:', function() {
expect(contextPassthroughs).toBe(0);

var pt = futureData.points[0];
expect(Object.keys(pt)).toEqual([
expect(Object.keys(pt).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex',
'bbox', 'x0', 'x1', 'y0', 'y1',
'x', 'y', 'xaxis', 'yaxis'
]);
].sort());
expect(pt.curveNumber).toEqual(0);
expect(pt.pointNumber).toEqual(11);
expect(pt.x).toEqual(0.125);
Expand Down Expand Up @@ -148,10 +149,11 @@ describe('Test click interactions:', function() {
expect(contextPassthroughs).toBe(0);

var pt = futureData.points[0];
expect(Object.keys(pt)).toEqual([
expect(Object.keys(pt).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex',
'bbox', 'x0', 'x1', 'y0', 'y1',
'x', 'y', 'xaxis', 'yaxis'
]);
].sort());
expect(pt.curveNumber).toEqual(0);
expect(pt.pointNumber).toEqual(11);
expect(pt.x).toEqual(0.125);
Expand Down Expand Up @@ -219,10 +221,11 @@ describe('Test click interactions:', function() {
expect(contextPassthroughs).toBe(0, i);

var pt = futureData.points[0];
expect(Object.keys(pt)).toEqual([
expect(Object.keys(pt).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex',
'bbox', 'x0', 'x1', 'y0', 'y1',
'x', 'y', 'xaxis', 'yaxis'
]);
].sort());
expect(pt.curveNumber).toEqual(0);
expect(pt.pointNumber).toEqual(11);
expect(pt.x).toEqual(0.125);
Expand Down Expand Up @@ -308,10 +311,11 @@ describe('Test click interactions:', function() {
expect(futureData.points.length).toEqual(1);

var pt = futureData.points[0];
expect(Object.keys(pt)).toEqual([
expect(Object.keys(pt).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex',
'bbox', 'x0', 'x1', 'y0', 'y1',
'x', 'y', 'xaxis', 'yaxis'
]);
].sort());
expect(pt.curveNumber).toEqual(0);
expect(pt.pointNumber).toEqual(11);
expect(pt.x).toEqual(0.125);
Expand Down Expand Up @@ -341,10 +345,11 @@ describe('Test click interactions:', function() {
expect(futureData.points.length).toEqual(1);

var pt = futureData.points[0];
expect(Object.keys(pt)).toEqual([
expect(Object.keys(pt).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex',
'bbox', 'x0', 'x1', 'y0', 'y1',
'x', 'y', 'xaxis', 'yaxis'
]);
].sort());
expect(pt.curveNumber).toEqual(0);
expect(pt.pointNumber).toEqual(11);
expect(pt.x).toEqual(0.125);
Expand Down Expand Up @@ -378,10 +383,11 @@ describe('Test click interactions:', function() {
expect(futureData.points.length).toEqual(1);

var pt = futureData.points[0];
expect(Object.keys(pt)).toEqual([
expect(Object.keys(pt).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex',
'bbox', 'x0', 'x1', 'y0', 'y1',
'x', 'y', 'xaxis', 'yaxis'
]);
].sort());
expect(pt.curveNumber).toEqual(0);
expect(pt.pointNumber).toEqual(11);
expect(pt.x).toEqual(0.125);
Expand Down
2 changes: 1 addition & 1 deletion test/jasmine/tests/funnelarea_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -763,7 +763,7 @@ describe('funnelarea hovering', function() {

var fields = [
'curveNumber', 'pointNumber', 'pointNumbers',
'data', 'fullData',
'data', 'fullData', 'bbox',
'label', 'color', 'value',
'percent', 'text'
];
Expand Down
Loading