-
Notifications
You must be signed in to change notification settings - Fork 0
/
Threadily.KnockoutBridge.ts
151 lines (142 loc) · 7.38 KB
/
Threadily.KnockoutBridge.ts
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/**
* This class is responsible for linking threadily observables to knockout observables.
* As they both work on subscription systems, it's a very one-to-one process.
*/
export class ThreadilyKnockoutBridge
{
/**
* Links a Threadily Observable object to a KnockoutObservable object so that whenever the threadily object is updated, the knockout object is updated
* @param threadilyModule The loaded module of which contains not just Threadily but the ViewModel of the application
* @param koModule The knockout module
* @param self The object to create the knockout properties on
* @param threadilyProperty The threadily property to be subscribed to
* @param threadilyTypeName The type of the threadily property to be subscribed to
* @param koObjectName The name that the knockout observable will be called
* @param koViewModelFactory Optional: The constructor to be called when the value is set to a new object. Should only needed for complex types.
* @param decorator Optional: Function to run anytime a new value comes in
* @return A knockout subscription
*/
public static initAndLinkKnockoutObservableToThreadilyObject(threadilyModule: any, koModule: any, self: any, threadilyProperty: any, threadilyTypeName: string, koObjectName: string, koViewModelFactory: (threadilyModule: any, koModule: any, viewModel: any) => void, decorator: (newValue: any) => any)
{
var requiredArguments = ["threadilyModule", "koModule", "self", "threadilyProperty", "threadilyTypeName", "koObjectName"];
for (var i = 0; i < requiredArguments.length; i++) {
if (arguments[i] == null) {
throw new Error(requiredArguments[i] + " cannot be null");
}
}
if (decorator == null) {
decorator = (originalValue) => {
return originalValue;
};
}
// create the observable object on the self object
if (threadilyProperty.get() == null) {
self[koObjectName] = koModule.observable(null);
}
else {
// only if it is a ThreadObject, store a reference so we can make service calls on it
var data = threadilyProperty.get();
if (threadilyProperty.getThreadId != null) {
data = threadilyProperty.clone();
self[koObjectName + "ThreadObject"] = data;
}
if (koViewModelFactory != null) {
self[koObjectName] = koModule.observable(koViewModelFactory(threadilyModule, koModule, decorator(data)));
}
else {
self[koObjectName] = koModule.observable(decorator(data));
}
}
// link up for updates
return threadilyProperty.subscribe(new threadilyModule["ISubscribeHandle" + threadilyTypeName + "Callback"].implement({
onChange(newValue) {
// only if it is a ThreadObject, store a reference so we can make service calls on it
if (newValue.getThreadId != null) {
if (self[koObjectName + "ThreadObject"] != null) {
self[koObjectName + "ThreadObject"].delete();
}
if (newValue != null) {
newValue = newValue.clone();
self[koObjectName + "ThreadObject"] = newValue;
}
}
// now set the value
if (koViewModelFactory != null) {
self[koObjectName](koViewModelFactory(threadilyModule, koModule, decorator(newValue)));
}
else {
self[koObjectName](decorator(newValue));
}
}
}));
}
/**
* Links a Threadily ObservableVector to a KnockoutObservableArray so that whenever the Threadily ObservableVector is updated, the KnockoutObservableArray is updated
* @param threadilyModule The loaded module of which contains not just Threadily but the ViewModel of the application
* @param koModule The knockout module
* @param self The object to create the knockout properties on
* @param threadilyVector The threadily property to be subscribed to
* @param threadilyVectorTypeName The type of the threadily property to be subscribed to
* @param koArrayName The name that the knockout observable will be called
* @param koViewModelFactory Optional: The constructor to be called when the value is set to a new object. Should only needed for complex types.
* @return A knockout subscription
*/
public static initAndLinkKnockoutArrayToThreadilyVector(threadilyModule, koModule, self, threadilyVector, threadilyVectorTypeName, koArrayName, koViewModelFactory) {
var requiredArguments = ["threadilyModule", "koModule", "self", "threadilyVector", "threadilyVectorTypeName", "koArrayName"];
for (var i = 0; i < requiredArguments.length; i++) {
if (arguments[i] == null) {
throw new Error(requiredArguments[i] + " cannot be null");
}
}
// create the observable array on the self object
self[koArrayName] = koModule.observableArray([]);
self[koArrayName + "ThreadObjects"] = [];
// populate it with the initial data
var koArray = self[koArrayName];
for (var i = 0; i < threadilyVector.size(); i++) {
var iObject = threadilyVector.at(i);
// only if it is a ThreadObject, store a reference so we can make service calls on it
if (iObject.getThreadId != null) {
iObject = iObject.clone();
self[koArrayName + "ThreadObjects"].push(iObject);
}
if (koViewModelFactory != null) {
koArray.push(koViewModelFactory(threadilyModule, koModule, iObject));
}
else {
koArray.push(iObject);
}
}
// subscribe to events
return threadilyVector.subscribe(new threadilyModule["ISubscribeHandle" + threadilyVectorTypeName + "VectorCallback"].implement({
onChange(value, index, action) {
if (value != null && value.getThreadId != null) {
value = value.clone();
}
if (action == threadilyModule.ObservableActionType.Insert) {
// only if it is a ThreadObject, store a reference so we can make service calls on it
if (value.getThreadId != null) {
self[koArrayName + "ThreadObjects"].splice(index, 0, value);
}
if (koViewModelFactory != null) {
koArray.splice(index, 0, koViewModelFactory(threadilyModule, koModule, value));
}
else {
koArray.splice(index, 0, value);
}
}
else if (action == threadilyModule.ObservableActionType.Erase) {
if (value.getThreadId != null) {
var removed = self[koArrayName + "ThreadObjects"][index];
self[koArrayName + "ThreadObjects"].splice(index, 1);
removed.delete();
}
koArray.splice(index, 1);
}
else {
throw new Error('Not implemented');
}
}
}));
}
}