cx 25.5.1 → 25.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/charts.js +40 -21
- package/dist/manifest.js +771 -771
- package/dist/ui.js +0 -15
- package/dist/widgets.js +34 -25
- package/package.json +1 -1
- package/src/charts/LineGraph.js +1 -1
- package/src/charts/axis/NumericAxis.d.ts +46 -46
- package/src/charts/helpers/PointReducer.d.ts +9 -0
- package/src/charts/helpers/PointReducer.js +36 -22
- package/src/data/AugmentedViewBase.js +77 -77
- package/src/data/ExposedRecordView.js +75 -75
- package/src/data/ExposedValueView.js +73 -73
- package/src/data/Ref.d.ts +24 -24
- package/src/data/Ref.spec.js +79 -79
- package/src/data/StoreRef.spec.js +24 -24
- package/src/data/StructuredDataAccessor.d.ts +7 -7
- package/src/data/SubscribableView.js +54 -54
- package/src/ui/Container.js +154 -154
- package/src/ui/DataProxy.js +31 -45
- package/src/ui/DetachedScope.js +98 -98
- package/src/ui/Instance.d.ts +72 -72
- package/src/ui/Instance.js +623 -623
- package/src/ui/IsolatedScope.js +30 -30
- package/src/ui/Repeater.js +109 -109
- package/src/ui/Rescope.js +35 -35
- package/src/ui/Restate.js +167 -167
- package/src/ui/Widget.js +184 -184
- package/src/ui/adapter/ArrayAdapter.js +152 -152
- package/src/ui/adapter/TreeAdapter.js +101 -101
- package/src/ui/createFunctionalComponent.d.ts +1 -1
- package/src/ui/index.d.ts +42 -42
- package/src/ui/layout/exploreChildren.d.ts +12 -12
- package/src/ui/layout/exploreChildren.js +27 -27
- package/src/util/debounce.js +18 -18
- package/src/util/validatedDebounce.js +19 -19
- package/src/widgets/Button.js +118 -118
- package/src/widgets/List.js +594 -594
- package/src/widgets/form/Calendar.d.ts +86 -86
- package/src/widgets/form/Checkbox.js +5 -2
- package/src/widgets/form/MonthField.d.ts +5 -0
- package/src/widgets/form/MonthField.js +1 -0
- package/src/widgets/form/MonthPicker.d.ts +13 -0
- package/src/widgets/form/MonthPicker.js +25 -21
- package/src/widgets/grid/Grid.js +3421 -3421
- package/src/widgets/nav/Route.js +102 -102
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
import { View } from "./View";
|
|
2
|
-
import { Binding } from "./Binding";
|
|
3
|
-
|
|
4
|
-
export class ExposedValueView extends View {
|
|
5
|
-
getData() {
|
|
6
|
-
if (
|
|
7
|
-
this.sealed &&
|
|
8
|
-
this.meta.version === this.cache.version &&
|
|
9
|
-
this.cache.key === this.key &&
|
|
10
|
-
this.meta == this.store.meta
|
|
11
|
-
)
|
|
12
|
-
return this.cache.result;
|
|
13
|
-
|
|
14
|
-
let data = this.store.getData();
|
|
15
|
-
let container = this.containerBinding.value(data) || {};
|
|
16
|
-
let record = container[this.key];
|
|
17
|
-
|
|
18
|
-
this.cache.version = this.meta.version;
|
|
19
|
-
this.cache.key = this.key;
|
|
20
|
-
this.cache.result = this.sealed || this.immutable || this.store.sealed ? { ...data } : data;
|
|
21
|
-
this.cache.result[this.recordName] = record;
|
|
22
|
-
this.meta = this.store.meta;
|
|
23
|
-
return this.cache.result;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
setKey(key) {
|
|
27
|
-
this.key = key;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
getKey() {
|
|
31
|
-
return this.key;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
setItem(path, value) {
|
|
35
|
-
if (path == this.recordName || path.indexOf(this.recordName + ".") == 0) {
|
|
36
|
-
var data = this.getData();
|
|
37
|
-
var d = Binding.get(path).set(data, value);
|
|
38
|
-
if (d === data) return false;
|
|
39
|
-
var container = this.containerBinding.value(d);
|
|
40
|
-
var record = d[this.recordName];
|
|
41
|
-
var newContainer = Object.assign({}, container);
|
|
42
|
-
newContainer[this.key] = record;
|
|
43
|
-
return this.store.setItem(this.containerBinding.path, newContainer);
|
|
44
|
-
}
|
|
45
|
-
return this.store.setItem(path, value);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
deleteItem(path) {
|
|
49
|
-
var data, container, newContainer;
|
|
50
|
-
|
|
51
|
-
if (path == this.recordName) {
|
|
52
|
-
data = this.getData();
|
|
53
|
-
container = this.containerBinding.value(data);
|
|
54
|
-
if (!container || !container.hasOwnProperty(path)) return false;
|
|
55
|
-
newContainer = Object.assign({}, container);
|
|
56
|
-
delete newContainer[this.key];
|
|
57
|
-
this.store.set(this.containerBinding.path, newContainer);
|
|
58
|
-
} else if (path.indexOf(this.recordName + ".") == 0) {
|
|
59
|
-
data = this.getData();
|
|
60
|
-
var d = Binding.get(path).delete(data);
|
|
61
|
-
if (d === data) return false;
|
|
62
|
-
container = this.containerBinding.value(d);
|
|
63
|
-
var record = d[this.recordName];
|
|
64
|
-
newContainer = Object.assign({}, container);
|
|
65
|
-
newContainer[this.key] = record;
|
|
66
|
-
return this.store.setItem(this.containerBinding.path, newContainer);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return this.store.deleteItem(path);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
ExposedValueView.prototype.immutable = false;
|
|
1
|
+
import { View } from "./View";
|
|
2
|
+
import { Binding } from "./Binding";
|
|
3
|
+
|
|
4
|
+
export class ExposedValueView extends View {
|
|
5
|
+
getData() {
|
|
6
|
+
if (
|
|
7
|
+
this.sealed &&
|
|
8
|
+
this.meta.version === this.cache.version &&
|
|
9
|
+
this.cache.key === this.key &&
|
|
10
|
+
this.meta == this.store.meta
|
|
11
|
+
)
|
|
12
|
+
return this.cache.result;
|
|
13
|
+
|
|
14
|
+
let data = this.store.getData();
|
|
15
|
+
let container = this.containerBinding.value(data) || {};
|
|
16
|
+
let record = container[this.key];
|
|
17
|
+
|
|
18
|
+
this.cache.version = this.meta.version;
|
|
19
|
+
this.cache.key = this.key;
|
|
20
|
+
this.cache.result = this.sealed || this.immutable || this.store.sealed ? { ...data } : data;
|
|
21
|
+
this.cache.result[this.recordName] = record;
|
|
22
|
+
this.meta = this.store.meta;
|
|
23
|
+
return this.cache.result;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
setKey(key) {
|
|
27
|
+
this.key = key;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getKey() {
|
|
31
|
+
return this.key;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
setItem(path, value) {
|
|
35
|
+
if (path == this.recordName || path.indexOf(this.recordName + ".") == 0) {
|
|
36
|
+
var data = this.getData();
|
|
37
|
+
var d = Binding.get(path).set(data, value);
|
|
38
|
+
if (d === data) return false;
|
|
39
|
+
var container = this.containerBinding.value(d);
|
|
40
|
+
var record = d[this.recordName];
|
|
41
|
+
var newContainer = Object.assign({}, container);
|
|
42
|
+
newContainer[this.key] = record;
|
|
43
|
+
return this.store.setItem(this.containerBinding.path, newContainer);
|
|
44
|
+
}
|
|
45
|
+
return this.store.setItem(path, value);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
deleteItem(path) {
|
|
49
|
+
var data, container, newContainer;
|
|
50
|
+
|
|
51
|
+
if (path == this.recordName) {
|
|
52
|
+
data = this.getData();
|
|
53
|
+
container = this.containerBinding.value(data);
|
|
54
|
+
if (!container || !container.hasOwnProperty(path)) return false;
|
|
55
|
+
newContainer = Object.assign({}, container);
|
|
56
|
+
delete newContainer[this.key];
|
|
57
|
+
this.store.set(this.containerBinding.path, newContainer);
|
|
58
|
+
} else if (path.indexOf(this.recordName + ".") == 0) {
|
|
59
|
+
data = this.getData();
|
|
60
|
+
var d = Binding.get(path).delete(data);
|
|
61
|
+
if (d === data) return false;
|
|
62
|
+
container = this.containerBinding.value(d);
|
|
63
|
+
var record = d[this.recordName];
|
|
64
|
+
newContainer = Object.assign({}, container);
|
|
65
|
+
newContainer[this.key] = record;
|
|
66
|
+
return this.store.setItem(this.containerBinding.path, newContainer);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return this.store.deleteItem(path);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
ExposedValueView.prototype.immutable = false;
|
package/src/data/Ref.d.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { View } from "./View";
|
|
2
|
-
|
|
3
|
-
interface RefConfig {
|
|
4
|
-
store: View;
|
|
5
|
-
path: string;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export class Ref<T = any> {
|
|
9
|
-
constructor(config: RefConfig);
|
|
10
|
-
|
|
11
|
-
init(value: T): boolean;
|
|
12
|
-
|
|
13
|
-
set(value: T): boolean;
|
|
14
|
-
|
|
15
|
-
delete(): boolean;
|
|
16
|
-
|
|
17
|
-
get(): T;
|
|
18
|
-
|
|
19
|
-
toggle(): boolean;
|
|
20
|
-
|
|
21
|
-
update(updateFn: (currentValue: T, ...args) => T, ...args): boolean;
|
|
22
|
-
|
|
23
|
-
ref<ST = any>(path: string): Ref<ST>;
|
|
24
|
-
}
|
|
1
|
+
import { View } from "./View";
|
|
2
|
+
|
|
3
|
+
interface RefConfig {
|
|
4
|
+
store: View;
|
|
5
|
+
path: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class Ref<T = any> {
|
|
9
|
+
constructor(config: RefConfig);
|
|
10
|
+
|
|
11
|
+
init(value: T): boolean;
|
|
12
|
+
|
|
13
|
+
set(value: T): boolean;
|
|
14
|
+
|
|
15
|
+
delete(): boolean;
|
|
16
|
+
|
|
17
|
+
get(): T;
|
|
18
|
+
|
|
19
|
+
toggle(): boolean;
|
|
20
|
+
|
|
21
|
+
update(updateFn: (currentValue: T, ...args) => T, ...args): boolean;
|
|
22
|
+
|
|
23
|
+
ref<ST = any>(path: string): Ref<ST>;
|
|
24
|
+
}
|
package/src/data/Ref.spec.js
CHANGED
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
import assert from "assert";
|
|
2
|
-
import { Store } from "./Store";
|
|
3
|
-
import { Ref } from "./Ref";
|
|
4
|
-
import { append } from "./ops/append";
|
|
5
|
-
import { StoreRef } from "./StoreRef";
|
|
6
|
-
|
|
7
|
-
const getStore = () => {
|
|
8
|
-
return new Store({
|
|
9
|
-
data: {
|
|
10
|
-
a: 3,
|
|
11
|
-
item: {
|
|
12
|
-
firstName: "Jack",
|
|
13
|
-
},
|
|
14
|
-
array: [],
|
|
15
|
-
},
|
|
16
|
-
});
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
describe("Ref", () => {
|
|
20
|
-
it("can init data", () => {
|
|
21
|
-
let store = getStore();
|
|
22
|
-
let b = store.ref("b", 1);
|
|
23
|
-
assert.equal(store.get("b"), 1);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("can set data", () => {
|
|
27
|
-
let store = getStore();
|
|
28
|
-
let b = store.ref("b", 1);
|
|
29
|
-
b.set(2);
|
|
30
|
-
assert.equal(store.get("b"), 2);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("can delete data", () => {
|
|
34
|
-
let store = getStore();
|
|
35
|
-
let b = store.ref("item");
|
|
36
|
-
b.delete();
|
|
37
|
-
assert.equal(store.get("item"), undefined);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it("can cast itself to a ref of another type", () => {
|
|
41
|
-
class ArrayRef extends StoreRef {
|
|
42
|
-
append(...args) {
|
|
43
|
-
this.update(append, ...args);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
let store = getStore();
|
|
47
|
-
let array = store.ref("array").as(ArrayRef);
|
|
48
|
-
array.append(1, 2, 3);
|
|
49
|
-
assert.deepEqual(array.get(), [1, 2, 3]);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it("can extend itself in a functional way", () => {
|
|
53
|
-
let store = getStore();
|
|
54
|
-
let array = store.ref("array").as(({ update, set, path }) => ({
|
|
55
|
-
append(...args) {
|
|
56
|
-
update(path, append, ...args);
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
clear() {
|
|
60
|
-
set(path, []);
|
|
61
|
-
},
|
|
62
|
-
}));
|
|
63
|
-
array.append(1, 2, 3);
|
|
64
|
-
assert.deepEqual(array.get(), [1, 2, 3]);
|
|
65
|
-
array.clear();
|
|
66
|
-
assert.deepEqual(array.get(), []);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it("can get subrefs", () => {
|
|
70
|
-
let store = getStore();
|
|
71
|
-
let person = new Ref({
|
|
72
|
-
get: () => store.get("person"),
|
|
73
|
-
set: (value) => store.set("person", value),
|
|
74
|
-
});
|
|
75
|
-
let name = person.ref("name");
|
|
76
|
-
name.set("John");
|
|
77
|
-
assert.equal(name.get(), "John");
|
|
78
|
-
});
|
|
79
|
-
});
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
import { Store } from "./Store";
|
|
3
|
+
import { Ref } from "./Ref";
|
|
4
|
+
import { append } from "./ops/append";
|
|
5
|
+
import { StoreRef } from "./StoreRef";
|
|
6
|
+
|
|
7
|
+
const getStore = () => {
|
|
8
|
+
return new Store({
|
|
9
|
+
data: {
|
|
10
|
+
a: 3,
|
|
11
|
+
item: {
|
|
12
|
+
firstName: "Jack",
|
|
13
|
+
},
|
|
14
|
+
array: [],
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
describe("Ref", () => {
|
|
20
|
+
it("can init data", () => {
|
|
21
|
+
let store = getStore();
|
|
22
|
+
let b = store.ref("b", 1);
|
|
23
|
+
assert.equal(store.get("b"), 1);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("can set data", () => {
|
|
27
|
+
let store = getStore();
|
|
28
|
+
let b = store.ref("b", 1);
|
|
29
|
+
b.set(2);
|
|
30
|
+
assert.equal(store.get("b"), 2);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("can delete data", () => {
|
|
34
|
+
let store = getStore();
|
|
35
|
+
let b = store.ref("item");
|
|
36
|
+
b.delete();
|
|
37
|
+
assert.equal(store.get("item"), undefined);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("can cast itself to a ref of another type", () => {
|
|
41
|
+
class ArrayRef extends StoreRef {
|
|
42
|
+
append(...args) {
|
|
43
|
+
this.update(append, ...args);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
let store = getStore();
|
|
47
|
+
let array = store.ref("array").as(ArrayRef);
|
|
48
|
+
array.append(1, 2, 3);
|
|
49
|
+
assert.deepEqual(array.get(), [1, 2, 3]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("can extend itself in a functional way", () => {
|
|
53
|
+
let store = getStore();
|
|
54
|
+
let array = store.ref("array").as(({ update, set, path }) => ({
|
|
55
|
+
append(...args) {
|
|
56
|
+
update(path, append, ...args);
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
clear() {
|
|
60
|
+
set(path, []);
|
|
61
|
+
},
|
|
62
|
+
}));
|
|
63
|
+
array.append(1, 2, 3);
|
|
64
|
+
assert.deepEqual(array.get(), [1, 2, 3]);
|
|
65
|
+
array.clear();
|
|
66
|
+
assert.deepEqual(array.get(), []);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("can get subrefs", () => {
|
|
70
|
+
let store = getStore();
|
|
71
|
+
let person = new Ref({
|
|
72
|
+
get: () => store.get("person"),
|
|
73
|
+
set: (value) => store.set("person", value),
|
|
74
|
+
});
|
|
75
|
+
let name = person.ref("name");
|
|
76
|
+
name.set("John");
|
|
77
|
+
assert.equal(name.get(), "John");
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import assert from "assert";
|
|
2
|
-
import { Store } from "./Store";
|
|
3
|
-
import { StoreRef } from "./StoreRef";
|
|
4
|
-
|
|
5
|
-
const getStore = () => {
|
|
6
|
-
return new Store({
|
|
7
|
-
data: {
|
|
8
|
-
person: {
|
|
9
|
-
name: "Jack",
|
|
10
|
-
},
|
|
11
|
-
},
|
|
12
|
-
});
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
describe("StoreRef", () => {
|
|
16
|
-
it("can access child refs", () => {
|
|
17
|
-
let store = getStore();
|
|
18
|
-
let person = store.ref("person");
|
|
19
|
-
let name = person.ref("name");
|
|
20
|
-
assert.equal(name.get("person"), "Jack");
|
|
21
|
-
name.set("John");
|
|
22
|
-
assert.equal(name.get("person"), "John");
|
|
23
|
-
});
|
|
24
|
-
});
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
import { Store } from "./Store";
|
|
3
|
+
import { StoreRef } from "./StoreRef";
|
|
4
|
+
|
|
5
|
+
const getStore = () => {
|
|
6
|
+
return new Store({
|
|
7
|
+
data: {
|
|
8
|
+
person: {
|
|
9
|
+
name: "Jack",
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
describe("StoreRef", () => {
|
|
16
|
+
it("can access child refs", () => {
|
|
17
|
+
let store = getStore();
|
|
18
|
+
let person = store.ref("person");
|
|
19
|
+
let name = person.ref("name");
|
|
20
|
+
assert.equal(name.get("person"), "Jack");
|
|
21
|
+
name.set("John");
|
|
22
|
+
assert.equal(name.get("person"), "John");
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export interface StructuredDataAccessor {
|
|
2
|
-
getSelector(): (data: Cx.Record) => Cx.Record;
|
|
3
|
-
get(): Cx.Record;
|
|
4
|
-
setItem(key: string, value: any): boolean;
|
|
5
|
-
containsKey(key): string;
|
|
6
|
-
getKeys(): string[];
|
|
7
|
-
}
|
|
1
|
+
export interface StructuredDataAccessor {
|
|
2
|
+
getSelector(): (data: Cx.Record) => Cx.Record;
|
|
3
|
+
get(): Cx.Record;
|
|
4
|
+
setItem(key: string, value: any): boolean;
|
|
5
|
+
containsKey(key): string;
|
|
6
|
+
getKeys(): string[];
|
|
7
|
+
}
|
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
import { View } from "./View";
|
|
2
|
-
import { SubscriberList } from "../util/SubscriberList";
|
|
3
|
-
|
|
4
|
-
export class SubscribableView extends View {
|
|
5
|
-
constructor(config) {
|
|
6
|
-
super(config);
|
|
7
|
-
this.subscribers = new SubscriberList();
|
|
8
|
-
this.changes = [];
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
subscribe(callback) {
|
|
12
|
-
return this.subscribers.subscribe(callback);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
unsubscribeAll() {
|
|
16
|
-
this.subscribers.clear();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
doNotify(path) {
|
|
20
|
-
if (this.notificationsSuspended) return;
|
|
21
|
-
|
|
22
|
-
if (!this.async) {
|
|
23
|
-
this.subscribers.notify([path]);
|
|
24
|
-
} else {
|
|
25
|
-
this.changes.push(path || "");
|
|
26
|
-
if (!this.scheduled) {
|
|
27
|
-
this.scheduled = true;
|
|
28
|
-
setTimeout(() => {
|
|
29
|
-
this.scheduled = false;
|
|
30
|
-
let changes = this.changes;
|
|
31
|
-
this.changes = [];
|
|
32
|
-
this.subscribers.notify(changes);
|
|
33
|
-
}, 0);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
silently(callback) {
|
|
39
|
-
this.notificationsSuspended = (this.notificationsSuspended || 0) + 1;
|
|
40
|
-
let wasDirty = this.dirty,
|
|
41
|
-
dirty;
|
|
42
|
-
this.dirty = false;
|
|
43
|
-
try {
|
|
44
|
-
callback(this);
|
|
45
|
-
} finally {
|
|
46
|
-
this.notificationsSuspended--;
|
|
47
|
-
dirty = this.dirty;
|
|
48
|
-
this.dirty = wasDirty;
|
|
49
|
-
}
|
|
50
|
-
return dirty;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
SubscribableView.prototype.async = false;
|
|
1
|
+
import { View } from "./View";
|
|
2
|
+
import { SubscriberList } from "../util/SubscriberList";
|
|
3
|
+
|
|
4
|
+
export class SubscribableView extends View {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
super(config);
|
|
7
|
+
this.subscribers = new SubscriberList();
|
|
8
|
+
this.changes = [];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
subscribe(callback) {
|
|
12
|
+
return this.subscribers.subscribe(callback);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
unsubscribeAll() {
|
|
16
|
+
this.subscribers.clear();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
doNotify(path) {
|
|
20
|
+
if (this.notificationsSuspended) return;
|
|
21
|
+
|
|
22
|
+
if (!this.async) {
|
|
23
|
+
this.subscribers.notify([path]);
|
|
24
|
+
} else {
|
|
25
|
+
this.changes.push(path || "");
|
|
26
|
+
if (!this.scheduled) {
|
|
27
|
+
this.scheduled = true;
|
|
28
|
+
setTimeout(() => {
|
|
29
|
+
this.scheduled = false;
|
|
30
|
+
let changes = this.changes;
|
|
31
|
+
this.changes = [];
|
|
32
|
+
this.subscribers.notify(changes);
|
|
33
|
+
}, 0);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
silently(callback) {
|
|
39
|
+
this.notificationsSuspended = (this.notificationsSuspended || 0) + 1;
|
|
40
|
+
let wasDirty = this.dirty,
|
|
41
|
+
dirty;
|
|
42
|
+
this.dirty = false;
|
|
43
|
+
try {
|
|
44
|
+
callback(this);
|
|
45
|
+
} finally {
|
|
46
|
+
this.notificationsSuspended--;
|
|
47
|
+
dirty = this.dirty;
|
|
48
|
+
this.dirty = wasDirty;
|
|
49
|
+
}
|
|
50
|
+
return dirty;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
SubscribableView.prototype.async = false;
|