vsn 0.1.26 → 0.1.27

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.
Files changed (191) hide show
  1. package/dist/AST.js +2197 -0
  2. package/dist/AST.js.map +1 -0
  3. package/dist/Attribute.d.ts +1 -1
  4. package/dist/Attribute.js +187 -0
  5. package/dist/Attribute.js.map +1 -0
  6. package/dist/Bencmark.js +179 -0
  7. package/dist/Bencmark.js.map +1 -0
  8. package/dist/Configuration.d.ts +1 -1
  9. package/dist/Configuration.js +64 -0
  10. package/dist/Configuration.js.map +1 -0
  11. package/dist/Controller.d.ts +1 -1
  12. package/dist/Controller.js +54 -0
  13. package/dist/Controller.js.map +1 -0
  14. package/dist/DOM/DOMObject.d.ts +1 -1
  15. package/dist/DOM/DOMObject.js +47 -0
  16. package/dist/DOM/DOMObject.js.map +1 -0
  17. package/dist/DOM/WrappedDocument.js +34 -0
  18. package/dist/DOM/WrappedDocument.js.map +1 -0
  19. package/dist/DOM/WrappedWindow.js +45 -0
  20. package/dist/DOM/WrappedWindow.js.map +1 -0
  21. package/dist/DOM.d.ts +1 -1
  22. package/dist/DOM.js +547 -0
  23. package/dist/DOM.js.map +1 -0
  24. package/dist/EventDispatcher.d.ts +26 -0
  25. package/dist/EventDispatcher.js +117 -0
  26. package/dist/EventDispatcher.js.map +1 -0
  27. package/dist/Formats.js +44 -0
  28. package/dist/Formats.js.map +1 -0
  29. package/dist/MessageList.d.ts +14 -0
  30. package/dist/MessageList.js +88 -0
  31. package/dist/MessageList.js.map +1 -0
  32. package/dist/Model/Collection.d.ts +5 -0
  33. package/dist/Model/Collection.js +37 -0
  34. package/dist/Model/Collection.js.map +1 -0
  35. package/dist/Model/DataModel.d.ts +6 -0
  36. package/dist/Model/DataModel.js +54 -0
  37. package/dist/Model/DataModel.js.map +1 -0
  38. package/dist/Model/ModelAbstract.d.ts +20 -0
  39. package/dist/Model/ModelAbstract.js +122 -0
  40. package/dist/Model/ModelAbstract.js.map +1 -0
  41. package/dist/Model/fields/BooleanField.d.ts +5 -0
  42. package/dist/Model/fields/BooleanField.js +43 -0
  43. package/dist/Model/fields/BooleanField.js.map +1 -0
  44. package/dist/Model/fields/EmailField.d.ts +5 -0
  45. package/dist/Model/fields/EmailField.js +36 -0
  46. package/dist/Model/fields/EmailField.js.map +1 -0
  47. package/dist/Model/fields/Field.d.ts +13 -0
  48. package/dist/Model/fields/Field.js +79 -0
  49. package/dist/Model/fields/Field.js.map +1 -0
  50. package/dist/Model/fields/FloatField.d.ts +5 -0
  51. package/dist/Model/fields/FloatField.js +47 -0
  52. package/dist/Model/fields/FloatField.js.map +1 -0
  53. package/dist/Model/fields/PositiveNumberField.d.ts +5 -0
  54. package/dist/Model/fields/PositiveNumberField.js +51 -0
  55. package/dist/Model/fields/PositiveNumberField.js.map +1 -0
  56. package/dist/Model/fields/StringField.d.ts +5 -0
  57. package/dist/Model/fields/StringField.js +43 -0
  58. package/dist/Model/fields/StringField.js.map +1 -0
  59. package/dist/Model.d.ts +11 -0
  60. package/dist/Model.js +72 -0
  61. package/dist/Model.js.map +1 -0
  62. package/dist/Query.js +66 -0
  63. package/dist/Query.js.map +1 -0
  64. package/dist/Registry.d.ts +2 -2
  65. package/dist/Registry.js +128 -0
  66. package/dist/Registry.js.map +1 -0
  67. package/dist/Scope.d.ts +7 -10
  68. package/dist/Scope.js +462 -0
  69. package/dist/Scope.js.map +1 -0
  70. package/dist/SimplePromise.d.ts +42 -0
  71. package/dist/SimplePromise.js +217 -0
  72. package/dist/SimplePromise.js.map +1 -0
  73. package/dist/Tag/List.js +85 -0
  74. package/dist/Tag/List.js.map +1 -0
  75. package/dist/Tag.js +770 -0
  76. package/dist/Tag.js.map +1 -0
  77. package/dist/Types.js +48 -0
  78. package/dist/Types.js.map +1 -0
  79. package/dist/attributes/AddClassIf.js +93 -0
  80. package/dist/attributes/AddClassIf.js.map +1 -0
  81. package/dist/attributes/Bind.js +272 -0
  82. package/dist/attributes/Bind.js.map +1 -0
  83. package/dist/attributes/ClassConstructor.js +104 -0
  84. package/dist/attributes/ClassConstructor.js.map +1 -0
  85. package/dist/attributes/ClickRemoveClass.js +114 -0
  86. package/dist/attributes/ClickRemoveClass.js.map +1 -0
  87. package/dist/attributes/ClickToggleClass.js +114 -0
  88. package/dist/attributes/ClickToggleClass.js.map +1 -0
  89. package/dist/attributes/ControllerAttribute.js +28 -0
  90. package/dist/attributes/ControllerAttribute.js.map +1 -0
  91. package/dist/attributes/DisableIf.js +94 -0
  92. package/dist/attributes/DisableIf.js.map +1 -0
  93. package/dist/attributes/Exec.js +108 -0
  94. package/dist/attributes/Exec.js.map +1 -0
  95. package/dist/attributes/Format.js +99 -0
  96. package/dist/attributes/Format.js.map +1 -0
  97. package/dist/attributes/If.js +159 -0
  98. package/dist/attributes/If.js.map +1 -0
  99. package/dist/attributes/JSONAttribute.js +118 -0
  100. package/dist/attributes/JSONAttribute.js.map +1 -0
  101. package/dist/attributes/KeyAbstract.js +117 -0
  102. package/dist/attributes/KeyAbstract.js.map +1 -0
  103. package/dist/attributes/KeyDown.js +88 -0
  104. package/dist/attributes/KeyDown.js.map +1 -0
  105. package/dist/attributes/KeyUp.js +88 -0
  106. package/dist/attributes/KeyUp.js.map +1 -0
  107. package/dist/attributes/List.js +282 -0
  108. package/dist/attributes/List.js.map +1 -0
  109. package/dist/attributes/ListItem.js +138 -0
  110. package/dist/attributes/ListItem.js.map +1 -0
  111. package/dist/attributes/ListItemModel.js +39 -0
  112. package/dist/attributes/ListItemModel.js.map +1 -0
  113. package/dist/attributes/ModelAttribute.js +29 -0
  114. package/dist/attributes/ModelAttribute.js.map +1 -0
  115. package/dist/attributes/Name.js +88 -0
  116. package/dist/attributes/Name.js.map +1 -0
  117. package/dist/attributes/On.js +135 -0
  118. package/dist/attributes/On.js.map +1 -0
  119. package/dist/attributes/Radio.js +174 -0
  120. package/dist/attributes/Radio.js.map +1 -0
  121. package/dist/attributes/Referenced.js +38 -0
  122. package/dist/attributes/Referenced.js.map +1 -0
  123. package/dist/attributes/RootAttribute.js +91 -0
  124. package/dist/attributes/RootAttribute.js.map +1 -0
  125. package/dist/attributes/ScopeAttribute.js +40 -0
  126. package/dist/attributes/ScopeAttribute.js.map +1 -0
  127. package/dist/attributes/ScopeChange.js +130 -0
  128. package/dist/attributes/ScopeChange.js.map +1 -0
  129. package/dist/attributes/SetAttribute.js +133 -0
  130. package/dist/attributes/SetAttribute.js.map +1 -0
  131. package/dist/attributes/StandardAttribute.js +186 -0
  132. package/dist/attributes/StandardAttribute.js.map +1 -0
  133. package/dist/attributes/StyleAttribute.js +183 -0
  134. package/dist/attributes/StyleAttribute.js.map +1 -0
  135. package/dist/attributes/Template.js +39 -0
  136. package/dist/attributes/Template.js.map +1 -0
  137. package/dist/attributes/TypeAttribute.js +104 -0
  138. package/dist/attributes/TypeAttribute.js.map +1 -0
  139. package/dist/attributes/_imports.js +60 -0
  140. package/dist/attributes/_imports.js.map +1 -0
  141. package/dist/helpers/DOMHelper.js +81 -0
  142. package/dist/helpers/DOMHelper.js.map +1 -0
  143. package/dist/helpers/ElementHelper.js +25 -0
  144. package/dist/helpers/ElementHelper.js.map +1 -0
  145. package/dist/helpers/VisionHelper.js +71 -0
  146. package/dist/helpers/VisionHelper.js.map +1 -0
  147. package/dist/helpers/decorators.js +38 -0
  148. package/dist/helpers/decorators.js.map +1 -0
  149. package/dist/vsn.d.ts +2 -1
  150. package/dist/vsn.js +166 -0
  151. package/dist/vsn.js.map +1 -0
  152. package/package.json +2 -6
  153. package/src/AST.ts +2 -2
  154. package/src/Attribute.ts +2 -2
  155. package/src/Configuration.ts +3 -3
  156. package/src/Controller.ts +1 -1
  157. package/src/DOM/DOMObject.ts +1 -1
  158. package/src/DOM.ts +3 -3
  159. package/src/EventDispatcher.ts +117 -0
  160. package/src/Formats.ts +2 -2
  161. package/src/MessageList.ts +81 -0
  162. package/src/Model/Collection.ts +13 -0
  163. package/src/Model/DataModel.ts +29 -0
  164. package/src/Model/ModelAbstract.ts +114 -0
  165. package/src/Model/fields/BooleanField.ts +16 -0
  166. package/src/Model/fields/EmailField.ts +12 -0
  167. package/src/Model/fields/Field.ts +65 -0
  168. package/src/Model/fields/FloatField.ts +22 -0
  169. package/src/Model/fields/PositiveNumberField.ts +24 -0
  170. package/src/Model/fields/StringField.ts +16 -0
  171. package/src/Model.ts +57 -0
  172. package/src/Registry.ts +3 -3
  173. package/src/Scope.ts +33 -89
  174. package/src/SimplePromise.ts +219 -0
  175. package/src/Tag.ts +2 -2
  176. package/src/attributes/Bind.ts +1 -1
  177. package/src/attributes/List.ts +3 -3
  178. package/src/attributes/Radio.ts +1 -1
  179. package/src/attributes/ScopeChange.ts +1 -1
  180. package/src/attributes/StandardAttribute.ts +1 -1
  181. package/src/attributes/StyleAttribute.ts +1 -1
  182. package/src/vsn.ts +3 -2
  183. package/test/AST.spec.ts +2 -1
  184. package/test/MessageList.spec.ts +101 -0
  185. package/test/Model/DataModel.spec.ts +141 -0
  186. package/test/Model.spec.ts +306 -0
  187. package/test/Scope.spec.ts +2 -2
  188. package/test/SimplePromise.spec.ts +271 -0
  189. package/test/attributes/Bind.spec.ts +5 -5
  190. package/test/attributes/ListItem.spec.ts +1 -1
  191. package/dist/vsn.min.js +0 -1
