-
-
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 all commits
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 |
---|---|---|
|
@@ -89,7 +89,8 @@ exports.quadrature = function quadrature(dx, dy) { | |
* | ||
* @param {object} pointData : point data object (gets mutated here) | ||
* @param {object} trace : full trace object | ||
* @param {number} pointNumber : point number | ||
* @param {number|Array(number)} pointNumber : point number. May be a length-2 array | ||
* [row, col] to dig into 2D arrays | ||
*/ | ||
exports.appendArrayPointValue = function(pointData, trace, pointNumber) { | ||
var arrayAttrs = trace._arrayAttrs; | ||
|
@@ -100,22 +101,68 @@ 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; | ||
} | ||
} | ||
}; | ||
|
||
/** | ||
* Appends values inside array attributes corresponding to given point number array | ||
* For use when pointData references a plot entity that arose (or potentially arose) | ||
* from multiple points in the input data | ||
* | ||
* @param {object} pointData : point data object (gets mutated here) | ||
* @param {object} trace : full trace object | ||
* @param {Array(number)|Array(Array(number))} pointNumbers : Array of point numbers. | ||
* Each entry in the array may itself be a length-2 array [row, col] to dig into 2D arrays | ||
*/ | ||
exports.appendArrayMultiPointValues = 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 = { | ||
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 |
---|---|---|
|
@@ -19,13 +19,14 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout | |
var coerceFont = Lib.coerceFont; | ||
|
||
var vals = coerce('values'); | ||
if(!Array.isArray(vals) || !vals.length) { | ||
traceOut.visible = false; | ||
return; | ||
} | ||
|
||
var labels = coerce('labels'); | ||
if(!Array.isArray(labels)) { | ||
if(!Array.isArray(vals) || !vals.length) { | ||
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. Blocking: Would you mind locking this down in a jasmine test? 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. sure -> ee1f8c4 |
||
// must have at least one of vals or labels | ||
traceOut.visible = false; | ||
return; | ||
} | ||
|
||
coerce('label0'); | ||
coerce('dlabel'); | ||
} | ||
|
@@ -34,14 +35,10 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout | |
if(lineWidth) coerce('marker.line.color'); | ||
|
||
var colors = coerce('marker.colors'); | ||
if(!Array.isArray(colors)) traceOut.marker.colors = []; // later this will get padded with default colors | ||
if(!Array.isArray(colors)) traceOut.marker.colors = []; | ||
|
||
coerce('scalegroup'); | ||
// TODO: tilt, depth, and hole all need to be coerced to the same values within a scaleegroup | ||
// (ideally actually, depth would get set the same *after* scaling, ie the same absolute depth) | ||
// and if colors aren't specified we should match these up - potentially even if separate pies | ||
// are NOT in the same sharegroup | ||
|
||
// TODO: hole needs to be coerced to the same value within a scaleegroup | ||
|
||
var textData = coerce('text'); | ||
var textInfo = coerce('textinfo', Array.isArray(textData) ? 'text+percent' : 'percent'); | ||
|
@@ -63,14 +60,6 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout | |
coerce('domain.x'); | ||
coerce('domain.y'); | ||
|
||
// 3D attributes commented out until I finish them in a later PR | ||
// var tilt = coerce('tilt'); | ||
// if(tilt) { | ||
// coerce('tiltaxis'); | ||
// coerce('depth'); | ||
// coerce('shading'); | ||
// } | ||
|
||
coerce('hole'); | ||
|
||
coerce('sort'); | ||
|
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 appendArrayMultiPointValues = require('../../components/fx/helpers').appendArrayMultiPointValues; | ||
|
||
|
||
// 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. | ||
appendArrayMultiPointValues(out, trace, pt.pts); | ||
|
||
return out; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,3 +25,16 @@ exports.formatPieValue = function formatPieValue(v, separators) { | |
} | ||
return Lib.numSeparate(vRounded, separators); | ||
}; | ||
|
||
exports.getFirstFilled = function getFirstFilled(array, indices) { | ||
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 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. Picking the first non-empty item is fine 👍 |
||
if(!Array.isArray(array)) return; | ||
for(var i = 0; i < indices.length; i++) { | ||
var v = array[indices[i]]; | ||
if(v || v === 0) return v; | ||
} | ||
}; | ||
|
||
exports.castOption = function castOption(item, indices) { | ||
if(Array.isArray(item)) return exports.getFirstFilled(item, indices); | ||
else if(item) return item; | ||
}; |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
{ | ||
"data": [ | ||
{ | ||
"labels": [ | ||
"Alice", | ||
"Bob", | ||
"Charlie", | ||
"Charlie", | ||
"Charlie", | ||
"Alice" | ||
], | ||
"type": "pie", | ||
"domain": {"x": [0, 0.4]} | ||
}, | ||
{ | ||
"labels": [ | ||
"Alice", | ||
"Alice", | ||
"Allison", | ||
"Alys", | ||
"Elise", | ||
"Allison", | ||
"Alys", | ||
"Alys" | ||
], | ||
"values": [ | ||
10, 20, 30, 40, 50, 60, 70, 80 | ||
], | ||
"marker": {"colors": ["", "", "#ccc"]}, | ||
"type": "pie", | ||
"domain": {"x": [0.5, 1]}, | ||
"textinfo": "label+value+percent" | ||
} | ||
], | ||
"layout": { | ||
"height": 300, | ||
"width": 500 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -65,6 +65,33 @@ describe('Pie traces:', function() { | |
.catch(failTest) | ||
.then(done); | ||
}); | ||
|
||
it('can sum values or count labels', function(done) { | ||
Plotly.newPlot(gd, [{ | ||
labels: ['a', 'b', 'c', 'a', 'b', 'a'], | ||
values: [1, 2, 3, 4, 5, 6], | ||
type: 'pie', | ||
domain: {x: [0, 0.45]} | ||
}, { | ||
labels: ['d', 'e', 'f', 'd', 'e', 'd'], | ||
type: 'pie', | ||
domain: {x: [0.55, 1]} | ||
}]) | ||
.then(function() { | ||
var expected = [ | ||
[['a', 11], ['b', 7], ['c', 3]], | ||
[['d', 3], ['e', 2], ['f', 1]] | ||
]; | ||
for(var i = 0; i < 2; i++) { | ||
for(var j = 0; j < 3; j++) { | ||
expect(gd.calcdata[i][j].label).toBe(expected[i][j][0], i + ',' + j); | ||
expect(gd.calcdata[i][j].v).toBe(expected[i][j][1], i + ',' + j); | ||
} | ||
} | ||
}) | ||
.catch(failTest) | ||
.then(done); | ||
}); | ||
}); | ||
|
||
describe('pie hovering', function() { | ||
|
@@ -141,24 +168,6 @@ describe('pie hovering', function() { | |
|
||
it('should contain the correct fields', function() { | ||
|
||
/* | ||
* expected = [{ | ||
* v: 4, | ||
* label: '3', | ||
* color: '#ff7f0e', | ||
* i: 3, | ||
* hidden: false, | ||
* text: '26.7%', | ||
* px1: [0,-60], | ||
* pxmid: [-44.588689528643656,-40.14783638153149], | ||
* midangle: -0.8377580409572781, | ||
* px0: [-59.67131372209641,6.2717077960592], | ||
* largeArc: 0, | ||
* cxFinal: 200, | ||
* cyFinal: 160, | ||
* originalEvent: MouseEvent | ||
* }]; | ||
*/ | ||
var hoverData, | ||
unhoverData; | ||
|
||
|
@@ -178,19 +187,17 @@ describe('pie hovering', function() { | |
expect(unhoverData.points.length).toEqual(1); | ||
|
||
var fields = [ | ||
'v', 'label', 'color', 'i', 'hidden', | ||
'text', 'px1', 'pxmid', 'midangle', | ||
'px0', 'largeArc', | ||
'pointNumber', 'curveNumber', | ||
'cxFinal', 'cyFinal', | ||
'originalEvent' | ||
'curveNumber', 'pointNumber', 'pointNumbers', | ||
'data', 'fullData', | ||
'label', 'color', 'value', | ||
'i', 'v' | ||
]; | ||
|
||
expect(Object.keys(hoverData.points[0])).toEqual(fields); | ||
expect(hoverData.points[0].i).toEqual(3); | ||
expect(Object.keys(hoverData.points[0]).sort()).toEqual(fields.sort()); | ||
expect(hoverData.points[0].pointNumber).toEqual(3); | ||
|
||
expect(Object.keys(unhoverData.points[0])).toEqual(fields); | ||
expect(unhoverData.points[0].i).toEqual(3); | ||
expect(Object.keys(unhoverData.points[0]).sort()).toEqual(fields.sort()); | ||
expect(unhoverData.points[0].pointNumber).toEqual(3); | ||
}); | ||
|
||
it('should fire hover event when moving from one slice to another', function(done) { | ||
|
@@ -355,7 +362,7 @@ describe('pie hovering', function() { | |
}); | ||
|
||
|
||
describe('Test event property of interactions on a pie plot:', function() { | ||
describe('Test event data of interactions on a pie plot:', function() { | ||
var mock = require('@mocks/pie_simple.json'); | ||
|
||
var mockCopy, gd; | ||
|
@@ -376,10 +383,37 @@ describe('Test event property of interactions on a pie plot:', function() { | |
beforeEach(function() { | ||
gd = createGraphDiv(); | ||
mockCopy = Lib.extendDeep({}, mock); | ||
Lib.extendFlat(mockCopy.data[0], { | ||
ids: ['marge', 'homer', 'bart', 'lisa', 'maggie'], | ||
customdata: [{1: 2}, {3: 4}, {5: 6}, {7: 8}, {9: 10}] | ||
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. Nice. I was wondering if 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. Which by the way ✅ #2048 |
||
}); | ||
}); | ||
|
||
afterEach(destroyGraphDiv); | ||
|
||
function checkEventData(data) { | ||
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. A long-overdue test abstraction. Thanks! |
||
var point = data.points[0]; | ||
|
||
expect(point.curveNumber).toBe(0); | ||
expect(point.pointNumber).toBe(4); | ||
expect(point.pointNumbers).toEqual([4]); | ||
expect(point.data).toBe(gd.data[0]); | ||
expect(point.fullData).toBe(gd._fullData[0]); | ||
expect(point.label).toBe('4'); | ||
expect(point.value).toBe(5); | ||
expect(point.color).toBe('#1f77b4'); | ||
expect(point.id).toEqual(['maggie']); | ||
expect(point.customdata).toEqual([{9: 10}]); | ||
|
||
// for backward compat - i/v to be removed at some point? | ||
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. Blocking: yeah, we should remove that in 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. commented #420 (comment) |
||
expect(point.i).toBe(point.pointNumber); | ||
expect(point.v).toBe(point.value); | ||
|
||
var evt = data.event; | ||
expect(evt.clientX).toEqual(pointPos[0], 'event.clientX'); | ||
expect(evt.clientY).toEqual(pointPos[1], 'event.clientY'); | ||
} | ||
|
||
describe('click events', function() { | ||
var futureData; | ||
|
||
|
@@ -400,43 +434,24 @@ describe('Test event property of interactions on a pie plot:', function() { | |
click(pointPos[0], pointPos[1]); | ||
expect(futureData.points.length).toEqual(1); | ||
|
||
var trace = futureData.points.trace; | ||
expect(typeof trace).toEqual(typeof {}, 'points.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.
And yet we had a test to verify that that's exactly what we did 🤔 |
||
|
||
var pt = futureData.points[0]; | ||
expect(Object.keys(pt)).toEqual(jasmine.arrayContaining([ | ||
'v', 'label', 'color', 'i', 'hidden', 'vTotal', 'text', 't', | ||
'trace', 'r', 'cx', 'cy', 'px1', 'pxmid', 'midangle', 'px0', | ||
'largeArc', 'cxFinal', 'cyFinal', | ||
'pointNumber', 'curveNumber' | ||
])); | ||
expect(Object.keys(pt).length).toBe(21); | ||
|
||
expect(typeof pt.color).toEqual(typeof '#1f77b4', 'points[0].color'); | ||
expect(pt.cx).toEqual(200, 'points[0].cx'); | ||
expect(pt.cxFinal).toEqual(200, 'points[0].cxFinal'); | ||
expect(pt.cy).toEqual(160, 'points[0].cy'); | ||
expect(pt.cyFinal).toEqual(160, 'points[0].cyFinal'); | ||
expect(pt.hidden).toEqual(false, 'points[0].hidden'); | ||
expect(pt.i).toEqual(4, 'points[0].i'); | ||
expect(pt.pointNumber).toEqual(4, 'points[0].pointNumber'); | ||
expect(pt.label).toEqual('4', 'points[0].label'); | ||
expect(pt.largeArc).toEqual(0, 'points[0].largeArc'); | ||
expect(pt.midangle).toEqual(1.0471975511965976, 'points[0].midangle'); | ||
expect(pt.px0).toEqual([0, -60], 'points[0].px0'); | ||
expect(pt.px1).toEqual([51.96152422706632, 29.999999999999986], 'points[0].px1'); | ||
expect(pt.pxmid).toEqual([51.96152422706631, -30.000000000000007], 'points[0].pxmid'); | ||
expect(pt.r).toEqual(60, 'points[0].r'); | ||
expect(typeof pt.t).toEqual(typeof {}, 'points[0].t'); | ||
expect(pt.text).toEqual('33.3%', 'points[0].text'); | ||
expect(typeof pt.trace).toEqual(typeof {}, 'points[0].trace'); | ||
expect(pt.v).toEqual(5, 'points[0].v'); | ||
expect(pt.vTotal).toEqual(15, 'points[0].vTotal'); | ||
expect(pt.curveNumber).toEqual(0, 'points[0].curveNumber'); | ||
checkEventData(futureData); | ||
}); | ||
|
||
var evt = futureData.event; | ||
expect(evt.clientX).toEqual(pointPos[0], 'event.clientX'); | ||
expect(evt.clientY).toEqual(pointPos[1], 'event.clientY'); | ||
it('should not contain pointNumber if aggregating', function() { | ||
var values = gd.data[0].values; | ||
var labels = []; | ||
for(var i = 0; i < values.length; i++) labels.push(i); | ||
Plotly.restyle(gd, { | ||
labels: [labels.concat(labels)], | ||
values: [values.concat(values)] | ||
}); | ||
|
||
click(pointPos[0], pointPos[1]); | ||
expect(futureData.points.length).toEqual(1); | ||
|
||
expect(futureData.points[0].pointNumber).toBeUndefined(); | ||
expect(futureData.points[0].i).toBeUndefined(); | ||
expect(futureData.points[0].pointNumbers).toEqual([4, 9]); | ||
}); | ||
}); | ||
|
||
|
@@ -466,42 +481,9 @@ describe('Test event property of interactions on a pie plot:', function() { | |
click(pointPos[0], pointPos[1], clickOpts); | ||
expect(futureData.points.length).toEqual(1); | ||
|
||
var trace = futureData.points.trace; | ||
expect(typeof trace).toEqual(typeof {}, 'points.trace'); | ||
|
||
var pt = futureData.points[0]; | ||
expect(Object.keys(pt)).toEqual(jasmine.arrayContaining([ | ||
'v', 'label', 'color', 'i', 'hidden', 'vTotal', 'text', 't', | ||
'trace', 'r', 'cx', 'cy', 'px1', 'pxmid', 'midangle', 'px0', | ||
'largeArc', 'cxFinal', 'cyFinal', | ||
'pointNumber', 'curveNumber' | ||
])); | ||
|
||
expect(typeof pt.color).toEqual(typeof '#1f77b4', 'points[0].color'); | ||
expect(pt.cx).toEqual(200, 'points[0].cx'); | ||
expect(pt.cxFinal).toEqual(200, 'points[0].cxFinal'); | ||
expect(pt.cy).toEqual(160, 'points[0].cy'); | ||
expect(pt.cyFinal).toEqual(160, 'points[0].cyFinal'); | ||
expect(pt.hidden).toEqual(false, 'points[0].hidden'); | ||
expect(pt.i).toEqual(4, 'points[0].i'); | ||
expect(pt.pointNumber).toEqual(4, 'points[0].pointNumber'); | ||
expect(pt.label).toEqual('4', 'points[0].label'); | ||
expect(pt.largeArc).toEqual(0, 'points[0].largeArc'); | ||
expect(pt.midangle).toEqual(1.0471975511965976, 'points[0].midangle'); | ||
expect(pt.px0).toEqual([0, -60], 'points[0].px0'); | ||
expect(pt.px1).toEqual([51.96152422706632, 29.999999999999986], 'points[0].px1'); | ||
expect(pt.pxmid).toEqual([51.96152422706631, -30.000000000000007], 'points[0].pxmid'); | ||
expect(pt.r).toEqual(60, 'points[0].r'); | ||
expect(typeof pt.t).toEqual(typeof {}, 'points[0].t'); | ||
expect(pt.text).toEqual('33.3%', 'points[0].text'); | ||
expect(typeof pt.trace).toEqual(typeof {}, 'points[0].trace'); | ||
expect(pt.v).toEqual(5, 'points[0].v'); | ||
expect(pt.vTotal).toEqual(15, 'points[0].vTotal'); | ||
expect(pt.curveNumber).toEqual(0, 'points[0].curveNumber'); | ||
checkEventData(futureData); | ||
|
||
var evt = futureData.event; | ||
expect(evt.clientX).toEqual(pointPos[0], 'event.clientX'); | ||
expect(evt.clientY).toEqual(pointPos[1], 'event.clientY'); | ||
Object.getOwnPropertyNames(clickOpts).forEach(function(opt) { | ||
expect(evt[opt]).toEqual(clickOpts[opt], 'event.' + opt); | ||
}); | ||
|
@@ -512,7 +494,8 @@ describe('Test event property of interactions on a pie plot:', function() { | |
var futureData; | ||
|
||
beforeEach(function(done) { | ||
Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); | ||
futureData = undefined; | ||
Plotly.newPlot(gd, mockCopy.data, mockCopy.layout).then(done); | ||
|
||
gd.on('plotly_hover', function(data) { | ||
futureData = data; | ||
|
@@ -522,33 +505,44 @@ describe('Test event property of interactions on a pie plot:', function() { | |
it('should contain the correct fields', function() { | ||
mouseEvent('mouseover', pointPos[0], pointPos[1]); | ||
|
||
var point0 = futureData.points[0], | ||
evt = futureData.event; | ||
expect(point0.originalEvent).toEqual(evt, 'points'); | ||
expect(evt.clientX).toEqual(pointPos[0], 'event.clientX'); | ||
expect(evt.clientY).toEqual(pointPos[1], 'event.clientY'); | ||
checkEventData(futureData); | ||
}); | ||
|
||
it('should not emit a hover if you\'re dragging', function() { | ||
gd._dragging = true; | ||
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. It occurred to me when fixing this bit of logic, it would perhaps be better to check 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. that will need a bunch more testing and ideally rolling out to all subplots at once, so I'll defer it -> #2120 |
||
mouseEvent('mouseover', pointPos[0], pointPos[1]); | ||
expect(futureData).toBeUndefined(); | ||
}); | ||
|
||
it('should not emit a hover if hover is disabled', function() { | ||
Plotly.relayout(gd, 'hovermode', false); | ||
mouseEvent('mouseover', pointPos[0], pointPos[1]); | ||
expect(futureData).toBeUndefined(); | ||
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 is also different from before, but consistent with other subplot types, I believe. 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. Yes this is how it should be. For the record, to get hover event data w/o visible hover labels, one should set |
||
}); | ||
}); | ||
|
||
describe('unhover events', function() { | ||
var futureData; | ||
|
||
beforeEach(function(done) { | ||
Plotly.plot(gd, mockCopy.data, mockCopy.layout).then(done); | ||
futureData = undefined; | ||
Plotly.newPlot(gd, mockCopy.data, mockCopy.layout).then(done); | ||
|
||
gd.on('plotly_unhover', function(data) { | ||
futureData = data; | ||
}); | ||
}); | ||
|
||
it('should contain the correct fields', function() { | ||
mouseEvent('mouseover', pointPos[0], pointPos[1]); | ||
mouseEvent('mouseout', pointPos[0], pointPos[1]); | ||
|
||
var point0 = futureData.points[0], | ||
evt = futureData.event; | ||
expect(point0.originalEvent).toEqual(evt, 'points'); | ||
expect(evt.clientX).toEqual(pointPos[0], 'event.clientX'); | ||
expect(evt.clientY).toEqual(pointPos[1], 'event.clientY'); | ||
checkEventData(futureData); | ||
}); | ||
|
||
it('should not emit an unhover if you didn\'t first hover', function() { | ||
mouseEvent('mouseout', pointPos[0], pointPos[1]); | ||
expect(futureData).toBeUndefined(); | ||
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. kind of a weird one... but lets say you dragged over the pie from another subplot, so there was no hover event - you shouldn't get an unhover event even if you mouse up and then mouse out of that slice. |
||
}); | ||
}); | ||
}); |
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.
✨ at some point we might want to move this to the attribute declarations.