Skip to content

Rework transform style into array syntax #1794

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

Merged
merged 4 commits into from
Jun 16, 2017
Merged
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
41 changes: 30 additions & 11 deletions src/plot_api/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,6 @@ function cleanAxRef(container, attr) {
// Make a few changes to the data right away
// before it gets used for anything
exports.cleanData = function(data, existingData) {

// Enforce unique IDs
var suids = [], // seen uids --- so we can weed out incoming repeats
uids = data.concat(Array.isArray(existingData) ? existingData : [])
Expand Down Expand Up @@ -348,18 +347,38 @@ exports.cleanData = function(data, existingData) {

if(!Lib.isPlainObject(transform)) continue;

if(transform.type === 'filter') {
if(transform.filtersrc) {
transform.target = transform.filtersrc;
delete transform.filtersrc;
}
switch(transform.type) {
case 'filter':
if(transform.filtersrc) {
transform.target = transform.filtersrc;
delete transform.filtersrc;
}

if(transform.calendar) {
if(!transform.valuecalendar) {
transform.valuecalendar = transform.calendar;
if(transform.calendar) {
if(!transform.valuecalendar) {
transform.valuecalendar = transform.calendar;
}
delete transform.calendar;
}
break;

case 'groupby':
// Name has changed from `style` to `styles`, so use `style` but prefer `styles`:
transform.styles = transform.styles || transform.style;

if(transform.styles && !Array.isArray(transform.styles)) {
var prevStyles = transform.styles;
var styleKeys = Object.keys(prevStyles);

transform.styles = [];
for(var j = 0; j < styleKeys.length; j++) {
transform.styles.push({
target: styleKeys[j],
value: prevStyles[styleKeys[j]]
});
}
}
delete transform.calendar;
}
break;
}
}
}
Expand Down
55 changes: 41 additions & 14 deletions src/transforms/groupby.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,26 @@ exports.attributes = {
'with `x` [1, 3] and one trace with `x` [2, 4].'
].join(' ')
},
style: {
valType: 'any',
dflt: {},
description: [
'Sets each group style.',
'For example, with `groups` set to *[\'a\', \'b\', \'a\', \'b\']*',
'and `style` set to *{ a: { marker: { color: \'red\' } }}',
'marker points in group *\'a\'* will be drawn in red.'
].join(' ')
styles: {
_isLinkedToArray: 'style',
target: {
valType: 'string',
role: 'info',
description: [
'The group value which receives these styles.'
].join(' ')
},
value: {
valType: 'any',
role: 'info',
dflt: {},
description: [
'Sets each group styles.',
'For example, with `groups` set to *[\'a\', \'b\', \'a\', \'b\']*',
'and `styles` set to *[{target: \'a\', value: { marker: { color: \'red\' } }}]',
'marker points in group *\'a\'* will be drawn in red.'
].join(' ')
},
}
};

Expand Down Expand Up @@ -71,11 +82,22 @@ exports.supplyDefaults = function(transformIn) {
if(!enabled) return transformOut;

coerce('groups');
coerce('style');

var styleIn = transformIn.styles;
var styleOut = transformOut.styles = [];

if(styleIn) {
for(var i = 0; i < styleIn.length; i++) {
styleOut[i] = {};
Lib.coerce(styleIn[i], styleOut[i], exports.attributes.styles, 'target');
Lib.coerce(styleIn[i], styleOut[i], exports.attributes.styles, 'value');
}
}

return transformOut;
};


/**
* Apply transform !!!
*
Expand Down Expand Up @@ -115,6 +137,7 @@ function pasteArray(newTrace, trace, j, a) {
}

function transformOne(trace, state) {
var i;
var opts = state.transform;
var groups = trace.transforms[state.transformIndex].groups;

Expand All @@ -128,9 +151,13 @@ function transformOne(trace, state) {

var arrayAttrs = PlotSchema.findArrayAttributes(trace);

var style = opts.style || {};
var styles = opts.styles || [];
var styleLookup = {};
for(i = 0; i < styles.length; i++) {
styleLookup[styles[i].target] = styles[i].value;
}

for(var i = 0; i < groupNames.length; i++) {
for(i = 0; i < groupNames.length; i++) {
var groupName = groupNames[i];

var newTrace = newData[i] = Lib.extendDeepNoArrays({}, trace);
Expand All @@ -145,9 +172,9 @@ function transformOne(trace, state) {

newTrace.name = groupName;

// there's no need to coerce style[groupName] here
// there's no need to coerce styleLookup[groupName] here
// as another round of supplyDefaults is done on the transformed traces
newTrace = Lib.extendDeepNoArrays(newTrace, style[groupName] || {});
newTrace = Lib.extendDeepNoArrays(newTrace, styleLookup[groupName] || {});
}

return newData;
Expand Down
7 changes: 7 additions & 0 deletions test/jasmine/tests/plotschema_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,13 @@ describe('plot schema', function() {
});
});

it('should work with registered transforms (2)', function() {
var valObjects = plotSchema.transforms.groupby.attributes;
var items = valObjects.styles.items || {};

expect(Object.keys(items)).toEqual(['style']);
});

it('should work with registered components', function() {
expect(plotSchema.traces.scatter.attributes.xcalendar.valType).toEqual('enumerated');
expect(plotSchema.traces.scatter3d.attributes.zcalendar.valType).toEqual('enumerated');
Expand Down
119 changes: 100 additions & 19 deletions test/jasmine/tests/transform_groupby_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ var destroyGraphDiv = require('../assets/destroy_graph_div');
var assertDims = require('../assets/assert_dims');
var assertStyle = require('../assets/assert_style');


describe('groupby', function() {

describe('one-to-many transforms:', function() {
Expand All @@ -19,7 +18,10 @@ describe('groupby', function() {
transforms: [{
type: 'groupby',
groups: ['a', 'a', 'b', 'a', 'b', 'b', 'a'],
style: { a: {marker: {color: 'red'}}, b: {marker: {color: 'blue'}} }
styles: [
{target: 'a', value: {marker: {color: 'red'}}},
{target: 'b', value: {marker: {color: 'blue'}}}
]
}]
}];

Expand All @@ -30,7 +32,10 @@ describe('groupby', function() {
transforms: [{
type: 'groupby',
groups: ['b', 'a', 'b', 'b', 'b', 'a', 'a'],
style: { a: {marker: {color: 'green'}}, b: {marker: {color: 'black'}} }
styles: [
{target: 'a', value: {marker: {color: 'green'}}},
{target: 'b', value: {marker: {color: 'black'}}}
]
}]
}];

Expand Down Expand Up @@ -58,6 +63,58 @@ describe('groupby', function() {
});
});

it('Accepts deprecated object notation for styles', function(done) {
var oldStyleMockData = [{
mode: 'markers',
x: [1, -1, -2, 0, 1, 2, 3],
y: [1, 2, 3, 1, 2, 3, 1],
transforms: [{
type: 'groupby',
groups: ['a', 'a', 'b', 'a', 'b', 'b', 'a'],
styles: {
a: {marker: {color: 'red'}},
b: {marker: {color: 'blue'}}
}
}]
}];
var data = Lib.extendDeep([], oldStyleMockData);
data[0].marker = { size: 20 };

var gd = createGraphDiv();
var dims = [4, 3];

Plotly.plot(gd, data).then(function() {
assertStyle(dims,
['rgb(255, 0, 0)', 'rgb(0, 0, 255)'],
[1, 1]
);

return Plotly.restyle(gd, 'marker.opacity', 0.4);
}).then(function() {
assertStyle(dims,
['rgb(255, 0, 0)', 'rgb(0, 0, 255)'],
[0.4, 0.4]
);

expect(gd._fullData[0].marker.opacity).toEqual(0.4);
expect(gd._fullData[1].marker.opacity).toEqual(0.4);

return Plotly.restyle(gd, 'marker.opacity', 1);
}).then(function() {
assertStyle(dims,
['rgb(255, 0, 0)', 'rgb(0, 0, 255)'],
[1, 1]
);

expect(gd._fullData[0].marker.opacity).toEqual(1);
expect(gd._fullData[1].marker.opacity).toEqual(1);
}).then(done);

// The final test for restyle updates using deprecated syntax
// is ommitted since old style syntax is *only* sanitized on
// initial plot, *not* on restyle.
});

it('Plotly.restyle should work', function(done) {
var data = Lib.extendDeep([], mockData0);
data[0].marker = { size: 20 };
Expand Down Expand Up @@ -92,7 +149,10 @@ describe('groupby', function() {
expect(gd._fullData[1].marker.opacity).toEqual(1);

return Plotly.restyle(gd, {
'transforms[0].style': { a: {marker: {color: 'green'}}, b: {marker: {color: 'red'}} },
'transforms[0].styles': [[
{target: 'a', value: {marker: {color: 'green'}}},
{target: 'b', value: {marker: {color: 'red'}}}
]],
'marker.opacity': 0.4
});
}).then(function() {
Expand Down Expand Up @@ -192,7 +252,10 @@ describe('groupby', function() {
transforms: [{
type: 'groupby',
groups: ['a', 'a', 'b', 'a', 'b', 'b', 'a'],
style: { a: {marker: {color: 'red'}}, b: {marker: {color: 'blue'}} }
styles: [
{target: 'a', value: {marker: {color: 'red'}}},
{target: 'b', value: {marker: {color: 'blue'}}}
]
}]
}];

Expand Down Expand Up @@ -387,7 +450,10 @@ describe('groupby', function() {
transforms: [{
type: 'groupby',
groups: ['a', 'a', 'b', 'a', 'b', 'b', 'a'],
style: { a: {marker: {color: 'red'}}, b: {marker: {color: 'blue'}} }
styles: [
{target: 'a', value: {marker: {color: 'red'}}},
{target: 'b', value: {marker: {color: 'blue'}}}
]
}]
}];

Expand All @@ -401,17 +467,20 @@ describe('groupby', function() {
transforms: [{
type: 'groupby',
groups: ['a', 'a', 'b', 'a', 'b', 'b', 'a'],
style: {
a: {
styles: [{
target: 'a',
value: {
marker: {
color: 'orange',
size: 20,
line: {
color: 'red'
}
}
},
b: {
}
}, {
target: 'b',
value: {
mode: 'markers+lines', // heterogeonos attributes are OK: group 'a' doesn't need to define this
marker: {
color: 'cyan',
Expand All @@ -426,7 +495,7 @@ describe('groupby', function() {
color: 'purple'
}
}
}
}]
}]
}];

Expand All @@ -447,11 +516,14 @@ describe('groupby', function() {
transforms: [{
type: 'groupby',
groups: ['a', 'a', 'b', 'a', 'b', 'b', 'a'],
style: {
a: {marker: {size: 30}},
styles: [{
target: 'a',
value: {marker: {size: 30}}
}, {
// override general color:
b: {marker: {size: 15, line: {color: 'yellow'}}, line: {color: 'purple'}}
}
target: 'b',
value: {marker: {size: 15, line: {color: 'yellow'}}, line: {color: 'purple'}}
}]
}]
}];

Expand All @@ -464,7 +536,7 @@ describe('groupby', function() {
transforms: [{
type: 'groupby',
groups: ['a', 'a', 'b', 'a', 'b', 'b', 'a'],
style: {/* can be empty, or of partial group id coverage */}
styles: [/* can be empty, or of partial group id coverage */]
}]
}];

Expand Down Expand Up @@ -548,7 +620,10 @@ describe('groupby', function() {
transforms: [{
type: 'groupby',
// groups: ['a', 'a', 'b', 'a', 'b', 'b', 'a'],
style: { a: {marker: {color: 'red'}}, b: {marker: {color: 'blue'}} }
styles: [
{target: 'a', value: {marker: {color: 'red'}}},
{target: 'b', value: {marker: {color: 'blue'}}}
]
}]
}];

Expand All @@ -561,7 +636,10 @@ describe('groupby', function() {
transforms: [{
type: 'groupby',
groups: [],
style: { a: {marker: {color: 'red'}}, b: {marker: {color: 'blue'}} }
styles: [
{target: 'a', value: {marker: {color: 'red'}}},
{target: 'b', value: {marker: {color: 'blue'}}}
]
}]
}];

Expand All @@ -574,7 +652,10 @@ describe('groupby', function() {
transforms: [{
type: 'groupby',
groups: null,
style: { a: {marker: {color: 'red'}}, b: {marker: {color: 'blue'}} }
styles: [
{target: 'a', value: {marker: {color: 'red'}}},
{target: 'b', value: {marker: {color: 'blue'}}}
]
}]
}];

Expand Down
Loading