-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Pie aggregation and event cleanup #2117
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
Changes from 1 commit
679ed9c
ce8946c
d2756f1
ebc4d8b
5d0f3e2
e08e37a
4ba0249
ee1f8c4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -100,22 +100,58 @@ exports.appendArrayPointValue = function(pointData, trace, pointNumber) { | |
|
||
for(var i = 0; i < arrayAttrs.length; i++) { | ||
var astr = arrayAttrs[i]; | ||
var key; | ||
var key = getPointKey(astr); | ||
|
||
if(astr === 'ids') key = 'id'; | ||
else if(astr === 'locations') key = 'location'; | ||
else key = astr; | ||
if(pointData[key] === undefined) { | ||
var val = Lib.nestedProperty(trace, astr).get(); | ||
var pointVal = getPointData(val, pointNumber); | ||
|
||
if(pointVal !== undefined) pointData[key] = pointVal; | ||
} | ||
} | ||
}; | ||
|
||
exports.appendArrayPointValues = function(pointData, trace, pointNumbers) { | ||
var arrayAttrs = trace._arrayAttrs; | ||
|
||
if(!arrayAttrs) { | ||
return; | ||
} | ||
|
||
for(var i = 0; i < arrayAttrs.length; i++) { | ||
var astr = arrayAttrs[i]; | ||
var key = getPointKey(astr); | ||
|
||
if(pointData[key] === undefined) { | ||
var val = Lib.nestedProperty(trace, astr).get(); | ||
var keyVal = new Array(pointNumbers.length); | ||
|
||
if(Array.isArray(pointNumber)) { | ||
if(Array.isArray(val) && Array.isArray(val[pointNumber[0]])) { | ||
pointData[key] = val[pointNumber[0]][pointNumber[1]]; | ||
} | ||
} else { | ||
pointData[key] = val[pointNumber]; | ||
for(var j = 0; j < pointNumbers.length; j++) { | ||
keyVal[j] = getPointData(val, pointNumbers[j]); | ||
} | ||
pointData[key] = keyVal; | ||
} | ||
} | ||
}; | ||
|
||
var pointKeyMap = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ✨ at some point we might want to move this to the attribute declarations. |
||
ids: 'id', | ||
locations: 'location', | ||
labels: 'label', | ||
values: 'value', | ||
'marker.colors': 'color' | ||
}; | ||
|
||
function getPointKey(astr) { | ||
return pointKeyMap[astr] || astr; | ||
} | ||
|
||
function getPointData(val, pointNumber) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This thing is very similar to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the multipoint case it's nice to keep the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, it might be nice to move |
||
if(Array.isArray(pointNumber)) { | ||
if(Array.isArray(val) && Array.isArray(val[pointNumber[0]])) { | ||
return val[pointNumber[0]][pointNumber[1]]; | ||
} | ||
} else { | ||
return val[pointNumber]; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -155,7 +155,7 @@ exports.loneHover = function loneHover(hoverItem, opts) { | |
|
||
// The actual implementation is here: | ||
function _hover(gd, evt, subplot, noHoverEvent) { | ||
if((subplot === 'pie' || subplot === 'sankey') && !noHoverEvent) { | ||
if(subplot === 'sankey' && !noHoverEvent) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I couldn't see any purpose to having pie call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. simplified sankey -> e08e37a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. e08e37a is very nice. 👌 |
||
gd.emit('plotly_hover', { | ||
event: evt.originalEvent, | ||
points: [evt] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/** | ||
* Copyright 2012-2017, Plotly, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
|
||
'use strict'; | ||
|
||
var appendArrayPointValues = require('../../components/fx/helpers').appendArrayPointValues; | ||
|
||
|
||
// Note: like other eventData routines, this creates the data for hover/unhover/click events | ||
// but it has a different API and goes through a totally different pathway. | ||
// So to ensure it doesn't get misused, it's not attached to the Pie module. | ||
module.exports = function eventData(pt, trace) { | ||
var out = { | ||
curveNumber: trace.index, | ||
pointNumbers: pt.pts, | ||
data: trace._input, | ||
fullData: trace, | ||
label: pt.label, | ||
color: pt.color, | ||
value: pt.v, | ||
|
||
// pt.v (and pt.i below) for backward compatibility | ||
v: pt.v | ||
}; | ||
|
||
// Only include pointNumber if it's unambiguous | ||
if(pt.pts.length === 1) out.pointNumber = out.i = pt.pts[0]; | ||
|
||
// Add extra data arrays to the output | ||
// notice that this is the multi-point version ('s' on the end!) | ||
// so added data will be arrays matching the pointNumbers array. | ||
appendArrayPointValues(out, trace, pt.pts); | ||
|
||
return out; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ var Drawing = require('../../components/drawing'); | |
var svgTextUtils = require('../../lib/svg_text_utils'); | ||
|
||
var helpers = require('./helpers'); | ||
var eventData = require('./event_data'); | ||
|
||
module.exports = function plot(gd, cdpie) { | ||
var fullLayout = gd._fullLayout; | ||
|
@@ -69,15 +70,23 @@ module.exports = function plot(gd, cdpie) { | |
var cy = cd0.cy; | ||
var sliceTop = d3.select(this); | ||
var slicePath = sliceTop.selectAll('path.surface').data([pt]); | ||
var hasHoverData = false; | ||
|
||
function handleMouseOver(evt) { | ||
evt.originalEvent = d3.event; | ||
// hover state vars | ||
// have we drawn a hover label, so it should be cleared later | ||
var hasHoverLabel = false; | ||
// have we emitted a hover event, so later an unhover event should be emitted | ||
// note that click events do not depend on this - you can still get them | ||
// with hovermode: false or if you were earlier dragging, then clicked | ||
// in the same slice that you moused up in | ||
var hasHoverEvent = false; | ||
|
||
function handleMouseOver() { | ||
// in case fullLayout or fullData has changed without a replot | ||
var fullLayout2 = gd._fullLayout; | ||
var trace2 = gd._fullData[trace.index]; | ||
|
||
if(gd._dragging || fullLayout2.hovermode === false) return; | ||
|
||
var hoverinfo = trace2.hoverinfo; | ||
if(Array.isArray(hoverinfo)) { | ||
// super hacky: we need to pull out the *first* hoverinfo from | ||
|
@@ -95,68 +104,78 @@ module.exports = function plot(gd, cdpie) { | |
|
||
// in case we dragged over the pie from another subplot, | ||
// or if hover is turned off | ||
if(gd._dragging || fullLayout2.hovermode === false || | ||
hoverinfo === 'none' || hoverinfo === 'skip' || !hoverinfo) { | ||
Fx.hover(gd, evt, 'pie'); | ||
return; | ||
} | ||
|
||
var rInscribed = getInscribedRadiusFraction(pt, cd0); | ||
var hoverCenterX = cx + pt.pxmid[0] * (1 - rInscribed); | ||
var hoverCenterY = cy + pt.pxmid[1] * (1 - rInscribed); | ||
var separators = fullLayout.separators; | ||
var thisText = []; | ||
if(hoverinfo !== 'none' && hoverinfo !== 'skip' && hoverinfo) { | ||
var rInscribed = getInscribedRadiusFraction(pt, cd0); | ||
var hoverCenterX = cx + pt.pxmid[0] * (1 - rInscribed); | ||
var hoverCenterY = cy + pt.pxmid[1] * (1 - rInscribed); | ||
var separators = fullLayout.separators; | ||
var thisText = []; | ||
|
||
if(hoverinfo.indexOf('label') !== -1) thisText.push(pt.label); | ||
if(hoverinfo.indexOf('text') !== -1) { | ||
var texti = helpers.castOption(trace2.hovertext || trace2.text, pt.pts); | ||
if(texti) thisText.push(texti); | ||
} | ||
if(hoverinfo.indexOf('value') !== -1) thisText.push(helpers.formatPieValue(pt.v, separators)); | ||
if(hoverinfo.indexOf('percent') !== -1) thisText.push(helpers.formatPiePercent(pt.v / cd0.vTotal, separators)); | ||
|
||
var hoverLabel = trace.hoverlabel; | ||
var hoverFont = hoverLabel.font; | ||
|
||
Fx.loneHover({ | ||
x0: hoverCenterX - rInscribed * cd0.r, | ||
x1: hoverCenterX + rInscribed * cd0.r, | ||
y: hoverCenterY, | ||
text: thisText.join('<br>'), | ||
name: hoverinfo.indexOf('name') !== -1 ? trace2.name : undefined, | ||
idealAlign: pt.pxmid[0] < 0 ? 'left' : 'right', | ||
color: helpers.castOption(hoverLabel.bgcolor, pt.pts) || pt.color, | ||
borderColor: helpers.castOption(hoverLabel.bordercolor, pt.pts), | ||
fontFamily: helpers.castOption(hoverFont.family, pt.pts), | ||
fontSize: helpers.castOption(hoverFont.size, pt.pts), | ||
fontColor: helpers.castOption(hoverFont.color, pt.pts) | ||
}, { | ||
container: fullLayout2._hoverlayer.node(), | ||
outerContainer: fullLayout2._paper.node(), | ||
gd: gd | ||
}); | ||
|
||
if(hoverinfo.indexOf('label') !== -1) thisText.push(pt.label); | ||
if(hoverinfo.indexOf('text') !== -1) { | ||
var texti = helpers.castOption(trace2.hovertext || trace2.text, pt.pts); | ||
if(texti) thisText.push(texti); | ||
hasHoverLabel = true; | ||
} | ||
if(hoverinfo.indexOf('value') !== -1) thisText.push(helpers.formatPieValue(pt.v, separators)); | ||
if(hoverinfo.indexOf('percent') !== -1) thisText.push(helpers.formatPiePercent(pt.v / cd0.vTotal, separators)); | ||
|
||
var hoverLabel = trace.hoverlabel; | ||
var hoverFont = hoverLabel.font; | ||
|
||
Fx.loneHover({ | ||
x0: hoverCenterX - rInscribed * cd0.r, | ||
x1: hoverCenterX + rInscribed * cd0.r, | ||
y: hoverCenterY, | ||
text: thisText.join('<br>'), | ||
name: hoverinfo.indexOf('name') !== -1 ? trace2.name : undefined, | ||
idealAlign: pt.pxmid[0] < 0 ? 'left' : 'right', | ||
color: helpers.castOption(hoverLabel.bgcolor, pt.pts) || pt.color, | ||
borderColor: helpers.castOption(hoverLabel.bordercolor, pt.pts), | ||
fontFamily: helpers.castOption(hoverFont.family, pt.pts), | ||
fontSize: helpers.castOption(hoverFont.size, pt.pts), | ||
fontColor: helpers.castOption(hoverFont.color, pt.pts) | ||
}, { | ||
container: fullLayout2._hoverlayer.node(), | ||
outerContainer: fullLayout2._paper.node(), | ||
gd: gd | ||
}); | ||
|
||
Fx.hover(gd, evt, 'pie'); | ||
|
||
hasHoverData = true; | ||
gd.emit('plotly_hover', { | ||
points: [eventData(pt, trace2)], | ||
event: d3.event | ||
}); | ||
hasHoverEvent = true; | ||
} | ||
|
||
function handleMouseOut(evt) { | ||
evt.originalEvent = d3.event; | ||
gd.emit('plotly_unhover', { | ||
event: d3.event, | ||
points: [evt] | ||
}); | ||
var fullLayout2 = gd._fullLayout; | ||
var trace2 = gd._fullData[trace.index]; | ||
|
||
if(hasHoverEvent) { | ||
evt.originalEvent = d3.event; | ||
gd.emit('plotly_unhover', { | ||
points: [eventData(pt, trace2)], | ||
event: d3.event | ||
}); | ||
hasHoverEvent = false; | ||
} | ||
|
||
if(hasHoverData) { | ||
Fx.loneUnhover(fullLayout._hoverlayer.node()); | ||
hasHoverData = false; | ||
if(hasHoverLabel) { | ||
Fx.loneUnhover(fullLayout2._hoverlayer.node()); | ||
hasHoverLabel = false; | ||
} | ||
} | ||
|
||
function handleClick() { | ||
gd._hoverdata = [pt]; | ||
gd._hoverdata.trace = cd0.trace; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We probably didn't mean to attach There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wow. Brutal. Good catch ⚾ |
||
var fullLayout2 = gd._fullLayout; | ||
var trace2 = gd._fullData[trace.index]; | ||
|
||
if(gd._dragging || fullLayout2.hovermode === false) return; | ||
|
||
gd._hoverdata = [eventData(pt, trace2)]; | ||
Fx.click(gd, d3.event); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe
appendArrayMultiPointValue
orappendArrayMultiPointValues
would more typo-proof.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... and please add jsDOC⤴️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good call on
appendArrayMultiPointValues
-> with docs in4ba0249