more work on FilteredMap (not done yet though)

I ended up not using this, but at some point we'll need it,
so commit this work
This commit is contained in:
Bruno Windels 2020-10-06 12:19:08 +02:00
parent 943467cf67
commit 84425fad5c

View file

@ -23,6 +23,7 @@ export class FilteredMap extends BaseObservableMap {
this._filter = filter; this._filter = filter;
/** @type {Map<string, bool>} */ /** @type {Map<string, bool>} */
this._included = null; this._included = null;
this._subscription = null;
} }
setFilter(filter) { setFilter(filter) {
@ -30,14 +31,30 @@ export class FilteredMap extends BaseObservableMap {
this.update(); this.update();
} }
/**
* reapply the filter
*/
update() { update() {
// TODO: need to check if we have a subscriber already? If not, we really should not iterate the source? // TODO: need to check if we have a subscriber already? If not, we really should not iterate the source?
if (this._filter) { if (this._filter) {
const hadFilterBefore = !!this._included;
this._included = this._included || new Map(); this._included = this._included || new Map();
for (const [key, value] of this._source) { for (const [key, value] of this._source) {
this._included.set(key, this._filter(value, key)); const isIncluded = this._filter(value, key);
const wasIncluded = hadFilterBefore ? this._included.get(key) : true;
this._included.set(key, isIncluded);
this._emitForUpdate(wasIncluded, isIncluded, key, value);
}
} else { // no filter
// did we have a filter before?
if (this._included) {
// add any non-included items again
for (const [key, value] of this._source) {
if (!this._included.get(key)) {
this.emitAdd(key, value);
}
}
} }
} else {
this._included = null; this._included = null;
} }
} }
@ -60,24 +77,28 @@ export class FilteredMap extends BaseObservableMap {
this.emitRemove(key, value); this.emitRemove(key, value);
} }
onChange(key, value, params) { onUpdate(key, value, params) {
if (this._filter) { if (this._filter) {
const wasIncluded = this._included.get(key); const wasIncluded = this._included.get(key);
const isIncluded = this._filter(value, key); const isIncluded = this._filter(value, key);
this._included.set(key, isIncluded); this._included.set(key, isIncluded);
this._emitForUpdate(wasIncluded, isIncluded, key, value, params);
}
this.emitUpdate(key, value, params);
}
_emitForUpdate(wasIncluded, isIncluded, key, value, params = null) {
if (wasIncluded && !isIncluded) { if (wasIncluded && !isIncluded) {
this.emitRemove(key, value); this.emitRemove(key, value);
} else if (!wasIncluded && isIncluded) { } else if (!wasIncluded && isIncluded) {
this.emitAdd(key, value); this.emitAdd(key, value);
} else if (!wasIncluded && !isIncluded) { } else if (wasIncluded && isIncluded) {
return; this.emitUpdate(key, value, params);
} // fall through to emitChange
} }
this.emitChange(key, value, params);
} }
onSubscribeFirst() { onSubscribeFirst() {
this._subscription = this._source.subscribe(this);
this.update(); this.update();
super.onSubscribeFirst(); super.onSubscribeFirst();
} }
@ -85,6 +106,7 @@ export class FilteredMap extends BaseObservableMap {
onUnsubscribeLast() { onUnsubscribeLast() {
super.onUnsubscribeLast(); super.onUnsubscribeLast();
this._included = null; this._included = null;
this._subscription = this._subscription();
} }
onReset() { onReset() {
@ -118,26 +140,26 @@ class FilterIterator {
} }
} }
import {ObservableMap} from "./ObservableMap.js"; // import {ObservableMap} from "./ObservableMap.js";
export function tests() { // export function tests() {
return { // return {
"filter preloaded list": assert => { // "filter preloaded list": assert => {
const source = new ObservableMap(); // const source = new ObservableMap();
source.add("one", 1); // source.add("one", 1);
source.add("two", 2); // source.add("two", 2);
source.add("three", 3); // source.add("three", 3);
const odds = Array.from(new FilteredMap(source, x => x % 2 !== 0)); // const odds = Array.from(new FilteredMap(source, x => x % 2 !== 0));
assert.equal(odds.length, 2); // assert.equal(odds.length, 2);
}, // },
"filter added values": assert => { // "filter added values": assert => {
}, // },
"filter removed values": assert => { // "filter removed values": assert => {
}, // },
"filter changed values": assert => { // "filter changed values": assert => {
}, // },
} // }
} // }