Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
16 changes: 14 additions & 2 deletions src/components/fx/click.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var hover = require('./hover').hover;

module.exports = function click(gd, evt, subplot) {
var annotationsDone = Registry.getComponentMethod('annotations', 'onClick')(gd, gd._hoverdata);
var fullLayout = gd._fullLayout;

// fallback to fail-safe in case the plot type's hover method doesn't pass the subplot.
// Ternary, for example, didn't, but it was caught because tested.
Expand All @@ -14,9 +15,20 @@ module.exports = function click(gd, evt, subplot) {
hover(gd, evt, subplot, true);
}

function emitClick() { gd.emit('plotly_click', {points: gd._hoverdata, event: evt}); }
function emitClick() {
var clickData = {points: gd._hoverdata, event: evt};

// get coordinate values from latest hover call, if available
clickData.xaxes ??= gd._hoverXAxes;
clickData.yaxes ??= gd._hoverYAxes;
clickData.xvals ??= gd._hoverXVals;
clickData.yvals ??= gd._hoverYVals;

if(gd._hoverdata && evt && evt.target) {
gd.emit('plotly_click', clickData);
}

if((gd._hoverdata || fullLayout.clickanywhere) && evt && evt.target) {
if(!gd._hoverdata) gd._hoverdata = [];
if(annotationsDone && annotationsDone.then) {
annotationsDone.then(emitClick);
} else emitClick();
Expand Down
28 changes: 26 additions & 2 deletions src/components/fx/hover.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ exports.loneHover = function loneHover(hoverItems, opts) {
y1: y1 + gTop
};

eventData.xPixel = (_x0 + _x1) / 2;
eventData.yPixel = (_y0 + _y1) / 2;

if (opts.inOut_bbox) {
opts.inOut_bbox.push(eventData.bbox);
}
Expand Down Expand Up @@ -473,6 +476,12 @@ function _hover(gd, evt, subplot, noHoverEvent, eventTarget) {
}
}

// Save coordinate values so clickanywhere can be used without hoveranywhere
gd._hoverXVals = xvalArray;
gd._hoverYVals = yvalArray;
gd._hoverXAxes = xaArray;
gd._hoverYAxes = yaArray;

// the pixel distance to beat as a matching point
// in 'x' or 'y' mode this resets for each trace
var distance = Infinity;
Expand Down Expand Up @@ -778,6 +787,17 @@ function _hover(gd, evt, subplot, noHoverEvent, eventTarget) {
createSpikelines(gd, spikePoints, spikelineOpts);
}
}

if (fullLayout.hoveranywhere && !noHoverEvent && eventTarget) {
gd.emit('plotly_hover', {
event: evt,
points: [],
xaxes: xaArray,
yaxes: yaArray,
xvals: xvalArray,
yvals: yvalArray
});
}
return result;
}

Expand Down Expand Up @@ -877,6 +897,9 @@ function _hover(gd, evt, subplot, noHoverEvent, eventTarget) {
y0: y0 + gTop,
y1: y1 + gTop
};

eventData.xPixel = (_x0 + _x1) / 2;
eventData.yPixel = (_y0 + _y1) / 2;
}

pt.eventData = [eventData];
Expand Down Expand Up @@ -914,9 +937,10 @@ function _hover(gd, evt, subplot, noHoverEvent, eventTarget) {
}

// don't emit events if called manually
if (!eventTarget || noHoverEvent || !hoverChanged(gd, evt, oldhoverdata)) return;
var _hoverChanged = hoverChanged(gd, evt, oldhoverdata);
if (!eventTarget || noHoverEvent || (!_hoverChanged && !fullLayout.hoveranywhere)) return;

