vsn 0.1.22 → 0.1.26

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 (146) hide show
  1. package/demo/demo.html +16 -7
  2. package/demo/vsn.js +1 -0
  3. package/dist/AST.d.ts +2 -1
  4. package/dist/Controller.d.ts +9 -4
  5. package/dist/Model.d.ts +0 -0
  6. package/dist/attributes/Radio.d.ts +2 -0
  7. package/dist/attributes/StyleAttribute.d.ts +1 -0
  8. package/dist/{Vision.d.ts → vsn.d.ts} +1 -0
  9. package/dist/vsn.min.js +1 -0
  10. package/package.json +8 -8
  11. package/src/AST.ts +94 -3
  12. package/src/Controller.ts +15 -6
  13. package/src/DOM.ts +1 -1
  14. package/src/Model.ts +0 -0
  15. package/src/Registry.ts +0 -2
  16. package/src/Scope.ts +7 -2
  17. package/src/Tag.ts +10 -7
  18. package/src/attributes/ClickRemoveClass.ts +2 -0
  19. package/src/attributes/ClickToggleClass.ts +2 -0
  20. package/src/attributes/Exec.ts +2 -0
  21. package/src/attributes/Format.ts +1 -0
  22. package/src/attributes/If.ts +4 -0
  23. package/src/attributes/JSONAttribute.ts +1 -0
  24. package/src/attributes/KeyAbstract.ts +2 -1
  25. package/src/attributes/KeyDown.ts +1 -0
  26. package/src/attributes/KeyUp.ts +1 -0
  27. package/src/attributes/List.ts +3 -0
  28. package/src/attributes/ListItem.ts +1 -0
  29. package/src/attributes/On.ts +4 -0
  30. package/src/attributes/Radio.ts +17 -2
  31. package/src/attributes/RootAttribute.ts +1 -0
  32. package/src/attributes/ScopeChange.ts +2 -0
  33. package/src/attributes/SetAttribute.ts +1 -0
  34. package/src/attributes/StandardAttribute.ts +3 -0
  35. package/src/attributes/StyleAttribute.ts +1 -0
  36. package/src/attributes/TypeAttribute.ts +1 -0
  37. package/src/{Vision.ts → vsn.ts} +1 -0
  38. package/test/DOM.spec.ts +1 -1
  39. package/test/attributes/JSONAttribute.spec.ts +1 -1
  40. package/webpack.config.js +2 -2
  41. package/demo/vision.js +0 -1
  42. package/dist/AST.js +0 -2107
  43. package/dist/AST.js.map +0 -1
  44. package/dist/Attribute.js +0 -187
  45. package/dist/Attribute.js.map +0 -1
  46. package/dist/Bencmark.js +0 -179
  47. package/dist/Bencmark.js.map +0 -1
  48. package/dist/Configuration.js +0 -64
  49. package/dist/Configuration.js.map +0 -1
  50. package/dist/Controller.js +0 -39
  51. package/dist/Controller.js.map +0 -1
  52. package/dist/DOM/DOMObject.js +0 -47
  53. package/dist/DOM/DOMObject.js.map +0 -1
  54. package/dist/DOM/WrappedDocument.js +0 -34
  55. package/dist/DOM/WrappedDocument.js.map +0 -1
  56. package/dist/DOM/WrappedWindow.js +0 -45
  57. package/dist/DOM/WrappedWindow.js.map +0 -1
  58. package/dist/DOM.js +0 -547
  59. package/dist/DOM.js.map +0 -1
  60. package/dist/Formats.js +0 -44
  61. package/dist/Formats.js.map +0 -1
  62. package/dist/Query.js +0 -66
  63. package/dist/Query.js.map +0 -1
  64. package/dist/Registry.js +0 -138
  65. package/dist/Registry.js.map +0 -1
  66. package/dist/Scope.js +0 -512
  67. package/dist/Scope.js.map +0 -1
  68. package/dist/Tag/List.js +0 -85
  69. package/dist/Tag/List.js.map +0 -1
  70. package/dist/Tag.js +0 -764
  71. package/dist/Tag.js.map +0 -1
  72. package/dist/Types.js +0 -48
  73. package/dist/Types.js.map +0 -1
  74. package/dist/Vision.js +0 -162
  75. package/dist/Vision.js.map +0 -1
  76. package/dist/attributes/AddClassIf.js +0 -93
  77. package/dist/attributes/AddClassIf.js.map +0 -1
  78. package/dist/attributes/Bind.js +0 -272
  79. package/dist/attributes/Bind.js.map +0 -1
  80. package/dist/attributes/ClassConstructor.js +0 -104
  81. package/dist/attributes/ClassConstructor.js.map +0 -1
  82. package/dist/attributes/ClickRemoveClass.js +0 -102
  83. package/dist/attributes/ClickRemoveClass.js.map +0 -1
  84. package/dist/attributes/ClickToggleClass.js +0 -102
  85. package/dist/attributes/ClickToggleClass.js.map +0 -1
  86. package/dist/attributes/ControllerAttribute.js +0 -28
  87. package/dist/attributes/ControllerAttribute.js.map +0 -1
  88. package/dist/attributes/DisableIf.js +0 -94
  89. package/dist/attributes/DisableIf.js.map +0 -1
  90. package/dist/attributes/Exec.js +0 -102
  91. package/dist/attributes/Exec.js.map +0 -1
  92. package/dist/attributes/Format.js +0 -96
  93. package/dist/attributes/Format.js.map +0 -1
  94. package/dist/attributes/If.js +0 -147
  95. package/dist/attributes/If.js.map +0 -1
  96. package/dist/attributes/JSONAttribute.js +0 -115
  97. package/dist/attributes/JSONAttribute.js.map +0 -1
  98. package/dist/attributes/KeyAbstract.js +0 -110
  99. package/dist/attributes/KeyAbstract.js.map +0 -1
  100. package/dist/attributes/KeyDown.js +0 -82
  101. package/dist/attributes/KeyDown.js.map +0 -1
  102. package/dist/attributes/KeyUp.js +0 -82
  103. package/dist/attributes/KeyUp.js.map +0 -1
  104. package/dist/attributes/List.js +0 -273
  105. package/dist/attributes/List.js.map +0 -1
  106. package/dist/attributes/ListItem.js +0 -135
  107. package/dist/attributes/ListItem.js.map +0 -1
  108. package/dist/attributes/ListItemModel.js +0 -39
  109. package/dist/attributes/ListItemModel.js.map +0 -1
  110. package/dist/attributes/ModelAttribute.js +0 -29
  111. package/dist/attributes/ModelAttribute.js.map +0 -1
  112. package/dist/attributes/Name.js +0 -88
  113. package/dist/attributes/Name.js.map +0 -1
  114. package/dist/attributes/On.js +0 -123
  115. package/dist/attributes/On.js.map +0 -1
  116. package/dist/attributes/Radio.js +0 -127
  117. package/dist/attributes/Radio.js.map +0 -1
  118. package/dist/attributes/Referenced.js +0 -38
  119. package/dist/attributes/Referenced.js.map +0 -1
  120. package/dist/attributes/RootAttribute.js +0 -85
  121. package/dist/attributes/RootAttribute.js.map +0 -1
  122. package/dist/attributes/ScopeAttribute.js +0 -40
  123. package/dist/attributes/ScopeAttribute.js.map +0 -1
  124. package/dist/attributes/ScopeChange.js +0 -124
  125. package/dist/attributes/ScopeChange.js.map +0 -1
  126. package/dist/attributes/SetAttribute.js +0 -130
  127. package/dist/attributes/SetAttribute.js.map +0 -1
  128. package/dist/attributes/StandardAttribute.js +0 -168
  129. package/dist/attributes/StandardAttribute.js.map +0 -1
  130. package/dist/attributes/StyleAttribute.js +0 -182
  131. package/dist/attributes/StyleAttribute.js.map +0 -1
  132. package/dist/attributes/Template.js +0 -39
  133. package/dist/attributes/Template.js.map +0 -1
  134. package/dist/attributes/TypeAttribute.js +0 -101
  135. package/dist/attributes/TypeAttribute.js.map +0 -1
  136. package/dist/attributes/_imports.js +0 -60
  137. package/dist/attributes/_imports.js.map +0 -1
  138. package/dist/helpers/DOMHelper.js +0 -81
  139. package/dist/helpers/DOMHelper.js.map +0 -1
  140. package/dist/helpers/ElementHelper.js +0 -25
  141. package/dist/helpers/ElementHelper.js.map +0 -1
  142. package/dist/helpers/VisionHelper.js +0 -71
  143. package/dist/helpers/VisionHelper.js.map +0 -1
  144. package/dist/helpers/decorators.js +0 -38
  145. package/dist/helpers/decorators.js.map +0 -1
  146. package/main.py +0 -16
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "vsn",
3
- "version": "0.1.22",
3
+ "version": "0.1.26",
4
4
  "description": "SEO Friendly Javascript/Typescript Framework",
