-
-
Notifications
You must be signed in to change notification settings - Fork 96
/
binding-expression.js
122 lines (108 loc) · 3.16 KB
/
binding-expression.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import {bindingMode} from './binding-mode';
import {connectable, sourceContext} from './connectable-binding';
export class BindingExpression {
constructor(observerLocator, targetProperty, sourceExpression,
mode, lookupFunctions, attribute){
this.observerLocator = observerLocator;
this.targetProperty = targetProperty;
this.sourceExpression = sourceExpression;
this.mode = mode;
this.lookupFunctions = lookupFunctions;
this.attribute = attribute;
this.discrete = false;
}
createBinding(target) {
return new Binding(
this.observerLocator,
this.sourceExpression,
target,
this.targetProperty,
this.mode,
this.lookupFunctions
);
}
}
const targetContext = 'Binding:target';
@connectable()
export class Binding {
constructor(observerLocator, sourceExpression, target, targetProperty, mode, lookupFunctions) {
this.observerLocator = observerLocator;
this.sourceExpression = sourceExpression;
this.targetProperty = observerLocator.getObserver(target, targetProperty);
this.mode = mode;
this.lookupFunctions = lookupFunctions;
}
updateTarget(value) {
this.targetProperty.setValue(value);
}
updateSource(value) {
this.sourceExpression.assign(this.source, value, this.lookupFunctions);
}
call(context, newValue, oldValue) {
if (!this.isBound) {
return;
}
if (context === sourceContext) {
oldValue = this.targetProperty.getValue();
newValue = this.sourceExpression.evaluate(this.source, this.lookupFunctions);
if (newValue !== oldValue) {
this.updateTarget(newValue);
}
if (this.mode !== bindingMode.oneTime) {
this._version++;
this.sourceExpression.connect(this, this.source);
this.unobserve(false);
}
return;
}
if (context === targetContext) {
this.updateSource(newValue);
return;
}
throw new Error(`Unexpected call context ${context}`);
}
bind(source) {
if (this.isBound) {
if (this.source === source) {
return;
}
this.unbind();
}
this.isBound = true;
this.source = source;
let sourceExpression = this.sourceExpression;
if (sourceExpression.bind) {
sourceExpression.bind(this, source, this.lookupFunctions);
}
let targetProperty = this.targetProperty;
if ('bind' in targetProperty){
targetProperty.bind();
}
let value = sourceExpression.evaluate(source, this.lookupFunctions);
this.updateTarget(value);
let mode = this.mode;
if (mode === bindingMode.oneWay || mode === bindingMode.twoWay) {
sourceExpression.connect(this, source);
if (mode === bindingMode.twoWay) {
targetProperty.subscribe(targetContext, this);
}
}
}
unbind() {
if (!this.isBound) {
return;
}
this.isBound = false;
if (this.sourceExpression.unbind) {
this.sourceExpression.unbind(this, this.source);
}
this.source = null;
if ('unbind' in this.targetProperty) {
this.targetProperty.unbind();
}
if (this.mode === bindingMode.twoWay) {
this.targetProperty.unsubscribe(targetContext, this);
}
this.unobserve(true);
}
}