package/src/Registry.ts CHANGED
@@ -1,6 +1,6 @@
1
- import {EventDispatcher} from "simple-ts-event-dispatcher";
2
- import {IDeferred, IPromise, Promise as SimplePromise} from "simple-ts-promise";
3
1
  import {VisionHelper} from "./helpers/VisionHelper";
2
+ import {EventDispatcher} from "./EventDispatcher";
3
+ import {IDeferred, IPromise, SimplePromise} from "./SimplePromise";
4
4
 
5
5
  export function register(store: string, key: string = null, setup: () => void = null) {
6
6
  return function(target: any, _key: string = null) {
@@ -24,7 +24,7 @@ export class RegistryStore extends EventDispatcher {
24
24
 
25
25
  register(key: string, item: any) {
26
26
  this.store[key] = item;
27
- this.trigger(`registered:${key}`, item);
27
+ this.dispatch(`registered:${key}`, item);
28
28
  }
29
29
 
30
30
  get(key: string): IPromise<any> {
package/src/Scope.ts CHANGED
@@ -1,7 +1,8 @@
1
- import {DataModel, Model} from "simple-ts-models";
2
- import {EventCallback, EventCallbackList, EventDispatcher, EventDispatcherCallback} from "simple-ts-event-dispatcher";
3
1
  import {Registry} from "./Registry";
4
2
  import {DOM} from "./DOM";
3
+ import {EventDispatcher, EventDispatcherCallback} from "./EventDispatcher";
4
+ import {DataModel} from "./Model/DataModel";
5
+ import {Model} from "./Model";
5
6
 
6
7
  export class ScopeReference {
7
8
  private _scope: Scope;
@@ -64,26 +65,40 @@ export class ScopeVariableType {
64
65
  }
65
66
 
66
67
  export class WrappedArray<T> extends Array<T> {
67
- private _listeners: EventCallbackList;
68
- private _lastKey: number;
68
+ private dispatcher: EventDispatcher;
69
69
  public readonly $wrapped: boolean = true;
70
70
 
71
71
  constructor(...items: T[]) {
72
72
  super(...items);
73
73
  Object.setPrototypeOf(this, WrappedArray.prototype);
74
- this._lastKey = 0;
75
- this._listeners = {};
74
+ this.dispatcher = new EventDispatcher();
75
+ }
76
+
77
+ dispatch(event: string, ...args: any[]) {
78
+ this.dispatcher.dispatch(event, ...args);
79
+ }
80
+
81
+ on(event: string, callback: EventDispatcherCallback) {
82
+ this.dispatcher.on(event, callback);
83
+ }
84
+
85
+ off(event: string, key?: number) {
86
+ this.dispatcher.off(event, key);
87
+ }
88
+
89
+ once(event: string, callback: EventDispatcherCallback) {
90
+ this.dispatcher.once(event, callback);
76
91
  }
77
92
 
78
93
  push(...items: T[]): number {
79
94
  const num: number = super.push(...items);
80
95
 
81
- this.trigger('push', ...items);
82
- this.trigger('change', {
96
+ this.dispatch('push', ...items);
97
+ this.dispatch('change', {
83
98
  'added': items
84
99
  });
85
100
  for (const item of items) {
86
- this.trigger('add', item);
101
+ this.dispatch('add', item);
87
102
  }
88
103
  return num;
89
104
  }
@@ -91,11 +106,11 @@ export class WrappedArray<T> extends Array<T> {
91
106
  splice(start: number, deleteCount?: number): T[] {
92
107
  const removed: T[] = super.splice(start, deleteCount);
93
108
 
94
- this.trigger('change', {
109
+ this.dispatch('change', {
95
110
  'removed': removed
96
111
  });
97
112
  for (const item of removed) {
98
- this.trigger('remove', item);
113
+ this.dispatch('remove', item);
99
114
  }
100
115
 
101
116
  return removed;
@@ -134,77 +149,6 @@ export class WrappedArray<T> extends Array<T> {
134
149
  this.splice(this.indexOf(item), 1);
135
150
  }
136
151
  }
137
-
138
- bind(event: string, fct: EventDispatcherCallback, context?: any, once?: boolean): number {
139
- once = once || false;
140
- this._lastKey++;
141
- this._listeners[event] = this._listeners[event] || [];
142
- this._listeners[event].push(new EventCallback(fct, this._lastKey, once, context));
143
- return this._lastKey;
144
- }
145
-
146
- once(event: string, fct: EventDispatcherCallback, context?: any): number {
147
- return this.bind(event, fct, context, true);
148
- }
149
-
150
- unbind(event: string, key?: number): boolean {
151
- if(!(event in this._listeners)) return false;
152
- if(key) {
153
- for(const cb of this._listeners[event]) {
154
- if(key == cb.key) {
155
- this._listeners[event].splice(this._listeners[event].indexOf(cb), 1);
156
- return true;
157
- }
158
- }
159
- } else {
160
- this._listeners[event] = [];
161
- return true;
162
- }
163
- return false;
164
- }
165
-
166
- unbindWithContext(event: string, context: any): number {
167
- if(!(event in this._listeners)) return 0;
168
- let toRemove: EventCallback[] = [],
169
- cnt = 0;
170
-
171
- for(const cb of this._listeners[event]) {
172
- if(context == cb.context) {
173
- toRemove.push(cb);
174
- }
175
- }
176
-
177
- for(const cb of toRemove) {
178
- this._listeners[event].splice(this._listeners[event].indexOf(cb), 1);
179
- cnt++;
180
- }
181
- return cnt;
182
- }
183
-
184
- getListener(event: string, key: number): EventCallback | undefined {
185
- for(const cb of this._listeners[event]) {
186
- if(key == cb.key)
187
- return cb;
188
- }
189
- }
190
-
191
- trigger(event: string, ...args: any[]): void {
192
- if(!(event in this._listeners)) return;
193
-
194
- for(let i = 0; i < this._listeners[event].length; i++) {
195
- const cb: EventCallback = this._listeners[event][i];
196
-
197
- // We need to unbind callbacks before they're called to prevent
198
- // infinite loops if the event is somehow triggered within the
199
- // callback
200
- if(cb.once) {
201
- this.unbind(event, cb.key);
202
- i--;
203
- }
204
-
205
- cb.call(args);
206
- }
207
- }
208
152
  }
209
153
 
210
154
  export class Scope extends EventDispatcher {
@@ -307,8 +251,8 @@ export class Scope extends EventDispatcher {
307
251
  key: key
308
252
  };
309
253
 
310
- this.trigger(`change:${key}`, event);
311
- this.trigger('change', key, event);
254
+ this.dispatch(`change:${key}`, event);
255
+ this.dispatch('change', key, event);
312
256
  }
313
257
 
314
258
  if (this._keys.indexOf(key) === -1)
@@ -386,8 +330,8 @@ export class Scope extends EventDispatcher {
386
330
  if (!(this.wrapped[field] instanceof WrappedArray)) {
387
331
  this.wrapped[field] = new WrappedArray(...toWrap[field]);
388
332
  }
389
- this.wrapped[field].bind('change', (...args) => {
390
- this.trigger(`change:${field}`, ...args);
333
+ this.wrapped[field].on('change', (...args) => {
334
+ this.dispatch(`change:${field}`, ...args);
391
335
  })
392
336
  }
393
337
 
@@ -418,14 +362,14 @@ export class Scope extends EventDispatcher {
418
362
  });
419
363
 
420
364
  if (triggerUpdates)
421
- this.trigger(`change:${field}`);
365
+ this.dispatch(`change:${field}`);
422
366
  }
423
367
 
424
368
  this.wrapped.get = this.get.bind(this);
425
369
  this.wrapped.set = this.set.bind(this);
426
- this.wrapped.bind = this.bind.bind(this);
370
+ this.wrapped.bind = this.on.bind(this);
427
371
  this.wrapped.once = this.once.bind(this);
428
- this.wrapped.unbind = this.unbind.bind(this);
372
+ this.wrapped.unbind = this.off.bind(this);
429
373
  }
430
374
 
431
375
  public unwrap(): void {
@@ -0,0 +1,219 @@
1
+ import {EventDispatcher} from "./EventDispatcher";
2
+
3
+ export interface IDeferred<T> {
4
+ [key: string]: any;
5
+ promise: SimplePromise<T>;
6
+ resolve(result: T): void;
7
+ reject(reason: string): void;
8
+ }
9
+
10
+ export type TResolve<T> = (result: T) => void;
11
+ export type TReject = (reason: string) => void;
12
+ export type TResult<T> = T | string | null;
13
+
14
+ export enum EPromiseStates {
15
+ PENDING,
16
+ FULFILLED,
17
+ REJECTED
18
+ }
19
+
20
+ export interface IPromise<T> extends EventDispatcher {
21
+ state: EPromiseStates;
22
+ result: TResult<T>;
23
+ then<X = T>(success?: (result?: T) => X, error?: (reason?: string) => string): IPromise<X>;
24
+ catch(onRejected: (reason: string) => string): IPromise<string>;
25
+ finally<X = T>(finallyCallback: (result: T | string) => X | string): IPromise<X>;
26
+ }
27
+
28
+ export function noop<T = any>(result?: T): T { return result as T; }
29
+
30
+ export class SimplePromise<T> extends EventDispatcher implements IPromise<T> {
31
+ protected _state: EPromiseStates;
32
+ protected _result: TResult<T> = null;
33
+ private promiseClass: typeof SimplePromise;
34
+
35
+ constructor(executor: (resolve: TResolve<T>, reject: TReject) => void) {
36
+ super();
37
+ this._state = EPromiseStates.PENDING;
38
+ this.promiseClass = (Object.getPrototypeOf(this).constructor);
39
+ try {
40
+ executor(this._resolve.bind(this), this._reject.bind(this));
41
+ } catch (e) {
42
+ this._reject(e);
43
+ }
44
+ }
45
+
46
+ public get state(): EPromiseStates {
47
+ return this._state;
48
+ }
49
+
50
+ public get result(): TResult<T> {
51
+ return this._result;
52
+ }
53
+
54
+ public static defer<T>(): IDeferred<T> {
55
+ const promise: SimplePromise<T> = new SimplePromise<T>((res, rej) => {});
56
+
57
+ return {
58
+ promise: promise,
59
+ resolve: promise._resolve.bind(promise),
60
+ reject: promise._reject.bind(promise)
61
+ };
62
+ }
63
+
64
+ /*
65
+ * Returns a Promise object that is resolved with the given value. If the value is a thenable (i.e. has a then
66
+ * method), the returned promise will "follow" that thenable, adopting its eventual state; otherwise the returned
67
+ * promise will be fulfilled with the value. Generally, if you don't know if a value is a promise or not,
68
+ * Promise.resolve(value) it instead and work with the return value as a promise.
69
+ */
70
+ public static resolve<T>(result: T): IPromise<T> {
71
+ return new SimplePromise<T>((resolve: TResolve<T>): void => {
72
+ if (result instanceof SimplePromise) {
73
+ result.then((innerResult: T) => {
74
+ resolve(innerResult);
75
+ });
76
+ } else {
77
+ resolve(result);
78
+ }
79
+ });
80
+ }
81
+
82
+ /*
83
+ * Returns a Promise object that is rejected with the given reason.
84
+ */
85
+ public static reject(reason: string): IPromise<void> {
86
+ return new SimplePromise<void>((resolve: TResolve<void>, reject: TReject): void => {
87
+ reject(reason);
88
+ });
89
+ }
90
+
91
+ /*
92
+ * Returns a promise that either fulfills when all of the promises in the iterable argument have fulfilled or
93
+ * rejects as soon as one of the promises in the iterable argument rejects. If the returned promise fulfills, it is
94
+ * fulfilled with an array of the values from the fulfilled promises in the same order as defined in the iterable.
95
+ * If the returned promise rejects, it is rejected with the reason from the first promise in the iterable that
96
+ * rejected. This method can be useful for aggregating results of multiple promises.
97
+ */
98
+ public static all<T>(iter: IPromise<T>[]): IPromise<T[]> {
99
+ const deferred: IDeferred<T[]> = SimplePromise.defer<T[]>();
100
+ let done: boolean = true;
101
+ for (const promise of iter) {
102
+ if (promise.state == EPromiseStates.PENDING) {
103
+ done = false;
104
+ promise.once('fulfilled', (result: T): void => {
105
+ SimplePromise.poolResults(iter, deferred);
106
+ });
107
+
108
+ promise.once('rejected', (reason: string): void => {
109
+ deferred.reject(reason);
110
+ });
111
+ } else if(promise.state == EPromiseStates.REJECTED) {
112
+ deferred.reject(promise.result as string);
113
+ done = false;
114
+ break;
115
+ }
116
+ }
117
+
118
+ if (done)
119
+ SimplePromise.poolResults(iter, deferred);
120
+
121
+ return deferred.promise;
122
+ }
123
+
124
+ public static poolResults<T>(iter: IPromise<T>[], deferred: IDeferred<T[]>) {
125
+ let done: boolean = true;
126
+ const results: T[] = [];
127
+ for (const p of iter) {
128
+ if (p.state === EPromiseStates.REJECTED) {
129
+ deferred.reject(p.result as string);
130
+ break;
131
+ } else if (p.state === EPromiseStates.PENDING) {
132
+ done = false;
133
+ }
134
+ results.push(p.result as T);
135
+ }
136
+ if (done)
137
+ deferred.resolve(results);
138
+ }
139
+
140
+ /*
141
+ * Returns a promise that fulfills or rejects as soon as one of the promises in the iterable fulfills or rejects,
142
+ * with the value or reason from that promise.
143
+ */
144
+ public static race<T>(iter: IPromise<T>[]): IPromise<T> {
145
+ const deferred: IDeferred<T> = SimplePromise.defer<T>();
146
+
147
+ for (const promise of iter) {
148
+ promise.once('fulfilled', (result: T) => {
149
+ deferred.resolve(result);
150
+ });
151
+
152
+ promise.once('rejected', (reason: string) => {
153
+ deferred.reject(reason);
154
+ });
155
+ }
156
+
157
+ return deferred.promise;
158
+ }
159
+
160
+ /*
161
+ * Appends fulfillment and rejection handlers to the promise, and returns a new promise resolving to the return
162
+ * value of the called handler, or to its original settled value if the promise was not handled (i.e. if the
163
+ * relevant handler onFulfilled or onRejected is not a function).
164
+ */
165
+ public then<X = T>(success?: (result: T) => X, error?: (reason: string) => string): IPromise<X> {
166
+ return new this.promiseClass<X>((resolve: TResolve<X>, reject: TReject): void => {
167
+ if (this.state === EPromiseStates.FULFILLED) {
168
+ if (success)
169
+ resolve(success(this.result as T));
170
+ } else if (this.state === EPromiseStates.REJECTED) {
171
+ if (error)
172
+ reject(error(this.result as string));
173
+ } else {
174
+ this.once('fulfilled', (result: T): void => {
175
+ if (success)
176
+ resolve(success(result));
177
+ });
178
+
179
+ this.once('rejected', (reason: string): void => {
180
+ if (error)
181
+ reject(error(reason));
182
+ });
183
+ }
184
+ });
185
+ }
186
+
187
+ /*
188
+ * Appends a rejection handler callback to the promise, and returns a new promise resolving to the return value of
189
+ * the callback if it is called, or to its original fulfillment value if the promise is instead fulfilled.
190
+ */
191
+ public catch(onRejected: (reason: string) => string): IPromise<string> {
192
+ return this.then<string>(undefined, onRejected);
193
+ }
194
+
195
+ /*
196
+ * Appends a handler to the promise, and returns a new promise which is resolved when the original promise is
197
+ * resolved. The handler is called when the promise is settled, whether fulfilled or rejected.
198
+ */
199
+ public finally<X = T>(finallyCallback: (result: T | string) => X | string): IPromise<X> {
200
+ const success: (r: T) => X = (result: T): X => finallyCallback(result) as X;
201
+ const error: (r: string) => string = (reason: string): string => finallyCallback(reason) as string;
202
+
203
+ return this.then<X>(success, error);
204
+ }
205
+
206
+ protected _resolve(result: T): void {
207
+ if (this.state !== EPromiseStates.PENDING) return;
208
+ this._state = EPromiseStates.FULFILLED;
209
+ this._result = result;
210
+ this.dispatch('fulfilled', result);
211
+ }
212
+
213
+ protected _reject(reason: string): void {
214
+ if (this.state !== EPromiseStates.PENDING) return;
215
+ this._state = EPromiseStates.REJECTED;
216
+ this._result = reason;
217
+ this.dispatch('rejected', reason);
218
+ }
219
+ }
package/src/Tag.ts CHANGED
@@ -122,7 +122,7 @@ export class Tag extends DOMObject {
122
122
  for (const attr of this.attributes) {
123
123
  attr.mutate(mutation);
124
124
  }
125
- this.trigger('mutate', mutation);
125
+ this.dispatch('mutate', mutation);
126
126
  }
127
127
 
128
128
  public get(attr: string) {
@@ -348,7 +348,7 @@ export class Tag extends DOMObject {
348
348
  if (defer && attrClass.canDefer) {
349
349
  await attrObj.defer();
350
350
  this.deferredAttributes.push(attrObj);
351
- attrObj.bind('state', this.onAttributeStateChange.bind(this));
351
+ attrObj.on('state', this.onAttributeStateChange.bind(this));
352
352
  }
353
353
  }
354
354
  }
@@ -53,7 +53,7 @@ export class Bind extends Attribute {
53
53
  public async connect() {
54
54
  if (this.doUpdateTo) {
55
55
  this.updateTo();
56
- this.boundScope.bind(`change:${this.key}`, this.updateTo, this);
56
+ this.boundScope.on(`change:${this.key}`, this.updateTo, this);
57
57
  }
58
58
  await super.connect();
59
59
  }
@@ -84,10 +84,10 @@ export class List extends Attribute {
84
84
  this.items = new WrappedArray(this.items);
85
85
  }
86
86
 
87
- (this.items as WrappedArray<any>).bind('add', (item) => {
87
+ (this.items as WrappedArray<any>).on('add', (item) => {
88
88
  this.add(item);
89
89
  });
90
- (this.items as WrappedArray<any>).bind('remove', (item) => {
90
+ (this.items as WrappedArray<any>).on('remove', (item) => {
91
91
  this.remove(item);
92
92
  });
93
93
 
@@ -137,6 +137,6 @@ export class List extends Attribute {
137
137
  tag.wrap(obj);
138
138
  }
139
139
 
140
- this.tag.trigger('add', obj);
140
+ this.tag.dispatch('add', obj);
141
141
  }
142
142
  }
@@ -31,7 +31,7 @@ export class Radio extends Attribute {
31
31
  }
32
32
 
33
33
  public async connect() {
34
- this.boundScope.bind(`change:${this.key}`, this.checkSelected, this);
34
+ this.boundScope.on(`change:${this.key}`, this.checkSelected, this);
35
35
  this.tag.addEventHandler('change', this.getAttributeModifiers(), this.handleEvent.bind(this));
36
36
  await this.checkSelected();
37
37
  await super.connect();
@@ -18,7 +18,7 @@ export abstract class ScopeChange extends Attribute {
18
18
  public async connect() {
19
19
  const binding = this.getAttributeBinding();
20
20
  const ref: ScopeReference = this.tag.scope.getReference(binding, false);
21
- (await ref.getScope()).bind(`change:${await ref.getKey()}`, this.handleEvent.bind(this));
21
+ (await ref.getScope()).on(`change:${await ref.getKey()}`, this.handleEvent.bind(this));
22
22
  await super.connect();
23
23
  }
24
24
 
@@ -22,7 +22,7 @@ export class StandardAttribute extends Attribute {
22
22
  }
23
23
 
24
24
  public async connect() {
25
- this.tag.scope.bind(`change:${this.key}`, this.updateTo.bind(this));
25
+ this.tag.scope.on(`change:${this.key}`, this.updateTo.bind(this));
26
26
  await super.connect();
27
27
  }
28
28
 
@@ -28,7 +28,7 @@ export class StyleAttribute extends Attribute {
28
28
  }
29
29
 
30
30
  public async connect() {
31
- this.styleScope.bind(`change`, this.handleEvent.bind(this));
31
+ this.styleScope.on(`change`, this.handleEvent.bind(this));
32
32
  await super.connect();
33
33
  }
34
34
 
package/src/vsn.ts CHANGED
@@ -1,7 +1,5 @@
1
1
  import {DOM} from "./DOM";
2
- import {EventDispatcher} from "simple-ts-event-dispatcher";
3
2
  import {WrappedArray} from "./Scope";
4
- import {DataModel} from "simple-ts-models";
5
3
  import {Registry} from "./Registry";
6
4
  import "./Types";
7
5
  import "./Formats";
@@ -9,6 +7,8 @@ import {Configuration} from "./Configuration";
9
7
  import {VisionHelper} from "./helpers/VisionHelper";
10
8
  import {Tree} from "./AST";
11
9
  import {Query} from "./Query";
10
+ import {EventDispatcher} from "./EventDispatcher";
11
+ import {DataModel} from "./Model/DataModel";
12
12
 
13
13
  export class Vision extends EventDispatcher {
14
14
  protected static _instance: Vision;
@@ -74,4 +74,5 @@ export * from './AST';
74
74
  export {DOM} from './DOM';
75
75
  export {WrappedArray, Scope, ScopeReference} from './Scope';
76
76
  export {Controller} from './Controller';
77
+ export {Tag} from './Tag';
77
78
  export const vision: Vision = Vision.instance;
package/test/AST.spec.ts CHANGED
@@ -1,7 +1,8 @@
1
- import {Promise as SimplePromise, IDeferred} from 'simple-ts-promise';
1
+
2
2
  import {Scope, WrappedArray} from "../src/Scope";
3
3
  import {Tree} from "../src/AST";
4
4
  import {DOM} from "../src/DOM";
5
+ import {IDeferred, SimplePromise} from "../src/SimplePromise";
5
6
 
6
7
  describe('Tree', () => {
7
8
  let scope: Scope = null,
@@ -0,0 +1,101 @@
1
+ import MessageList from "../src/MessageList";
2
+
3
+ describe('MessageList', () => {
4
+ it("should reset properly", () => {
5
+ const list = new MessageList();
6
+ list.merge({
7
+ 'foo': ['bar', 'baz']
8
+ });
9
+ console.info(list.keys);
10
+ expect(list.length).toBe(1);
11
+ expect(list['foo']).toEqual(['bar', 'baz']);
12
+
13
+ list.reset();
14
+
15
+ expect(list.length).toBe(0);
16
+ expect(list['foo']).toEqual(undefined);
17
+ });
18
+
19
+ it("should add messages", () => {
20
+ const list = new MessageList({
21
+ 'foo': ['bar', 'baz']
22
+ });
23
+
24
+ // Add list
25
+ list.add('foo', ['biz', 'blarg']);
26
+ expect(list['foo']).toEqual(['bar', 'baz', 'biz', 'blarg']);
27
+
28
+ // Add single error and replace
29
+ list.add('foo', 'replaced', true);
30
+ expect(list['foo']).toEqual(['replaced']);
31
+ });
32
+
33
+ it("should merge messages", () => {
34
+ const list = new MessageList();
35
+ list.merge({
36
+ 'foo': ['bar', 'baz'],
37
+ 'test': ['test 1', 'test 2']
38
+ });
39
+
40
+ list.merge({
41
+ 'foo': ['merged 1', 'merged 2'],
42
+ 'test': ['test 3', 'test 4'],
43
+ 'new': ['new 1', 'new 2']
44
+ });
45
+
46
+ expect(list['foo']).toEqual(['bar', 'baz', 'merged 1', 'merged 2']);
47
+ expect(list['test']).toEqual(['test 1', 'test 2', 'test 3', 'test 4']);
48
+ expect(list['new']).toEqual(['new 1', 'new 2']);
49
+ });
50
+
51
+ it("should replace messages", () => {
52
+ const list = new MessageList();
53
+ list.merge({
54
+ 'foo': ['bar', 'baz'],
55
+ 'test': ['test 1', 'test 2']
56
+ });
57
+
58
+ list.merge({
59
+ 'foo': ['merged 1', 'merged 2'],
60
+ 'test': ['test 3', 'test 4'],
61
+ 'new': ['new 1', 'new 2']
62
+ }, true);
63
+
64
+ expect(list['foo']).toEqual(['merged 1', 'merged 2']);
65
+ expect(list['test']).toEqual(['test 3', 'test 4']);
66
+ expect(list['new']).toEqual(['new 1', 'new 2']);
67
+ });
68
+
69
+ it("should return a list", () => {
70
+ const list = new MessageList(),
71
+ items = {
72
+ 'foo': ['bar', 'baz'],
73
+ 'test': ['test 1', 'test 2']
74
+ };
75
+ list.merge(items);
76
+ expect(list.list).toEqual(items);
77
+ });
78
+
79
+ it("should ignore empty additions", () => {
80
+ const list = new MessageList();
81
+ list.merge({});
82
+ list.merge(null);
83
+ expect(list.length).toEqual(0);
84
+
85
+ list.merge({
86
+ 'empty': [],
87
+ 'null': null
88
+ });
89
+ expect(list.length).toEqual(0);
90
+ });
91
+
92
+ it("should cache list getter result", () => {
93
+ const messageList = new MessageList({
94
+ 'foo': ['bar', 'baz']
95
+ }),
96
+ list = messageList.list;
97
+ expect(list).toBe(messageList.list);
98
+ messageList.add('bar', 'baz');
99
+ expect(list).not.toBe(messageList.list);
100
+ });
101
+ });