5
5
  "keywords": [
6
6
  "framework",
7
7
  "typescript"
8
8
  ],
9
- "main": "./dist/Vision.js",
9
+ "main": "./dist/vsn.js",
10
10
  "scripts": {
11
11
  "build": "rm -rf ./dist/ && tsc",
12
12
  "build_dev": "rm -rf ./dist/ && webpack --env BUILD=development BENCHMARK=1",
13
- "demo": "rm -rf ./dist/ && webpack --env BUILD=production BENCHMARK=1 && cp ./dist/vision.min.js ./demo/vision.js",
13
+ "demo": "rm -rf ./dist/ && webpack --env BUILD=production BENCHMARK=1 && cp ./dist/vsn.min.js ./demo/vsn.js",
14
14
  "clean": "rm -rf ./dist/",
15
15
  "test": "karma start --single-run",
16
16
  "posttest": "codecov",
@@ -37,16 +37,16 @@
37
37
  "webpack-cli": "^4.6.0"
38
38
  },
39
39
  "homepage": "https://www.vsnjs.com",
40
- "git": "https://github.com/malero/visionjs",
41
- "typings": "./dist/Vision.d.ts",
42
- "types": "./dist/Vision.d.ts",
40
+ "git": "https://github.com/malero/vsn.git",
41
+ "typings": "./dist/vsn.d.ts",
42
+ "types": "./dist/vsn.d.ts",
43
43
  "author": "Malero <contact@vsnjs.com> (https://www.vsnjs.com/)",
