Skip to content

Commit 1de5072

Browse files
committed
hover: wrap existing logic into a function
1 parent 0ad049c commit 1de5072

File tree

1 file changed

+154
-150
lines changed

1 file changed

+154
-150
lines changed

src/components/fx/hover.js

+154-150
Original file line numberDiff line numberDiff line change
@@ -365,176 +365,178 @@ function _hover(gd, evt, subplot, noHoverEvent) {
365365
// find the closest point in each trace
366366
// this is minimum dx and/or dy, depending on mode
367367
// and the pixel position for the label (labelXpx, labelYpx)
368-
for(curvenum = 0; curvenum < searchData.length; curvenum++) {
369-
cd = searchData[curvenum];
368+
function findHoverPoints(vals) {
369+
for(curvenum = 0; curvenum < searchData.length; curvenum++) {
370+
cd = searchData[curvenum];
370371

371-
// filter out invisible or broken data
372-
if(!cd || !cd[0] || !cd[0].trace) continue;
372+
// filter out invisible or broken data
373+
if(!cd || !cd[0] || !cd[0].trace) continue;
373374

374-
trace = cd[0].trace;
375+
trace = cd[0].trace;
375376

376-
if(trace.visible !== true || trace._length === 0) continue;
377+
if(trace.visible !== true || trace._length === 0) continue;
377378

378-
// Explicitly bail out for these two. I don't know how to otherwise prevent
379-
// the rest of this function from running and failing
380-
if(['carpet', 'contourcarpet'].indexOf(trace._module.name) !== -1) continue;
379+
// Explicitly bail out for these two. I don't know how to otherwise prevent
380+
// the rest of this function from running and failing
381+
if(['carpet', 'contourcarpet'].indexOf(trace._module.name) !== -1) continue;
381382

382-
if(trace.type === 'splom') {
383-
// splom traces do not generate overlay subplots,
384-
// it is safe to assume here splom traces correspond to the 0th subplot
385-
subploti = 0;
386-
subplotId = subplots[subploti];
387-
} else {
388-
subplotId = helpers.getSubplot(trace);
389-
subploti = subplots.indexOf(subplotId);
390-
}
391-
392-
// within one trace mode can sometimes be overridden
393-
mode = hovermode;
394-
if(['x unified', 'y unified'].indexOf(mode) !== -1) {
395-
mode = mode.charAt(0);
396-
}
397-
398-
// container for new point, also used to pass info into module.hoverPoints
399-
pointData = {
400-
// trace properties
401-
cd: cd,
402-
trace: trace,
403-
xa: xaArray[subploti],
404-
ya: yaArray[subploti],
405-
406-
// max distances for hover and spikes - for points that want to show but do not
407-
// want to override other points, set distance/spikeDistance equal to max*Distance
408-
// and it will not get filtered out but it will be guaranteed to have a greater
409-
// distance than any point that calculated a real distance.
410-
maxHoverDistance: hoverdistance,
411-
maxSpikeDistance: spikedistance,
412-
413-
// point properties - override all of these
414-
index: false, // point index in trace - only used by plotly.js hoverdata consumers
415-
distance: Math.min(distance, hoverdistance), // pixel distance or pseudo-distance
416-
417-
// distance/pseudo-distance for spikes. This distance should always be calculated
418-
// as if in "closest" mode, and should only be set if this point should
419-
// generate a spike.
420-
spikeDistance: Infinity,
421-
422-
// in some cases the spikes have different positioning from the hover label
423-
// they don't need x0/x1, just one position
424-
xSpike: undefined,
425-
ySpike: undefined,
426-
427-
// where and how to display the hover label
428-
color: Color.defaultLine, // trace color
429-
name: trace.name,
430-
x0: undefined,
431-
x1: undefined,
432-
y0: undefined,
433-
y1: undefined,
434-
xLabelVal: undefined,
435-
yLabelVal: undefined,
436-
zLabelVal: undefined,
437-
text: undefined
438-
};
383+
if(trace.type === 'splom') {
384+
// splom traces do not generate overlay subplots,
385+
// it is safe to assume here splom traces correspond to the 0th subplot
386+
subploti = 0;
387+
subplotId = subplots[subploti];
388+
} else {
389+
subplotId = helpers.getSubplot(trace);
390+
subploti = subplots.indexOf(subplotId);
391+
}
439392

440-
// add ref to subplot object (non-cartesian case)
441-
if(fullLayout[subplotId]) {
442-
pointData.subplot = fullLayout[subplotId]._subplot;
443-
}
444-
// add ref to splom scene
445-
if(fullLayout._splomScenes && fullLayout._splomScenes[trace.uid]) {
446-
pointData.scene = fullLayout._splomScenes[trace.uid];
447-
}
393+
// within one trace mode can sometimes be overridden
394+
mode = hovermode;
395+
if(['x unified', 'y unified'].indexOf(mode) !== -1) {
396+
mode = mode.charAt(0);
397+
}
448398

449-
closedataPreviousLength = hoverData.length;
399+
// container for new point, also used to pass info into module.hoverPoints
400+
pointData = {
401+
// trace properties
402+
cd: cd,
403+
trace: trace,
404+
xa: xaArray[subploti],
405+
ya: yaArray[subploti],
406+
407+
// max distances for hover and spikes - for points that want to show but do not
408+
// want to override other points, set distance/spikeDistance equal to max*Distance
409+
// and it will not get filtered out but it will be guaranteed to have a greater
410+
// distance than any point that calculated a real distance.
411+
maxHoverDistance: hoverdistance,
412+
maxSpikeDistance: spikedistance,
413+
414+
// point properties - override all of these
415+
index: false, // point index in trace - only used by plotly.js hoverdata consumers
416+
distance: Math.min(distance, hoverdistance), // pixel distance or pseudo-distance
417+
418+
// distance/pseudo-distance for spikes. This distance should always be calculated
419+
// as if in "closest" mode, and should only be set if this point should
420+
// generate a spike.
421+
spikeDistance: Infinity,
422+
423+
// in some cases the spikes have different positioning from the hover label
424+
// they don't need x0/x1, just one position
425+
xSpike: undefined,
426+
ySpike: undefined,
427+
428+
// where and how to display the hover label
429+
color: Color.defaultLine, // trace color
430+
name: trace.name,
431+
x0: undefined,
432+
x1: undefined,
433+
y0: undefined,
434+
y1: undefined,
435+
xLabelVal: undefined,
436+
yLabelVal: undefined,
437+
zLabelVal: undefined,
438+
text: undefined
439+
};
440+
441+
// add ref to subplot object (non-cartesian case)
442+
if(fullLayout[subplotId]) {
443+
pointData.subplot = fullLayout[subplotId]._subplot;
444+
}
445+
// add ref to splom scene
446+
if(fullLayout._splomScenes && fullLayout._splomScenes[trace.uid]) {
447+
pointData.scene = fullLayout._splomScenes[trace.uid];
448+
}
450449

451-
// for a highlighting array, figure out what
452-
// we're searching for with this element
453-
if(mode === 'array') {
454-
var selection = evt[curvenum];
455-
if('pointNumber' in selection) {
456-
pointData.index = selection.pointNumber;
457-
mode = 'closest';
458-
} else {
459-
mode = '';
460-
if('xval' in selection) {
461-
xval = selection.xval;
462-
mode = 'x';
463-
}
464-
if('yval' in selection) {
465-
yval = selection.yval;
466-
mode = mode ? 'closest' : 'y';
450+
closedataPreviousLength = hoverData.length;
451+
452+
// for a highlighting array, figure out what
453+
// we're searching for with this element
454+
if(mode === 'array') {
455+
var selection = evt[curvenum];
456+
if('pointNumber' in selection) {
457+
pointData.index = selection.pointNumber;
458+
mode = 'closest';
459+
} else {
460+
mode = '';
461+
if('xval' in selection) {
462+
xval = selection.xval;
463+
mode = 'x';
464+
}
465+
if('yval' in selection) {
466+
yval = selection.yval;
467+
mode = mode ? 'closest' : 'y';
468+
}
467469
}
470+
} else {
471+
xval = xvalArray[subploti];
472+
yval = yvalArray[subploti];
468473
}
469-
} else {
470-
xval = xvalArray[subploti];
471-
yval = yvalArray[subploti];
472-
}
473474

474-
// Now if there is range to look in, find the points to hover.
475-
if(hoverdistance !== 0) {
476-
if(trace._module && trace._module.hoverPoints) {
477-
var newPoints = trace._module.hoverPoints(pointData, xval, yval, mode, fullLayout._hoverlayer);
478-
if(newPoints) {
479-
var newPoint;
480-
for(var newPointNum = 0; newPointNum < newPoints.length; newPointNum++) {
481-
newPoint = newPoints[newPointNum];
482-
if(isNumeric(newPoint.x0) && isNumeric(newPoint.y0)) {
483-
hoverData.push(cleanPoint(newPoint, hovermode));
475+
// Now if there is range to look in, find the points to hover.
476+
if(hoverdistance !== 0) {
477+
if(trace._module && trace._module.hoverPoints) {
478+
var newPoints = trace._module.hoverPoints(pointData, xval, yval, mode, fullLayout._hoverlayer);
479+
if(newPoints) {
480+
var newPoint;
481+
for(var newPointNum = 0; newPointNum < newPoints.length; newPointNum++) {
482+
newPoint = newPoints[newPointNum];
483+
if(isNumeric(newPoint.x0) && isNumeric(newPoint.y0)) {
484+
hoverData.push(cleanPoint(newPoint, hovermode));
485+
}
484486
}
485487
}
488+
} else {
489+
Lib.log('Unrecognized trace type in hover:', trace);
486490
}
487-
} else {
488-
Lib.log('Unrecognized trace type in hover:', trace);
489491
}
490-
}
491492

492-
// in closest mode, remove any existing (farther) points
493-
// and don't look any farther than this latest point (or points, some
494-
// traces like box & violin make multiple hover labels at once)
495-
if(hovermode === 'closest' && hoverData.length > closedataPreviousLength) {
496-
hoverData.splice(0, closedataPreviousLength);
497-
distance = hoverData[0].distance;
498-
}
493+
// in closest mode, remove any existing (farther) points
494+
// and don't look any farther than this latest point (or points, some
495+
// traces like box & violin make multiple hover labels at once)
496+
if(hovermode === 'closest' && hoverData.length > closedataPreviousLength) {
497+
hoverData.splice(0, closedataPreviousLength);
498+
distance = hoverData[0].distance;
499+
}
499500

500-
// Now if there is range to look in, find the points to draw the spikelines
501-
// Do it only if there is no hoverData
502-
if(hasCartesian && (spikedistance !== 0)) {
503-
if(hoverData.length === 0) {
504-
pointData.distance = spikedistance;
505-
pointData.index = false;
506-
var closestPoints = trace._module.hoverPoints(pointData, xval, yval, 'closest', fullLayout._hoverlayer);
507-
if(closestPoints) {
508-
closestPoints = closestPoints.filter(function(point) {
509-
// some hover points, like scatter fills, do not allow spikes,
510-
// so will generate a hover point but without a valid spikeDistance
511-
return point.spikeDistance <= spikedistance;
512-
});
513-
}
514-
if(closestPoints && closestPoints.length) {
515-
var tmpPoint;
516-
var closestVPoints = closestPoints.filter(function(point) {
517-
return point.xa.showspikes;
518-
});
519-
if(closestVPoints.length) {
520-
var closestVPt = closestVPoints[0];
521-
if(isNumeric(closestVPt.x0) && isNumeric(closestVPt.y0)) {
522-
tmpPoint = fillSpikePoint(closestVPt);
523-
if(!spikePoints.vLinePoint || (spikePoints.vLinePoint.spikeDistance > tmpPoint.spikeDistance)) {
524-
spikePoints.vLinePoint = tmpPoint;
501+
// Now if there is range to look in, find the points to draw the spikelines
502+
// Do it only if there is no hoverData
503+
if(hasCartesian && (spikedistance !== 0)) {
504+
if(hoverData.length === 0) {
505+
pointData.distance = spikedistance;
506+
pointData.index = false;
507+
var closestPoints = trace._module.hoverPoints(pointData, xval, yval, 'closest', fullLayout._hoverlayer);
508+
if(closestPoints) {
509+
closestPoints = closestPoints.filter(function(point) {
510+
// some hover points, like scatter fills, do not allow spikes,
511+
// so will generate a hover point but without a valid spikeDistance
512+
return point.spikeDistance <= spikedistance;
513+
});
514+
}
515+
if(closestPoints && closestPoints.length) {
516+
var tmpPoint;
517+
var closestVPoints = closestPoints.filter(function(point) {
518+
return point.xa.showspikes;
519+
});
520+
if(closestVPoints.length) {
521+
var closestVPt = closestVPoints[0];
522+
if(isNumeric(closestVPt.x0) && isNumeric(closestVPt.y0)) {
523+
tmpPoint = fillSpikePoint(closestVPt);
524+
if(!spikePoints.vLinePoint || (spikePoints.vLinePoint.spikeDistance > tmpPoint.spikeDistance)) {
525+
spikePoints.vLinePoint = tmpPoint;
526+
}
525527
}
526528
}
527-
}
528529

529-
var closestHPoints = closestPoints.filter(function(point) {
530-
return point.ya.showspikes;
531-
});
532-
if(closestHPoints.length) {
533-
var closestHPt = closestHPoints[0];
534-
if(isNumeric(closestHPt.x0) && isNumeric(closestHPt.y0)) {
535-
tmpPoint = fillSpikePoint(closestHPt);
536-
if(!spikePoints.hLinePoint || (spikePoints.hLinePoint.spikeDistance > tmpPoint.spikeDistance)) {
537-
spikePoints.hLinePoint = tmpPoint;
530+
var closestHPoints = closestPoints.filter(function(point) {
531+
return point.ya.showspikes;
532+
});
533+
if(closestHPoints.length) {
534+
var closestHPt = closestHPoints[0];
535+
if(isNumeric(closestHPt.x0) && isNumeric(closestHPt.y0)) {
536+
tmpPoint = fillSpikePoint(closestHPt);
537+
if(!spikePoints.hLinePoint || (spikePoints.hLinePoint.spikeDistance > tmpPoint.spikeDistance)) {
538+
spikePoints.hLinePoint = tmpPoint;
539+
}
538540
}
539541
}
540542
}
@@ -543,6 +545,8 @@ function _hover(gd, evt, subplot, noHoverEvent) {
543545
}
544546
}
545547

548+
findHoverPoints();
549+
546550
function selectClosestPoint(pointsData, spikedistance) {
547551
var resultPoint = null;
548552
var minDistance = Infinity;

0 commit comments

Comments
 (0)