Skip to content

Commit 4c4503f

Browse files
authored
Merge pull request #1379 from plotly/add-extra-data-to-scatter-points
Pass customdata through to scatter calcdata
2 parents 8269ea0 + c16cbfb commit 4c4503f

File tree

7 files changed

+80
-5
lines changed

7 files changed

+80
-5
lines changed

src/traces/scatter/arrays_to_calcdata.js

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ var Lib = require('../../lib');
1616
module.exports = function arraysToCalcdata(cd, trace) {
1717

1818
Lib.mergeArray(trace.text, cd, 'tx');
19+
Lib.mergeArray(trace.customdata, cd, 'data');
1920
Lib.mergeArray(trace.textposition, cd, 'tp');
2021
if(trace.textfont) {
2122
Lib.mergeArray(trace.textfont.size, cd, 'ts');

src/traces/scatter/attributes.js

+4
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ module.exports = {
5656
'where `y0` is the starting coordinate and `dy` the step.'
5757
].join(' ')
5858
},
59+
customdata: {
60+
valType: 'data_array',
61+
description: 'Assigns extra data to each scatter point DOM element'
62+
},
5963
dy: {
6064
valType: 'number',
6165
dflt: 1,

src/traces/scatter/defaults.js

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
3636
return;
3737
}
3838

39+
coerce('customdata');
3940
coerce('text');
4041
coerce('mode', defaultMode);
4142
coerce('ids');

src/traces/scatter/plot.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -428,9 +428,14 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
428428
}
429429

430430
join.each(function(d) {
431-
var sel = transition(d3.select(this));
431+
var el = d3.select(this);
432+
var sel = transition(el);
432433
Drawing.translatePoint(d, sel, xa, ya);
433434
Drawing.singlePointStyle(d, sel, trace);
435+
436+
if(trace.customdata) {
437+
el.classed('plotly-customdata', d.data !== null && d.data !== undefined);
438+
}
434439
});
435440

436441
if(hasTransition) {

src/traces/scatter/style.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,14 @@ module.exports = function style(gd) {
2424

2525
s.selectAll('g.points')
2626
.each(function(d) {
27-
d3.select(this).selectAll('path.point')
28-
.call(Drawing.pointStyle, d.trace || d[0].trace);
29-
d3.select(this).selectAll('text')
30-
.call(Drawing.textPointStyle, d.trace || d[0].trace);
27+
var el = d3.select(this);
28+
var pts = el.selectAll('path.point');
29+
var trace = d.trace || d[0].trace;
30+
31+
pts.call(Drawing.pointStyle, trace);
32+
33+
el.selectAll('text')
34+
.call(Drawing.textPointStyle, trace);
3135
});
3236

3337
s.selectAll('g.trace path.js-line')

test/jasmine/tests/calcdata_test.js

+14
Original file line numberDiff line numberDiff line change
@@ -862,4 +862,18 @@ describe('calculated data and points', function() {
862862
});
863863
});
864864
});
865+
866+
describe('customdata', function() {
867+
it('should pass customdata to the calcdata points', function() {
868+
Plotly.plot(gd, [{
869+
x: [0, 1, 3],
870+
y: [4, 5, 7],
871+
customdata: ['a', 'b', {foo: 'bar'}]
872+
}], {});
873+
874+
expect(gd.calcdata[0][0]).toEqual(jasmine.objectContaining({data: 'a'}));
875+
expect(gd.calcdata[0][1]).toEqual(jasmine.objectContaining({data: 'b'}));
876+
expect(gd.calcdata[0][2]).toEqual(jasmine.objectContaining({data: {foo: 'bar'}}));
877+
});
878+
});
865879
});

test/jasmine/tests/scatter_test.js

+46
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1+
var d3 = require('d3');
12
var Scatter = require('@src/traces/scatter');
23
var makeBubbleSizeFn = require('@src/traces/scatter/make_bubble_size_func');
34
var linePoints = require('@src/traces/scatter/line_points');
45
var Lib = require('@src/lib');
56

7+
var Plotly = require('@lib/index');
8+
var createGraphDiv = require('../assets/create_graph_div');
9+
var destroyGraphDiv = require('../assets/destroy_graph_div');
10+
var fail = require('../assets/fail_test');
11+
612
describe('Test scatter', function() {
713
'use strict';
814

@@ -326,3 +332,43 @@ describe('Test scatter', function() {
326332
});
327333

328334
});
335+
336+
describe('end-to-end scatter tests', function() {
337+
var gd;
338+
339+
beforeEach(function() {
340+
gd = createGraphDiv();
341+
});
342+
343+
afterEach(destroyGraphDiv);
344+
345+
it('should add a plotly-customdata class to points with custom data', function(done) {
346+
Plotly.plot(gd, [{
347+
x: [1, 2, 3, 4, 5, 6, 7],
348+
y: [2, 3, 4, 5, 6, 7, 8],
349+
customdata: [null, undefined, 0, false, {foo: 'bar'}, 'a']
350+
}]).then(function() {
351+
var points = d3.selectAll('g.scatterlayer').selectAll('.point');
352+
353+
// Rather than just duplicating the logic, let's be explicit about
354+
// what's expected. Specifially, only null and undefined (the default)
355+
// do *not* add the class.
356+
var expected = [false, false, true, true, true, true, false];
357+
358+
points.each(function(cd, i) {
359+
expect(d3.select(this).classed('plotly-customdata')).toBe(expected[i]);
360+
});
361+
362+
return Plotly.animate(gd, [{
363+
data: [{customdata: []}]
364+
}], {frame: {redraw: false, duration: 0}});
365+
}).then(function() {
366+
var points = d3.selectAll('g.scatterlayer').selectAll('.point');
367+
368+
points.each(function() {
369+
expect(d3.select(this).classed('plotly-customdata')).toBe(false);
370+
});
371+
372+
}).catch(fail).then(done);
373+
});
374+
});

0 commit comments

Comments
 (0)