44
44
  "bugs": {
45
- "url": "https://github.com/malero/visionjs/issues",
45
+ "url": "https://github.com/malero/vsn/issues",
46
46
  "email": "contact@vsnjs.com"
47
47
  },
48
48
  "repository": {
49
49
  "type": "git",
50
- "url": "https://github.com/malero/visionjs.git"
50
+ "url": "https://github.com/malero/vsn.git"
51
51
  }
52
52
  }
package/src/AST.ts CHANGED
@@ -78,7 +78,8 @@ export enum TokenType {
78
78
  ELEMENT_REFERENCE,
79
79
  ELEMENT_ATTRIBUTE,
80
80
  ELEMENT_STYLE,
81
- ELEMENT_QUERY
81
+ ELEMENT_QUERY,
82
+ UNIT,
82
83
  }
83
84
 
84
85
  const TOKEN_PATTERNS: TokenPattern[] = [
@@ -98,6 +99,10 @@ const TOKEN_PATTERNS: TokenPattern[] = [
98
99
  type: TokenType.TYPE_FLOAT,
99
100
  pattern: /^float+/
100
101
  },
102
+ {
103
+ type: TokenType.UNIT,
104
+ pattern: /^\d+\.?\d?(?:cm|mm|in|px|pt|pc|em|ex|ch|rem|vw|vh|vmin|vmax|%)/
105
+ },
101
106
  {
102
107
  type: TokenType.TYPE_STRING,
103
108
  pattern: /^string+/
@@ -144,11 +149,11 @@ const TOKEN_PATTERNS: TokenPattern[] = [
144
149
  },
145
150
  {
146
151
  type: TokenType.ELEMENT_ATTRIBUTE,
147
- pattern: /^\.?@[_a-zA-Z0-9]*/
152
+ pattern: /^\.?@[-_a-zA-Z0-9]*/
148
153
  },
149
154
  {
150
155
  type: TokenType.ELEMENT_STYLE,
151
- pattern: /^\.?\$[a-zA-Z0-9]*/
156
+ pattern: /^\.?\$[-a-zA-Z0-9]*/
152
157
  },
153
158
  {
154
159
  type: TokenType.ELEMENT_REFERENCE,
@@ -687,6 +692,55 @@ class NumberLiteralNode extends LiteralNode<number> {
687
692
  }
688
693
  }
689
694
 
695
+ class UnitLiteral {
696
+ protected _amount: number;
697
+ protected _unit: string;
698
+
699
+ constructor(
700
+ protected _value: any
701
+ ) {
702
+ this.value = this._value;
703
+ }
704
+
705
+ get amount(): number {
706
+ return this._amount;
707
+ }
708
+
709
+ get unit(): string {
710
+ return this._unit;
711
+ }
712
+
713
+ get value(): string {
714
+ return `${this._amount}${this._unit}`;
715
+ }
716
+
717
+ set value(value: string) {
718
+ if (value.indexOf('.') > -1) {
719
+ this._amount = parseFloat(value)
720
+ } else {
721
+ this._amount = parseInt(value);
722
+ }
723
+
724
+ if (isNaN(this._amount))
725
+ this._amount = 0;
726
+
727
+ const unit = /[^\d.]+$/.exec(value);
728
+ this._unit = unit && unit[0] || '';
729
+ }
730
+
731
+ public toString() {
732
+ return this.value;
733
+ }
734
+ }
735
+
736
+ class UnitLiteralNode extends LiteralNode<UnitLiteral> {
737
+ constructor(
738
+ _value: any
739
+ ) {
740
+ super(new UnitLiteral(_value));
741
+ }
742
+ }
743
+
690
744
 
691
745
  class FunctionCallNode<T = any> extends Node implements TreeNode {
692
746
  constructor(
@@ -895,6 +949,8 @@ class ArithmeticAssignmentNode extends Node implements TreeNode {
895
949
 
896
950
  if (left instanceof Array) {
897
951
  left = this.handleArray(name, left, right, localScope);
952
+ } else if ((left as any) instanceof UnitLiteral || right instanceof UnitLiteral) {
953
+ left = this.handleUnit(name, left, right, localScope);
898
954
  } else if (Number.isFinite(left)) {
899
955
  left = this.handleNumber(name, left, right, localScope);
900
956
  } else {
@@ -958,6 +1014,38 @@ class ArithmeticAssignmentNode extends Node implements TreeNode {
958
1014
  return left;
959
1015
  }
960
1016
 
1017
+ public handleUnit(key, left, right, scope) {
1018
+ if (!(left instanceof UnitLiteral)) {
1019
+ left = new UnitLiteral(left);
1020
+ }
1021
+
1022
+ if (!(right instanceof UnitLiteral)) {
1023
+ right = new UnitLiteral(right);
1024
+ }
1025
+ const unit = left.unit || right.unit || 'px';
1026
+
1027
+ switch (this.type) {
1028
+ case TokenType.ASSIGN:
1029
+ left = right;
1030
+ break;
1031
+ case TokenType.ADD_ASSIGN:
1032
+ left = new UnitLiteral(`${left.amount+right.amount}${unit}`);
1033
+ break;
1034
+ case TokenType.SUBTRACT_ASSIGN:
1035
+ left = new UnitLiteral(`${left.amount-right.amount}${unit}`);
1036
+ break;
1037
+ case TokenType.MULTIPLY_ASSIGN:
1038
+ left = new UnitLiteral(`${left.amount*right.amount}${unit}`);
1039
+ break;
1040
+ case TokenType.DIVIDE_ASSIGN:
1041
+ left = new UnitLiteral(`${left.amount/right.amount}${unit}`);
1042
+ break;
1043
+ }
1044
+
1045
+ scope.set(key, left);
1046
+ return left;
1047
+ }
1048
+
961
1049
  public async handleDOMObject(key: string, dom: DOM, domObject: DOMObject, tag: Tag) {
962
1050
  let left = domObject.scope.get(key);
963
1051
  let right: number | Array<any> | string = await this.right.evaluate(domObject.scope, dom, tag);
@@ -1486,6 +1574,9 @@ export class Tree {
1486
1574
  node = ArithmeticAssignmentNode.parse(node, token, tokens);
1487
1575
  } else if (tokens[0].type === TokenType.WHITESPACE) {
1488
1576
  tokens.splice(0, 1);
1577
+ } else if (tokens[0].type === TokenType.UNIT) {
1578
+ node = new UnitLiteralNode(tokens[0].value);
1579
+ tokens.splice(0, 1);
1489
1580
  } else if (tokens[0].type === TokenType.BOOLEAN_LITERAL) {
1490
1581
  node = new BooleanLiteralNode(tokens[0].value);
1491
1582
  tokens.splice(0, 1);
package/src/Controller.ts CHANGED
@@ -1,18 +1,27 @@
1
1
  import {EventDispatcher} from "simple-ts-event-dispatcher";
2
+ import {Scope} from "./Scope";
3
+ import {Tag} from "./Tag";
2
4
 
3
5
  export abstract class Controller extends EventDispatcher {
4
- protected _tag: any;
6
+ protected _scope: Scope;
7
+ protected _tag: Tag;
8
+ protected _element: HTMLElement;
5
9
 
6
- protected constructor() {
7
- super();
10
+ public get scope(): Scope {
11
+ return this._scope;
8
12
  }
9
13
 
10
- public get tag(): any {
14
+ public get tag(): Tag {
11
15
  return this._tag;
12
16
  }
13
17
 
14
- public set tag(tag: any) {
18
+ public get element(): HTMLElement {
19
+ return this._element;
20
+ }
21
+
22
+ public init(scope: Scope, tag: Tag, element: HTMLElement): void {
23
+ this._scope = scope;
15
24
  this._tag = tag;
16
- this.trigger('tag', tag);
25
+ this._element = element;
17
26
  }
18
27
  }
package/src/DOM.ts CHANGED
@@ -183,7 +183,7 @@ export class DOM extends EventDispatcher {
183
183
  if (tag === this.root)
184
184
  continue;
185
185
 
186
- // Find closest ancestor
186
+ // Find the closest ancestor
187
187
  let parentElement: HTMLElement = tag.element.parentElement as HTMLElement;
188
188
  let foundParent = false;
189
189
  while (parentElement) {
package/src/Model.ts ADDED
File without changes
package/src/Registry.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import {EventDispatcher} from "simple-ts-event-dispatcher";
2
2
  import {IDeferred, IPromise, Promise as SimplePromise} from "simple-ts-promise";
3
3
  import {VisionHelper} from "./helpers/VisionHelper";
4
- import {benchmark} from "./Bencmark";
5
4
 
6
5
  export function register(store: string, key: string = null, setup: () => void = null) {
7
6
  return function(target: any, _key: string = null) {
@@ -28,7 +27,6 @@ export class RegistryStore extends EventDispatcher {
28
27
  this.trigger(`registered:${key}`, item);
29
28
  }
30
29
 
31
- @benchmark('RegistryStore.get')
32
30
  get(key: string): IPromise<any> {
33
31
  const deferred: IDeferred<any> = SimplePromise.defer();
34
32
 
package/src/Scope.ts CHANGED
@@ -1,4 +1,4 @@
1
- import {DataModel} from "simple-ts-models";
1
+ import {DataModel, Model} from "simple-ts-models";
2
2
  import {EventCallback, EventCallbackList, EventDispatcher, EventDispatcherCallback} from "simple-ts-event-dispatcher";
3
3
  import {Registry} from "./Registry";
4
4
  import {DOM} from "./DOM";
@@ -276,7 +276,7 @@ export class Scope extends EventDispatcher {
276
276
  if (searchParents && this.parentScope)
277
277
  return this.parentScope.get(key, searchParents);
278
278
 
279
- return this._keys.indexOf(key) > -1 ? '' : undefined;
279
+ return '';
280
280
  }
281
281
 
282
282
  return value;
@@ -352,6 +352,11 @@ export class Scope extends EventDispatcher {
352
352
  }
353
353
 
354
354
  public wrap(toWrap: any, triggerUpdates: boolean = false, updateFromWrapped: boolean = true) {
355
+ if (toWrap instanceof Model) {
356
+ this.data = toWrap;
357
+ return;
358
+ }
359
+
355
360
  if (toWrap instanceof Scope)
356
361
  toWrap = toWrap.data;
357
362
 
package/src/Tag.ts CHANGED
@@ -8,7 +8,7 @@ import {On} from "./attributes/On";
8
8
  import {Registry} from "./Registry";
9
9
  import {benchmarkEnd, benchmarkStart} from "./Bencmark";
10
10
  import {DOMObject} from "./DOM/DOMObject";
11
- import { Tree } from "./AST";
11
+ import {Tree} from "./AST";
12
12
  import {StyleAttribute} from "./attributes/StyleAttribute";
13
13
 
14
14
  export enum TagState {
@@ -251,10 +251,14 @@ export class Tag extends DOMObject {
251
251
  obj = new obj();
252
252
  }
253
253
 
254
- this.scope.wrap(obj, triggerUpdates, updateFromWrapped);
255
- obj['$scope'] = this.scope;
256
- obj['$tag'] = this;
257
- obj['$el'] = this.element;
254
+ if (obj instanceof Controller) {
255
+ obj.init(this.scope, this, this.element);
256
+ } else {
257
+ this.scope.wrap(obj, triggerUpdates, updateFromWrapped);
258
+ obj['$scope'] = this.scope;
259
+ obj['$tag'] = this;
260
+ obj['$el'] = this.element;
261
+ }
258
262
  return obj;
259
263
  }
260
264
 
@@ -428,8 +432,7 @@ export class Tag extends DOMObject {
428
432
 
429
433
  this.scope.set('$event', e);
430
434
  this.scope.set('$value', this.value);
431
- for (const handler of this.onEventHandlers[eventType])
432
- {
435
+ for (const handler of this.onEventHandlers[eventType]) {
433
436
  handler(e);
434
437
  }
435
438
  }
@@ -9,10 +9,12 @@ export class ClickRemoveClass extends Attribute {
9
9
  public async setup() {
10
10
  this.cssClass = this.getAttributeBinding('active');
11
11
  this.target = this.getAttributeValue();
12
+ await super.setup();
12
13
  }
13
14
 
14
15
  public async connect() {
15
16
  this.tag.addEventHandler('click', this.getAttributeModifiers(), this.onClick.bind(this));
17
+ await super.connect();
16
18
  }
17
19
 
18
20
  onClick(e) {
@@ -9,10 +9,12 @@ export class ClickToggleClass extends Attribute {
9
9
  public async setup() {
10
10
  this.cssClass = this.getAttributeBinding( 'active');
11
11
  this.target = this.getAttributeValue();
12
+ await super.setup();
12
13
  }
13
14
 
14
15
  public async connect() {
15
16
  this.tag.addEventHandler('click', this.getAttributeModifiers(), this.onClick.bind(this));
17
+ await super.connect();
16
18
  }
17
19
 
18
20
  onClick(e) {
@@ -10,9 +10,11 @@ export class Exec extends Attribute {
10
10
  public async compile() {
11
11
  this.tree = new Tree(this.getAttributeValue());
12
12
  await this.tree.prepare(this.tag.scope, this.tag.dom, this.tag);
13
+ await super.compile();
13
14
  }
14
15
 
15
16
  public async extract() {
16
17
  await this.tree.evaluate(this.tag.scope, this.tag.dom, this.tag);
18
+ await super.extract();
17
19
  }
18
20
  }
@@ -13,5 +13,6 @@ export class Format extends Attribute {
13
13
  const bindingKey = attribute ? `vsn-bind:${attribute}` : 'vsn-bind';
14
14
  const binding: Bind = await this.tag.getAttribute<Bind>(bindingKey);
15
15
  binding.setFormatter(formatter);
16
+ await super.extract();
16
17
  }
17
18
  }
@@ -11,18 +11,22 @@ export class If extends Attribute {
11
11
  const statement: string = this.getAttributeValue();
12
12
  this.tree = new Tree(statement);
13
13
  await this.tree.prepare(this.tag.scope, this.tag.dom, this.tag);
14
+ await super.compile();
14
15
  }
15
16
 
16
17
  public async extract() {
17
18
  await this.evaluate();
19
+ await super.extract();
18
20
  }
19
21
 
20
22
  public async connect() {
21
23
  await this.tree.bindToScopeChanges(this.tag.scope, this.onChange.bind(this), this.tag.dom, this.tag);
24
+ await super.connect();
22
25
  }
23
26
 
24
27
  public async evaluate() {
25
28
  await this.onChange();
29
+ await super.evaluate();
26
30
  }
27
31
 
28
32
  async onChange() {
@@ -34,5 +34,6 @@ export class JSONAttribute extends Attribute {
34
34
  }
35
35
 
36
36
  scope.set(key, data);
37
+ await super.extract();
37
38
  }
38
39
  }
@@ -4,12 +4,13 @@ export abstract class KeyAbstract extends On {
4
4
  protected specificKey: string = null;
5
5
 
6
6
  public async compile() {
7
- await super.compile();
8
7
  this.specificKey = this.getAttributeBinding();
8
+ await super.compile();
9
9
  }
10
10
 
11
11
  public async connect() {
12
12
  this.tag.addEventHandler('keydown', this.getAttributeModifiers(), this.handleEvent.bind(this));
13
+ await super.connect();
13
14
  }
14
15
 
15
16
  public async handleEvent(e) {
@@ -5,5 +5,6 @@ import {Registry} from "../Registry";
5
5
  export class KeyDown extends KeyAbstract {
6
6
  public async connect() {
7
7
  this.tag.addEventHandler('keydown', this.getAttributeModifiers(), this.handleEvent.bind(this));
8
+ await super.connect();
8
9
  }
9
10
  }
@@ -5,5 +5,6 @@ import {Registry} from "../Registry";
5
5
  export class KeyUp extends KeyAbstract {
6
6
  public async connect() {
7
7
  this.tag.addEventHandler('keyup', this.getAttributeModifiers(), this.handleEvent.bind(this));
8
+ await super.connect();
8
9
  }
9
10
  }
@@ -19,6 +19,7 @@ export class List extends Attribute {
19
19
  const listAttr: string = this.getAttributeBinding();
20
20
  this.tree = new Tree(listAttr);
21
21
  await this.tree.prepare(this.tag.scope, this.tag.dom, this.tag);
22
+ await super.compile();
22
23
  }
23
24
 
24
25
  public async setup() {
@@ -43,6 +44,7 @@ export class List extends Attribute {
43
44
  this.template = templateNode.element.content.cloneNode(true);
44
45
  }
45
46
  }
47
+ await super.setup();
46
48
  }
47
49
 
48
50
  public async extract() {
@@ -55,6 +57,7 @@ export class List extends Attribute {
55
57
  await this.add({});
56
58
  }
57
59
  }
60
+ await super.extract();
58
61
  }
59
62
 
60
63
  protected async addExistingItems(defaultList: any[] | null) {
@@ -23,6 +23,7 @@ export class ListItem extends Attribute {
23
23
  const modelName: string = (await this.getList()).listItemModel;
24
24
  const cls = await Registry.instance.classes.get(modelName);
25
25
  this.instantiateModel(cls);
26
+ await super.setup();
26
27
  }
27
28
 
28
29
  public get listItemName(): string {
@@ -22,13 +22,17 @@ export abstract class On extends Attribute {
22
22
  const code: string = this.getAttributeValue();
23
23
  this.handler = new Tree(code);
24
24
  await this.handler.prepare(this.tag.scope, this.tag.dom, this.tag);
25
+ await super.compile();
25
26
  }
26
27
 
27
28
  async handleEvent(e) {
29
+ if (this.hasModifier('preventdefault'))
30
+ e.preventDefault();
28
31
  await this.handler.evaluate(this.tag.scope, this.tag.dom, this.tag);
29
32
  }
30
33
 
31
34
  public async connect() {
32
35
  this.tag.addEventHandler(this.getAttributeBinding(), this.getAttributeModifiers(), this.handleEvent.bind(this));
36
+ await super.connect();
33
37
  }
34
38
  }
@@ -9,7 +9,7 @@ export class Radio extends Attribute {
9
9
  protected key?: string;
10
10
  protected boundScope?: Scope;
11
11
 
12
- public async extract() {
12
+ public async setup() {
13
13
  let scopeKey: string = this.getAttributeValue() || this.tag.getRawAttributeValue('name');
14
14
  let ref: ScopeReference;
15
15
  try {
@@ -21,11 +21,25 @@ export class Radio extends Attribute {
21
21
 
22
22
  this.key = await ref.getKey();
23
23
  this.boundScope = await ref.getScope();
24
+ await super.setup();
25
+ }
26
+
27
+ public async extract() {
28
+ if (this.tag.checked)
29
+ await this.handleEvent(null);
30
+ await super.extract();
24
31
  }
25
32
 
26
33
  public async connect() {
27
34
  this.boundScope.bind(`change:${this.key}`, this.checkSelected, this);
28
35
  this.tag.addEventHandler('change', this.getAttributeModifiers(), this.handleEvent.bind(this));
36
+ await this.checkSelected();
37
+ await super.connect();
38
+ }
39
+
40
+ public async evaluate() {
41
+ await this.checkSelected();
42
+ await super.evaluate();
29
43
  }
30
44
 
31
45
  async handleEvent(e) {
@@ -33,6 +47,7 @@ export class Radio extends Attribute {
33
47
  }
34
48
 
35
49
  async checkSelected() {
36
- this.tag.checked = this.boundScope.get(this.key) === this.tag.value;
50
+ const scopeValue = this.boundScope.get(this.key);
51
+ this.tag.checked = `${scopeValue}` === this.tag.value;
37
52
  }
38
53
  }
@@ -9,5 +9,6 @@ export class RootAttribute extends Attribute {
9
9
 
10
10
  public async setup() {
11
11
  this.tag.scope.set('$mobile', VisionHelper.isMobile());
12
+ await super.setup();
12
13
  }
13
14
  }
@@ -12,12 +12,14 @@ export abstract class ScopeChange extends Attribute {
12
12
  const code: string = this.getAttributeValue();
13
13
  this.handler = new Tree(code);
14
14
  await this.handler.prepare(this.tag.scope, this.tag.dom, this.tag);
15
+ await super.compile();
15
16
  }
16
17
 
17
18
  public async connect() {
18
19
  const binding = this.getAttributeBinding();
19
20
  const ref: ScopeReference = this.tag.scope.getReference(binding, false);
20
21
  (await ref.getScope()).bind(`change:${await ref.getKey()}`, this.handleEvent.bind(this));
22
+ await super.connect();
21
23
  }
22
24
 
23
25
  async handleEvent(e) {
@@ -30,6 +30,7 @@ export class SetAttribute extends Attribute {
30
30
  }
31
31
  this.key = await ref.getKey();
32
32
  this.boundScope = await ref.getScope();
33
+ await super.setup();
33
34
  }
34
35
 
35
36
  public async extract() {
@@ -13,14 +13,17 @@ export class StandardAttribute extends Attribute {
13
13
  if (StandardAttribute.magicAttributes.indexOf(this.key) === -1 && !this.tag.element.hasAttribute(this.attributeName)) {
14
14
  this.tag.element.setAttribute(this.attributeName, '');
15
15
  }
16
+ await super.setup();
16
17
  }
17
18
 
18
19
  public async extract() {
19
20
  this.updateFrom();
21
+ await super.extract();
20
22
  }
21
23
 
22
24
  public async connect() {
23
25
  this.tag.scope.bind(`change:${this.key}`, this.updateTo.bind(this));
26
+ await super.connect();
24
27
  }
25
28
 
26
29
  public mutate(mutation: MutationRecord) {
@@ -5,6 +5,7 @@ import {Scope, ScopeReference} from "../Scope";
5
5
 
6
6
  @Registry.attribute('vsn-styles')
7
7
  export class StyleAttribute extends Attribute {
8
+ public static readonly canDefer: boolean = false;
8
9
  private scopeRef: ScopeReference;
9
10
  private styleScope: Scope;
10
11
 
@@ -18,5 +18,6 @@ export class TypeAttribute extends Attribute {
18
18
  }
19
19
 
20
20
  (await ref.getScope()).setType(await ref.getKey(), type);
21
+ await super.extract();
21
22
  }
22
23
  }
@@ -73,4 +73,5 @@ export * from './Attribute';
73
73
  export * from './AST';
74
74
  export {DOM} from './DOM';
75
75
  export {WrappedArray, Scope, ScopeReference} from './Scope';
76
+ export {Controller} from './Controller';
76
77
  export const vision: Vision = Vision.instance;
package/test/DOM.spec.ts CHANGED
@@ -1,4 +1,4 @@
1
- import "../src/Vision";
1
+ import "../src/vsn";
2
2
  import {DOM} from "../src/DOM";
3
3
  import {Registry} from "../src/Registry";
4
4
 
@@ -77,7 +77,7 @@ describe('JSONAttribute', () => {
77
77
  it("vsn-json should work with a ref path", (done) => {
78
78
  document.body.innerHTML = `
79
79
  <div vsn-name="testing">
80
- <div vsn-json:testing.test="{&quot;testing&quot;: 123}"></div>
80
+ <div vsn-json:testing.test='{"testing": 123}'></div>
81
81
  </div>
82
82
  `;
83
83
  const dom = new DOM(document);
package/webpack.config.js CHANGED
@@ -2,7 +2,7 @@ const path = require('path');
2
2
  const webpack = require("webpack");
3
3
 
4
4
  const defaultConfiguration = {
5
- entry: './src/Vision.ts',
5
+ entry: './src/vsn.ts',
6
6
  module: {
7
7
  rules: [
8
8
  {
@@ -17,7 +17,7 @@ const defaultConfiguration = {
17
17
  },
18
18
  plugins: [],
19
19
  output: {
20
- filename: 'vision.min.js',
20
+ filename: 'vsn.min.js',
21
21
  path: path.resolve(__dirname, 'dist'),
22
22
  },
23
23
  };