Skip to content

Commit e397429

Browse files
authoredOct 24, 2016
Merge pull request #1062 from plotly/filter-fixes
Filter fixes
2 parents e1d440d + 14fd327 commit e397429

File tree

10 files changed

+253
-86
lines changed

10 files changed

+253
-86
lines changed
 

‎src/lib/coerce.js

+11
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,17 @@ exports.findArrayAttributes = function(trace) {
458458

459459
exports.crawl(trace._module.attributes, callback);
460460

461+
if(trace.transforms) {
462+
var transforms = trace.transforms;
463+
464+
for(var i = 0; i < transforms.length; i++) {
465+
var transform = transforms[i];
466+
467+
stack = ['transforms[' + i + ']'];
468+
exports.crawl(transform._module.attributes, callback, 1);
469+
}
470+
}
471+
461472
// Look into the fullInput module attributes for array attributes
462473
// to make sure that 'custom' array attributes are detected.
463474
//

‎src/plot_api/helpers.js

+18
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,24 @@ exports.cleanData = function(data, existingData) {
340340
}
341341
}
342342

343+
// transforms backward compatibility fixes
344+
if(Array.isArray(trace.transforms)) {
345+
var transforms = trace.transforms;
346+
347+
for(i = 0; i < transforms.length; i++) {
348+
var transform = transforms[i];
349+
350+
if(!Lib.isPlainObject(transform)) continue;
351+
352+
if(transform.type === 'filter') {
353+
if(transform.filtersrc) {
354+
transform.target = transform.filtersrc;
355+
delete transform.filtersrc;
356+
}
357+
}
358+
}
359+
}
360+
343361
// prune empty containers made before the new nestedProperty
344362
if(emptyContainer(trace, 'line')) delete trace.line;
345363
if('marker' in trace) {

‎src/plots/plots.js

+1
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,7 @@ function supplyTransformDefaults(traceIn, traceOut, layout) {
807807
if(_module && _module.supplyDefaults) {
808808
transformOut = _module.supplyDefaults(transformIn, traceOut, layout, traceIn);
809809
transformOut.type = type;
810+
transformOut._module = _module;
810811
}
811812
else {
812813
transformOut = Lib.extendFlat({}, transformIn);

‎src/transforms/filter.js

+52-22
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
var Lib = require('../lib');
1212
var axisIds = require('../plots/cartesian/axis_ids');
13+
var autoType = require('../plots/cartesian/axis_autotype');
14+
var setConvert = require('../plots/cartesian/set_convert');
1315

1416
var INEQUALITY_OPS = ['=', '<', '>=', '>', '<='];
1517
var INTERVAL_OPS = ['[]', '()', '[)', '(]', '][', ')(', '](', ')['];
@@ -27,18 +29,22 @@ exports.attributes = {
2729
'Determines whether this filter transform is enabled or disabled.'
2830
].join(' ')
2931
},
30-
filtersrc: {
32+
target: {
3133
valType: 'string',
3234
strict: true,
3335
noBlank: true,
36+
arrayOk: true,
3437
dflt: 'x',
3538
description: [
36-
'Sets the variable in the parent trace object',
37-
'by which the filter will be applied.',
39+
'Sets the filter target by which the filter is applied.',
3840

41+
'If a string, *target* is assumed to be a reference to a data array',
42+
'in the parent trace object.',
3943
'To filter about nested variables, use *.* to access them.',
40-
'For example, set `filtersrc` to *marker.color* to filter',
41-
'about the marker color array.'
44+
'For example, set `target` to *marker.color* to filter',
45+
'about the marker color array.',
46+
47+
'If an array, *target* is then the data array by which the filter is applied.'
4248
].join(' ')
4349
},
4450
operation: {
@@ -77,7 +83,7 @@ exports.attributes = {
7783
'Sets the value or values by which to filter by.',
7884

7985
'Values are expected to be in the same type as the data linked',
80-
'to *filtersrc*.',
86+
'to *target*.',
8187

8288
'When `operation` is set to one of the inequality values',
8389
'(' + INEQUALITY_OPS + ')',
@@ -108,25 +114,24 @@ exports.supplyDefaults = function(transformIn) {
108114
if(enabled) {
109115
coerce('operation');
110116
coerce('value');
111-
coerce('filtersrc');
117+
coerce('target');
112118
}
113119

114120
return transformOut;
115121
};
116122

117123
exports.calcTransform = function(gd, trace, opts) {
118-
var filtersrc = opts.filtersrc,
119-
filtersrcOk = filtersrc && Array.isArray(Lib.nestedProperty(trace, filtersrc).get());
120-
121-
if(!opts.enabled || !filtersrcOk) return;
124+
if(!opts.enabled) return;
122125

123-
var dataToCoord = getDataToCoordFunc(gd, trace, filtersrc),
124-
filterFunc = getFilterFunc(opts, dataToCoord);
126+
var target = opts.target,
127+
filterArray = getFilterArray(trace, target),
128+
len = filterArray.length;
125129

126-
var filterArr = Lib.nestedProperty(trace, filtersrc).get(),
127-
len = filterArr.length;
130+
if(!len) return;
128131

129-
var arrayAttrs = Lib.findArrayAttributes(trace),
132+
var dataToCoord = getDataToCoordFunc(gd, trace, target),
133+
filterFunc = getFilterFunc(opts, dataToCoord),
134+
arrayAttrs = Lib.findArrayAttributes(trace),
130135
originalArrays = {};
131136

132137
// copy all original array attribute values,
@@ -147,7 +152,7 @@ exports.calcTransform = function(gd, trace, opts) {
147152
}
148153

149154
for(var i = 0; i < len; i++) {
150-
var v = filterArr[i];
155+
var v = filterArray[i];
151156

152157
if(!filterFunc(v)) continue;
153158

@@ -157,18 +162,43 @@ exports.calcTransform = function(gd, trace, opts) {
157162
}
158163
};
159164

160-
function getDataToCoordFunc(gd, trace, filtersrc) {
161-
var ax = axisIds.getFromTrace(gd, trace, filtersrc);
165+
function getFilterArray(trace, target) {
166+
if(typeof target === 'string' && target) {
167+
var array = Lib.nestedProperty(trace, target).get();
168+
169+
return Array.isArray(array) ? array : [];
170+
}
171+
else if(Array.isArray(target)) return target.slice();
172+
173+
return false;
174+
}
175+
176+
function getDataToCoordFunc(gd, trace, target) {
177+
var ax;
178+
179+
// In the case of an array target, make a mock data array
180+
// and call supplyDefaults to the data type and
181+
// setup the data-to-calc method.
182+
if(Array.isArray(target)) {
183+
ax = {
184+
type: autoType(target),
185+
_categories: []
186+
};
187+
setConvert(ax);
188+
}
189+
else {
190+
ax = axisIds.getFromTrace(gd, trace, target);
191+
}
162192

163-
// if 'filtersrc' has corresponding axis
193+
// if 'target' has corresponding axis
164194
// -> use setConvert method
165195
if(ax) return ax.d2c;
166196

167197
// special case for 'ids'
168198
// -> cast to String
169-
if(filtersrc === 'ids') return function(v) { return String(v); };
199+
if(target === 'ids') return function(v) { return String(v); };
170200

171-
// otherwise
201+
// otherwise (e.g. numeric-array of 'marker.color' or 'marker.size')
172202
// -> cast to Number
173203
return function(v) { return +v; };
174204
}

‎test/jasmine/tests/finance_test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ describe('finance charts calc transforms:', function() {
423423
transforms: [{
424424
type: 'filter',
425425
operation: '>',
426-
filtersrc: 'open',
426+
target: 'open',
427427
value: 33
428428
}]
429429
});
@@ -433,7 +433,7 @@ describe('finance charts calc transforms:', function() {
433433
transforms: [{
434434
type: 'filter',
435435
operation: '{}',
436-
filtersrc: 'x',
436+
target: 'x',
437437
value: ['2016-09-01', '2016-09-10']
438438
}]
439439
});

‎test/jasmine/tests/plot_api_test.js

+29
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,35 @@ describe('Test plot api', function() {
995995

996996
expect(gd.data[1].contours).toBeUndefined();
997997
});
998+
999+
it('should rename *filtersrc* to *target* in filter transforms', function() {
1000+
var data = [{
1001+
transforms: [{
1002+
type: 'filter',
1003+
filtersrc: 'y'
1004+
}, {
1005+
type: 'filter',
1006+
operation: '<'
1007+
}]
1008+
}, {
1009+
transforms: [{
1010+
type: 'filter',
1011+
target: 'y'
1012+
}]
1013+
}];
1014+
1015+
Plotly.plot(gd, data);
1016+
1017+
var trace0 = gd.data[0],
1018+
trace1 = gd.data[1];
1019+
1020+
expect(trace0.transforms.length).toEqual(2);
1021+
expect(trace0.transforms[0].filtersrc).toBeUndefined();
1022+
expect(trace0.transforms[0].target).toEqual('y');
1023+
1024+
expect(trace1.transforms.length).toEqual(1);
1025+
expect(trace1.transforms[0].target).toEqual('y');
1026+
});
9981027
});
9991028

10001029
describe('Plotly.update should', function() {

‎test/jasmine/tests/plotschema_test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ describe('plot schema', function() {
176176
var valObjects = plotSchema.transforms.filter.attributes,
177177
attrNames = Object.keys(valObjects);
178178

179-
['operation', 'value', 'filtersrc'].forEach(function(k) {
179+
['operation', 'value', 'target'].forEach(function(k) {
180180
expect(attrNames).toContain(k);
181181
});
182182
});

‎test/jasmine/tests/transform_filter_test.js

+116-45
Large diffs are not rendered by default.

‎test/jasmine/tests/transform_multi_test.js

+16-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
var Plotly = require('@lib/index');
2+
var Filter = require('@lib/filter');
3+
24
var Plots = require('@src/plots/plots');
35
var Lib = require('@src/lib');
46

@@ -26,7 +28,8 @@ describe('general transforms:', function() {
2628
enabled: true,
2729
operation: '=',
2830
value: 0,
29-
filtersrc: 'x'
31+
target: 'x',
32+
_module: Filter
3033
}]);
3134
});
3235

@@ -48,7 +51,7 @@ describe('general transforms:', function() {
4851
type: 'filter',
4952
operation: '>',
5053
value: 0,
51-
filtersrc: 'x'
54+
target: 'x'
5255
}]
5356
};
5457

@@ -65,15 +68,17 @@ describe('general transforms:', function() {
6568
enabled: true,
6669
operation: '=',
6770
value: 0,
68-
filtersrc: 'x'
71+
target: 'x',
72+
_module: Filter
6973
}, '- global first');
7074

7175
expect(traceOut.transforms[1]).toEqual({
7276
type: 'filter',
7377
enabled: true,
7478
operation: '>',
7579
value: 0,
76-
filtersrc: 'x'
80+
target: 'x',
81+
_module: Filter
7782
}, '- trace second');
7883
});
7984

@@ -88,7 +93,7 @@ describe('general transforms:', function() {
8893
type: 'filter',
8994
operation: '>',
9095
value: 0,
91-
filtersrc: 'x'
96+
target: 'x'
9297
}]
9398
}];
9499

@@ -104,7 +109,7 @@ describe('general transforms:', function() {
104109
type: 'filter',
105110
operation: '>',
106111
value: 0,
107-
filtersrc: 'x'
112+
target: 'x'
108113
}], msg);
109114

