Skip to content

Commit 3f15c73

Browse files
committed
resolves #1178 - add preservegaps filter options
1 parent 52e9e4d commit 3f15c73

File tree

3 files changed

+72
-31
lines changed

3 files changed

+72
-31
lines changed

src/transforms/filter.js

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,17 @@ exports.attributes = {
102102
'*value* is expected to be an array with as many items as',
103103
'the desired set elements.'
104104
].join(' ')
105-
}
105+
},
106+
preservegaps: {
107+
valType: 'boolean',
108+
dflt: false,
109+
description: [
110+
'Determines whether or not gaps in data arrays produced by the filter operation',
111+
'are preserved or not.',
112+
'Setting this to *true* might be useful when plotting a line chart',
113+
'with `connectgaps` set to *true*.'
114+
].join(' ')
115+
},
106116
};
107117

108118
exports.supplyDefaults = function(transformIn) {
@@ -115,6 +125,7 @@ exports.supplyDefaults = function(transformIn) {
115125
var enabled = coerce('enabled');
116126

117127
if(enabled) {
128+
coerce('preservegaps');
118129
coerce('operation');
119130
coerce('value');
120131
coerce('target');
@@ -150,36 +161,47 @@ exports.calcTransform = function(gd, trace, opts) {
150161
var d2cTarget = (target === 'x' || target === 'y' || target === 'z') ?
151162
target : filterArray;
152163

153-
var dataToCoord = getDataToCoordFunc(gd, trace, d2cTarget),
154-
filterFunc = getFilterFunc(opts, dataToCoord, targetCalendar),
155-
arrayAttrs = PlotSchema.findArrayAttributes(trace),
156-
originalArrays = {};
157-
158-
// copy all original array attribute values,
159-
// and clear arrays in trace
160-
for(var k = 0; k < arrayAttrs.length; k++) {
161-
var attr = arrayAttrs[k],
162-
np = Lib.nestedProperty(trace, attr);
164+
var dataToCoord = getDataToCoordFunc(gd, trace, d2cTarget);
165+
var filterFunc = getFilterFunc(opts, dataToCoord, targetCalendar);
166+
var arrayAttrs = PlotSchema.findArrayAttributes(trace);
167+
var originalArrays = {};
163168

164-
originalArrays[attr] = Lib.extendDeep([], np.get());
165-
np.set([]);
169+
function forAllAttrs(fn, index) {
170+
for(var j = 0; j < arrayAttrs.length; j++) {
171+
var np = Lib.nestedProperty(trace, arrayAttrs[j]);
172+
fn(np, index);
173+
}
166174
}
167175

168-
function fill(attr, i) {
169-
var oldArr = originalArrays[attr],
170-
newArr = Lib.nestedProperty(trace, attr).get();
171-
172-
newArr.push(oldArr[i]);
176+
var initFn;
177+
var fillFn;
178+
if(opts.preservegaps) {
179+
initFn = function(np) {
180+
originalArrays[np.astr] = Lib.extendDeep([], np.get());
181+
np.set(new Array(len));
182+
};
183+
fillFn = function(np, index) {
184+
var val = originalArrays[np.astr][index];
185+
np.get()[index] = val;
186+
};
187+
} else {
188+
initFn = function(np) {
189+
originalArrays[np.astr] = Lib.extendDeep([], np.get());
190+
np.set([]);
191+
};
192+
fillFn = function(np, index) {
193+
var val = originalArrays[np.astr][index];
194+
np.get().push(val);
195+
};
173196
}
174197

175-
for(var i = 0; i < len; i++) {
176-
var v = filterArray[i];
198+
// copy all original array attribute values, and clear arrays in trace
199+
forAllAttrs(initFn);
177200

178-
if(!filterFunc(v)) continue;
179-
180-
for(var j = 0; j < arrayAttrs.length; j++) {
181-
fill(arrayAttrs[j], i);
182-
}
201+
// loop through filter array, fill trace arrays if passed
202+
for(var i = 0; i < len; i++) {
203+
var passed = filterFunc(filterArray[i]);
204+
if(passed) forAllAttrs(fillFn, i);
183205
}
184206
};
185207

test/jasmine/tests/transform_filter_test.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ describe('filter transforms defaults:', function() {
3030
expect(traceOut.transforms).toEqual([{
3131
type: 'filter',
3232
enabled: true,
33+
preservegaps: false,
3334
operation: '=',
3435
value: 0,
3536
target: 'x',
@@ -320,6 +321,22 @@ describe('filter transforms calc:', function() {
320321
expect(out[0].y).toEqual([1]);
321322
});
322323

324+
it('should preserve gaps in data when `preservegaps` is turned on', function() {
325+
var out = _transform([Lib.extendDeep({}, base, {
326+
transforms: [{
327+
type: 'filter',
328+
preservegaps: true,
329+
operation: '>',
330+
value: 0,
331+
target: 'x'
332+
}]
333+
})]);
334+
335+
expect(out[0].x).toEqual([undefined, undefined, undefined, undefined, 1, 2, 3]);
336+
expect(out[0].y).toEqual([undefined, undefined, undefined, undefined, 2, 3, 1]);
337+
expect(out[0].marker.color).toEqual([undefined, undefined, undefined, undefined, 0.2, 0.3, 0.4]);
338+
});
339+
323340
describe('filters should handle numeric values', function() {
324341
var _base = Lib.extendDeep({}, base);
325342

test/jasmine/tests/transform_multi_test.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ describe('general transforms:', function() {
3131
operation: '=',
3232
value: 0,
3333
target: 'x',
34+
preservegaps: false,
3435
_module: Filter
3536
}]);
3637
});
@@ -66,23 +67,23 @@ describe('general transforms:', function() {
6667

6768
traceOut = Plots.supplyTraceDefaults(traceIn, 0, layout);
6869

69-
expect(traceOut.transforms[0]).toEqual({
70+
expect(traceOut.transforms[0]).toEqual(jasmine.objectContaining({
7071
type: 'filter',
7172
enabled: true,
7273
operation: '=',
7374
value: 0,
7475
target: 'x',
7576
_module: Filter
76-
}, '- global first');
77+
}), '- global first');
7778

78-
expect(traceOut.transforms[1]).toEqual({
79+
expect(traceOut.transforms[1]).toEqual(jasmine.objectContaining({
7980
type: 'filter',
8081
enabled: true,
8182
operation: '>',
8283
value: 0,
8384
target: 'x',
8485
_module: Filter
85-
}, '- trace second');
86+
}), '- trace second');
8687

8788
expect(layout._transformModules).toEqual([Filter]);
8889
});
@@ -118,14 +119,14 @@ describe('general transforms:', function() {
118119
}], msg);
119120

120121
msg = 'supplying the transform defaults';
121-
expect(dataOut[1].transforms[0]).toEqual({
122+
expect(dataOut[1].transforms[0]).toEqual(jasmine.objectContaining({
122123
type: 'filter',
123124
enabled: true,
124125
operation: '>',
125126
value: 0,
126127
target: 'x',
127128
_module: Filter
128-
}, msg);
129+
}), msg);
129130

130131
msg = 'keeping refs to user data';
131132
expect(dataOut[1]._input.x).toEqual([-2, -1, -2, 0, 1, 2, 3], msg);
@@ -144,6 +145,7 @@ describe('general transforms:', function() {
144145
operation: '>',
145146
value: 0,
146147
target: 'x',
148+
preservegaps: false,
147149
_module: Filter
148150
}], msg);
149151

0 commit comments

Comments
 (0)