mirror of
https://github.com/vector-im/hydrogen-web.git
synced 2024-12-23 03:25:12 +01:00
map operator for observable lists
This commit is contained in:
parent
0b5c2f9273
commit
6f650d19b1
@ -5,6 +5,7 @@ import BaseObservableMap from "./map/BaseObservableMap.js";
|
||||
// re-export "root" (of chain) collections
|
||||
export { default as ObservableArray } from "./list/ObservableArray.js";
|
||||
export { default as SortedArray } from "./list/SortedArray.js";
|
||||
export { default as MappedList } from "./list/MappedList.js";
|
||||
export { default as ObservableMap } from "./map/ObservableMap.js";
|
||||
|
||||
// avoid circular dependency between these classes
|
||||
|
115
src/observable/list/MappedList.js
Normal file
115
src/observable/list/MappedList.js
Normal file
@ -0,0 +1,115 @@
|
||||
import BaseObservableList from "./BaseObservableList.js";
|
||||
|
||||
export default class MappedList extends BaseObservableList {
|
||||
constructor(sourceList, mapper, updater) {
|
||||
super();
|
||||
this._sourceList = sourceList;
|
||||
this._mapper = mapper;
|
||||
this._updater = updater;
|
||||
this._sourceUnsubscribe = null;
|
||||
this._mappedValues = null;
|
||||
}
|
||||
|
||||
onSubscribeFirst() {
|
||||
this._sourceUnsubscribe = this._sourceList.subscribe(this);
|
||||
this._mappedValues = [];
|
||||
for (const item of this._sourceList) {
|
||||
this._mappedValues.push(this._mapper(item));
|
||||
}
|
||||
}
|
||||
|
||||
onReset() {
|
||||
this._mappedValues = [];
|
||||
this.emitReset();
|
||||
}
|
||||
|
||||
onAdd(index, value) {
|
||||
const mappedValue = this._mapper(value);
|
||||
this._mappedValues.splice(index, 0, mappedValue);
|
||||
this.emitAdd(index, mappedValue);
|
||||
}
|
||||
|
||||
onUpdate(index, value, params) {
|
||||
const mappedValue = this._mappedValues[index];
|
||||
if (this._updater) {
|
||||
this._updater(mappedValue, value);
|
||||
}
|
||||
this.emitUpdate(index, mappedValue, params);
|
||||
}
|
||||
|
||||
onRemove(index) {
|
||||
const mappedValue = this._mappedValues[index];
|
||||
this._mappedValues.splice(index, 1);
|
||||
this.emitRemove(index, mappedValue);
|
||||
}
|
||||
|
||||
onMove(fromIdx, toIdx) {
|
||||
const mappedValue = this._mappedValues[fromIdx];
|
||||
this._mappedValues.splice(fromIdx, 1);
|
||||
this._mappedValues.splice(toIdx, 0, mappedValue);
|
||||
this.emitMove(fromIdx, toIdx, mappedValue);
|
||||
}
|
||||
|
||||
onUnsubscribeLast() {
|
||||
this._sourceUnsubscribe();
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this._mappedValues.length;
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return this._mappedValues.values();
|
||||
}
|
||||
}
|
||||
|
||||
export async function tests() {
|
||||
class MockList extends BaseObservableList {
|
||||
get length() {
|
||||
return 0;
|
||||
}
|
||||
[Symbol.iterator]() {
|
||||
return [].values();
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
test_add(assert) {
|
||||
const source = new MockList();
|
||||
const mapped = new MappedList(source, n => {return {n: n*n};});
|
||||
let fired = false;
|
||||
const unsubscribe = mapped.subscribe({
|
||||
onAdd(idx, value) {
|
||||
fired = true;
|
||||
assert.equal(idx, 0);
|
||||
assert.equal(value.n, 36);
|
||||
}
|
||||
});
|
||||
source.emitAdd(0, 6);
|
||||
assert(fired);
|
||||
unsubscribe();
|
||||
},
|
||||
test_update(assert) {
|
||||
const source = new MockList();
|
||||
const mapped = new MappedList(
|
||||
source,
|
||||
n => {return {n: n*n};},
|
||||
(o, n) => o.m = n*n
|
||||
);
|
||||
let fired = false;
|
||||
const unsubscribe = mapped.subscribe({
|
||||
onAdd() {},
|
||||
onUpdate(idx, value) {
|
||||
fired = true;
|
||||
assert.equal(idx, 0);
|
||||
assert.equal(value.n, 36);
|
||||
assert.equal(value.m, 49);
|
||||
}
|
||||
});
|
||||
source.emitAdd(0, 6);
|
||||
source.emitUpdate(0, 7);
|
||||
assert(fired);
|
||||
unsubscribe();
|
||||
}
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user