if (oldhoverdata) {
if (oldhoverdata && _hoverChanged) {
gd.emit('plotly_unhover', {
event: evt,
points: oldhoverdata
Expand Down
2 changes: 2 additions & 0 deletions src/components/fx/hovermode_defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,7 @@ module.exports = function handleHoverModeDefaults(layoutIn, layoutOut) {

coerce('clickmode');
coerce('hoversubplots');
coerce('hoveranywhere');
coerce('clickanywhere');
return coerce('hovermode');
};
22 changes: 22 additions & 0 deletions src/components/fx/layout_attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,28 @@ module.exports = {
'when `hovermode` is set to *x*, *x unified*, *y* or *y unified*.',
].join(' ')
},
hoveranywhere: {
valType: 'boolean',
dflt: false,
editType: 'none',
description: [
'If true, `plotly_hover` events will fire for any cursor position',
'within the plot area, not just over traces.',
'When the cursor is not over a trace, the event will have an empty `points` array',
'but will include `xvals` and `yvals` with cursor coordinates in data space.'
].join(' ')
},
clickanywhere: {
valType: 'boolean',
dflt: false,
editType: 'none',
description: [
'If true, `plotly_click` events will fire for any click position',
'within the plot area, not just over traces.',
'When clicking where there is no trace data, the event will have an empty `points` array',
'but will include `xvals` and `yvals` with click coordinates in data space.'
].join(' ')
},
hoverdistance: {
valType: 'integer',
min: -1,
Expand Down
Binary file modified test/image/baselines/map_custom-style.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 6 additions & 6 deletions test/jasmine/tests/click_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ describe('Test click interactions:', function() {
expect(Object.keys(pt).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex',
'bbox',
'x', 'y', 'xaxis', 'yaxis'
'x', 'y', 'xaxis', 'yaxis', 'xPixel', 'yPixel'
].sort());
expect(pt.curveNumber).toEqual(0);
expect(pt.pointNumber).toEqual(11);
Expand Down Expand Up @@ -153,7 +153,7 @@ describe('Test click interactions:', function() {
expect(Object.keys(pt).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex',
'bbox',
'x', 'y', 'xaxis', 'yaxis'
'x', 'y', 'xaxis', 'yaxis', 'xPixel', 'yPixel'
].sort());
expect(pt.curveNumber).toEqual(0);
expect(pt.pointNumber).toEqual(11);
Expand Down Expand Up @@ -225,7 +225,7 @@ describe('Test click interactions:', function() {
expect(Object.keys(pt).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex',
'bbox',
'x', 'y', 'xaxis', 'yaxis'
'x', 'y', 'xaxis', 'yaxis', 'xPixel', 'yPixel'
].sort());
expect(pt.curveNumber).toEqual(0);
expect(pt.pointNumber).toEqual(11);
Expand Down Expand Up @@ -315,7 +315,7 @@ describe('Test click interactions:', function() {
expect(Object.keys(pt).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex',
'bbox',
'x', 'y', 'xaxis', 'yaxis'
'x', 'y', 'xaxis', 'yaxis', 'xPixel', 'yPixel'
].sort());
expect(pt.curveNumber).toEqual(0);
expect(pt.pointNumber).toEqual(11);
Expand Down Expand Up @@ -349,7 +349,7 @@ describe('Test click interactions:', function() {
expect(Object.keys(pt).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex',
'bbox',
'x', 'y', 'xaxis', 'yaxis'
'x', 'y', 'xaxis', 'yaxis', 'xPixel', 'yPixel'
].sort());
expect(pt.curveNumber).toEqual(0);
expect(pt.pointNumber).toEqual(11);
Expand Down Expand Up @@ -387,7 +387,7 @@ describe('Test click interactions:', function() {
expect(Object.keys(pt).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex',
'bbox',
'x', 'y', 'xaxis', 'yaxis'
'x', 'y', 'xaxis', 'yaxis', 'xPixel', 'yPixel'
].sort());
expect(pt.curveNumber).toEqual(0);
expect(pt.pointNumber).toEqual(11);
Expand Down
18 changes: 9 additions & 9 deletions test/jasmine/tests/geo_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,7 @@ describe('Test geo interactions', function() {
it('should contain the correct fields', function() {
expect(Object.keys(ptData).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex', 'bbox',
'lon', 'lat', 'location', 'marker.size'
'lon', 'lat', 'location', 'marker.size', 'xPixel', 'yPixel'
].sort());
expect(cnt).toEqual(1);
});
Expand Down Expand Up @@ -947,7 +947,7 @@ describe('Test geo interactions', function() {
it('should contain the correct fields', function() {
expect(Object.keys(ptData).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex', 'bbox',
'lon', 'lat', 'location', 'marker.size'
'lon', 'lat', 'location', 'marker.size', 'xPixel', 'yPixel'
].sort());
});

Expand Down Expand Up @@ -979,7 +979,7 @@ describe('Test geo interactions', function() {
it('should contain the correct fields', function() {
expect(Object.keys(ptData).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex', 'bbox',
'lon', 'lat', 'location', 'marker.size'
'lon', 'lat', 'location', 'marker.size', 'xPixel', 'yPixel'
].sort());
});

Expand Down Expand Up @@ -1008,7 +1008,7 @@ describe('Test geo interactions', function() {
it('should contain the correct fields', function() {
expect(Object.keys(ptData).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex', 'bbox',
'location', 'z', 'ct'
'location', 'z', 'ct', 'xPixel', 'yPixel'
].sort());
});

Expand Down Expand Up @@ -1036,7 +1036,7 @@ describe('Test geo interactions', function() {
it('should contain the correct fields', function() {
expect(Object.keys(ptData).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex', 'bbox',
'location', 'z', 'ct'
'location', 'z', 'ct', 'xPixel', 'yPixel'
].sort());
});

Expand Down Expand Up @@ -1068,7 +1068,7 @@ describe('Test geo interactions', function() {
it('should contain the correct fields', function() {
expect(Object.keys(ptData).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex', 'bbox',
'location', 'z', 'ct'
'location', 'z', 'ct', 'xPixel', 'yPixel'
].sort());
});

Expand Down Expand Up @@ -1792,7 +1792,7 @@ describe('Test event property of interactions on a geo plot:', function() {
expect(Object.keys(pt).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex', 'bbox',
'lon', 'lat',
'location', 'text', 'marker.size'
'location', 'text', 'marker.size', 'xPixel', 'yPixel'
].sort());

expect(pt.curveNumber).toEqual(0, 'points[0].curveNumber');
Expand Down Expand Up @@ -1896,7 +1896,7 @@ describe('Test event property of interactions on a geo plot:', function() {
expect(Object.keys(pt).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex', 'bbox',
'lon', 'lat',
'location', 'text', 'marker.size'
'location', 'text', 'marker.size', 'xPixel', 'yPixel'
].sort());

expect(pt.curveNumber).toEqual(0, 'points[0].curveNumber');
Expand Down Expand Up @@ -1937,7 +1937,7 @@ describe('Test event property of interactions on a geo plot:', function() {
expect(Object.keys(pt).sort()).toEqual([
'data', 'fullData', 'curveNumber', 'pointNumber', 'pointIndex', 'bbox',
'lon', 'lat',
'location', 'text', 'marker.size'
'location', 'text', 'marker.size', 'xPixel', 'yPixel'
].sort());

expect(pt.curveNumber).toEqual(0, 'points[0].curveNumber');
Expand Down
Loading