diff --git a/src/components/fx/helpers.js b/src/components/fx/helpers.js index f11e5266ef7..d0d76712634 100644 --- a/src/components/fx/helpers.js +++ b/src/components/fx/helpers.js @@ -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; diff --git a/src/components/fx/hover.js b/src/components/fx/hover.js index e9e92749801..f6c79251142 100644 --- a/src/components/fx/hover.js +++ b/src/components/fx/hover.js @@ -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 hot = gd.offsetTop + gd.clientTop; + var hol = 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++) { @@ -746,6 +752,14 @@ function _hover(gd, evt, subplot, noHoverEvent) { pt.hovertemplate = ht || pt.trace.hovertemplate || false; } + var bbox = {}; + eventData.bbox = bbox; + + if ('x0' in pt) bbox.x0 = hol + pt.x0 + pt.xa._offset; + if ('x1' in pt) bbox.x1 = hol + pt.x1 + pt.xa._offset; + if ('y0' in pt) bbox.y0 = hot + pt.y0 + pt.ya._offset; + if ('y1' in pt) bbox.y1 = hot + pt.y1 + pt.ya._offset; + pt.eventData = [eventData]; newhoverdata.push(eventData); } diff --git a/src/traces/bar/event_data.js b/src/traces/bar/event_data.js index fb20f16b065..27320aa0997 100644 --- a/src/traces/bar/event_data.js +++ b/src/traces/bar/event_data.js @@ -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; + if(trace.orientation === 'h') { out.label = out.y; out.value = out.x; diff --git a/src/traces/box/event_data.js b/src/traces/box/event_data.js index 4ee9bd70d9f..16a8a51e011 100644 --- a/src/traces/box/event_data.js +++ b/src/traces/box/event_data.js @@ -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; }; diff --git a/src/traces/funnel/event_data.js b/src/traces/funnel/event_data.js index 678219186e4..3603a29055a 100644 --- a/src/traces/funnel/event_data.js +++ b/src/traces/funnel/event_data.js @@ -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; }; diff --git a/src/traces/histogram/event_data.js b/src/traces/histogram/event_data.js index db61fccc7db..3830a8e53f4 100644 --- a/src/traces/histogram/event_data.js +++ b/src/traces/histogram/event_data.js @@ -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) ? diff --git a/src/traces/image/event_data.js b/src/traces/image/event_data.js index 0d8d1bc3ba0..4bcb2bab08e 100644 --- a/src/traces/image/event_data.js +++ b/src/traces/image/event_data.js @@ -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; diff --git a/src/traces/pie/event_data.js b/src/traces/pie/event_data.js index 3393f0353dd..eb5cdcad87a 100644 --- a/src/traces/pie/event_data.js +++ b/src/traces/pie/event_data.js @@ -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) + bbox: { + x0: pt.x0, + x1: pt.x1, + y0: pt.y0, + y1: pt.y1, + }, }; // Only include pointNumber if it's unambiguous diff --git a/src/traces/pie/plot.js b/src/traces/pie/plot.js index cca8694817d..38a6699f580 100644 --- a/src/traces/pie/plot.js +++ b/src/traces/pie/plot.js @@ -379,12 +379,20 @@ 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 = []; @@ -406,9 +414,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('
'), name: (trace2.hovertemplate || hoverinfo.indexOf('name') !== -1) ? trace2.name : undefined, idealAlign: pt.pxmid[0] < 0 ? 'left' : 'right', diff --git a/src/traces/scattercarpet/event_data.js b/src/traces/scattercarpet/event_data.js index 41aa4b4a739..c4b1feca719 100644 --- a/src/traces/scattercarpet/event_data.js +++ b/src/traces/scattercarpet/event_data.js @@ -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; }; diff --git a/src/traces/scatterternary/event_data.js b/src/traces/scatterternary/event_data.js index ef7722d7419..4a72adc00b6 100644 --- a/src/traces/scatterternary/event_data.js +++ b/src/traces/scatterternary/event_data.js @@ -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]; diff --git a/src/traces/waterfall/event_data.js b/src/traces/waterfall/event_data.js index 24c05324795..5154517813a 100644 --- a/src/traces/waterfall/event_data.js +++ b/src/traces/waterfall/event_data.js @@ -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; };