Skip to content

Commit e397429

Browse files
authored
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
});

0 commit comments

Comments
 (0)