110115
msg = 'supplying the transform defaults';
@@ -113,7 +118,8 @@ describe('general transforms:', function() {
113118
enabled: true,
114119
operation: '>',
115120
value: 0,
116-
filtersrc: 'x'
121+
target: 'x',
122+
_module: Filter
117123
}, msg);
118124

119125
msg = 'keeping refs to user data';
@@ -123,7 +129,7 @@ describe('general transforms:', function() {
123129
type: 'filter',
124130
operation: '>',
125131
value: 0,
126-
filtersrc: 'x'
132+
target: 'x',
127133
}], msg);
128134

129135
msg = 'keeping refs to full transforms array';
@@ -132,7 +138,8 @@ describe('general transforms:', function() {
132138
enabled: true,
133139
operation: '>',
134140
value: 0,
135-
filtersrc: 'x'
141+
target: 'x',
142+
_module: Filter
136143
}], msg);
137144

138145
msg = 'setting index w.r.t user data';

‎test/jasmine/tests/transition_test.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,17 @@ function runTests(transitionDuration) {
7171
enabled: true,
7272
type: 'filter',
7373
operation: '<',
74-
filtersrc: 'x',
74+
target: 'x',
7575
value: 10
7676
}
7777
}, [0]).then(function() {
78-
expect(gd._fullData[0].transforms).toEqual([{
78+
expect(gd._fullData[0].transforms).toEqual([jasmine.objectContaining({
7979
enabled: true,
8080
type: 'filter',
8181
operation: '<',
82-
filtersrc: 'x',
82+
target: 'x',
8383
value: 10
84-
}]);
84+
})]);
8585

8686
return Plots.transition(gd, [{
8787
'transforms[0].operation': '>'
@@ -90,13 +90,13 @@ function runTests(transitionDuration) {
9090
{duration: transitionDuration, easing: 'cubic-in-out'}
9191
);
9292
}).then(function() {
93-
expect(gd._fullData[0].transforms).toEqual([{
93+
expect(gd._fullData[0].transforms).toEqual([jasmine.objectContaining({
9494
enabled: true,
9595
type: 'filter',
9696
operation: '>',
97-
filtersrc: 'x',
97+
target: 'x',
9898
value: 10
99-
}]);
99+
})]);
100100
}).catch(fail).then(done);
101101
});
102102

0 commit comments

Comments
 (0)
Please sign in to comment.