vsn 0.1.124 → 0.1.125

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.
@@ -5,12 +5,14 @@ import {Token, TokenType, Tree, TreeNode} from "../AST";
5
5
  import {Node} from "./Node";
6
6
  import {ObjectNode} from "./ObjectNode";
7
7
  import {ScopeData} from "../Scope/ScopeData";
8
+ import {ElementQueryNode} from "./ElementQueryNode";
8
9
 
9
10
  export class DispatchEventNode extends Node implements TreeNode {
10
11
  constructor(
11
12
  public readonly name: string,
12
13
  public readonly data: ObjectNode | null,
13
- public readonly bubbles: boolean = false
14
+ public readonly bubbles: boolean = false,
15
+ public readonly elementRef: ElementQueryNode | null,
14
16
  ) {
15
17
  super();
16
18
  }
@@ -23,28 +25,34 @@ export class DispatchEventNode extends Node implements TreeNode {
23
25
  }
24
26
 
25
27
  public async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
26
- let detail = this.data ? await this.data.evaluate(scope, dom, tag) : {};
28
+ let detail = this.data ? (await this.data.evaluate(scope, dom, tag)).objectify : {};
27
29
  if (detail instanceof Scope)
28
30
  detail = detail.data.getData();
29
31
  else if (detail instanceof ScopeData)
30
32
  detail = detail.getData();
31
33
 
32
- detail['source'] = tag.element;
34
+ let targets: Tag[] = [tag];
35
+ if (this.elementRef) {
36
+ targets = await this.elementRef.evaluate(scope, dom, tag, true);
37
+ }
33
38
 
34
- tag.element.dispatchEvent(new CustomEvent(this.name, {
35
- bubbles: this.bubbles,
36
- detail: detail
37
- }));
39
+ for (const target of targets) {
40
+ detail['source'] = target.element;
41
+ target.element.dispatchEvent(new CustomEvent(this.name, {
42
+ bubbles: this.bubbles,
43
+ detail: detail
44
+ }));
45
+ }
38
46
  }
39
47
 
40
48
  public static parse(lastNode, token, tokens: Token[]) {
41
49
  const name = tokens.shift();
42
50
  let data: ObjectNode = null;
43
- if (tokens.length && tokens[0].type === TokenType.L_PAREN) {
44
- const containedTokens = Tree.getNextStatementTokens(tokens, true, true, false);
51
+ if (tokens.length && tokens[0].type === TokenType.L_BRACE) {
52
+ const containedTokens = Tree.getNextStatementTokens(tokens, false, false, true);
45
53
  data = Tree.processTokens(containedTokens).statements[0] as ObjectNode;
46
54
  }
47
-
48
- return new DispatchEventNode(name.value, data, name.full.startsWith('!!!'));
55
+ const elementRef = lastNode instanceof ElementQueryNode ? lastNode : null;
56
+ return new DispatchEventNode(name.value, data, name.full.startsWith('!!!'), elementRef);
49
57
  }
50
58
  }
@@ -7,6 +7,8 @@ import {TreeNode} from "../AST";
7
7
  import {Node} from "./Node";
8
8
  import {ElementQueryNode} from "./ElementQueryNode";
9
9
  import {ScopeNodeAbstract} from "./ScopeNodeAbstract";
10
+ import {ObjectAccessor} from "../Scope/ObjectAccessor";
11
+ import {ScopeAbstract} from "../Scope/ScopeAbstract";
10
12
 
11
13
  export class ScopeMemberNode extends ScopeNodeAbstract implements TreeNode {
12
14
  constructor(
@@ -45,6 +47,8 @@ export class ScopeMemberNode extends ScopeNodeAbstract implements TreeNode {
45
47
  for (let parent of scopes) {
46
48
  if (parent instanceof DOMObject)
47
49
  parent = parent.scope;
50
+ else if (parent && !(parent instanceof ScopeAbstract))
51
+ parent = new ObjectAccessor(parent);
48
52
 
49
53
  if (!parent) {
50
54
  throw Error(`Cannot access "${await this.name.evaluate(scope, dom, tag)}" of undefined.`);
@@ -0,0 +1,21 @@
1
+ import {ScopeAbstract} from "./ScopeAbstract";
2
+
3
+ export class ObjectAccessor extends ScopeAbstract {
4
+ public readonly data: any;
5
+
6
+ constructor(data: any) {
7
+ super();
8
+ this.data = data;
9
+ }
10
+
11
+ public get(field: string, fallback = null): any {
12
+ const value = this.data[field];
13
+ if (typeof value === 'object')
14
+ return new ObjectAccessor(value);
15
+ return value === undefined ? fallback : value;
16
+ }
17
+
18
+ public set(field: string, value: any): void {
19
+ this.data[field] = value;
20
+ }
21
+ }
@@ -0,0 +1,11 @@
1
+ import {EventDispatcher} from "../EventDispatcher";
2
+
3
+ export interface IScope {
4
+ get(field: string, fallback?: any): any;
5
+ set(field: string, value: any): void;
6
+ }
7
+
8
+ export abstract class ScopeAbstract extends EventDispatcher implements IScope {
9
+ public abstract get(field: string, fallback?: any): any;
10
+ public abstract set(field: string, value: any): void;
11
+ }
package/src/Scope.ts CHANGED
@@ -5,9 +5,10 @@ import {WrappedArray} from "./Scope/WrappedArray";
5
5
  import {ScopeData} from "./Scope/ScopeData";
6
6
  import {DynamicScopeData} from "./Scope/DynamicScopeData";
7
7
  import {DOM} from "./DOM";
8
+ import {ScopeAbstract} from "./Scope/ScopeAbstract";
8
9
 
9
10
 
10
- export class Scope extends EventDispatcher {
11
+ export class Scope extends ScopeAbstract {
11
12
  public wrapped: any;
12
13
  protected _data: ScopeData;
13
14
  protected children: Scope[];
@@ -29,6 +30,18 @@ export class Scope extends EventDispatcher {
29
30
  return this._data;
30
31
  }
31
32
 
33
+ public get objectify(): any {
34
+ const obj = {};
35
+ for (const key of this.keys) {
36
+ const value = this.get(key);
37
+ if (value instanceof Scope)
38
+ obj[key] = value.objectify;
39
+ else
40
+ obj[key] = value;
41
+ }
42
+ return obj;
43
+ }
44
+
32
45
  public get parentScope(): Scope {
33
46
  if (this._parentScope)
34
47
  return this._parentScope;
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = '0.1.124';
1
+ export const VERSION = '0.1.125';
2
2
 
package/src/vsn.ts CHANGED
@@ -4,7 +4,6 @@ import {Registry} from "./Registry";
4
4
  import {Configuration} from "./Configuration";
5
5
  import {VisionHelper} from "./helpers/VisionHelper";
6
6
  import {Tree} from "./AST";
7
- import {Query} from "./Query";
8
7
  import {EventDispatcher} from "./EventDispatcher";
9
8
  import {DynamicScopeData} from "./Scope/DynamicScopeData";
10
9
  import {Controller} from "./Controller";
@@ -46,7 +45,7 @@ export class Vision extends EventDispatcher {
46
45
  window['Registry'] = Registry;
47
46
  window['vision'] = window['vsn'] = this;
48
47
  window['Tree'] = Tree;
49
- window['$'] = Query;
48
+ window['$'] = this.exec.bind(this);
50
49
  VisionHelper.window.dispatchEvent(new Event('vsn'));
51
50
  }
52
51
  }
@@ -2,6 +2,7 @@ import {DOM} from "../../src/DOM";
2
2
  import {ClassNode} from "../../src/AST/ClassNode";
3
3
  import {Registry} from "../../src/Registry";
4
4
  import {TagList} from "../../src/Tag/TagList";
5
+ import {Tag} from "../../src/vsn";
5
6
 
6
7
 
7
8
  describe('ClassNode', () => {
@@ -16,6 +17,7 @@ describe('ClassNode', () => {
16
17
  }
17
18
  </script>
18
19
  <div class="simple"><input /></div>
20
+ <input id="not-nested" />
19
21
  `;
20
22
  const dom = new DOM(document);
21
23
  await dom.ready;
@@ -25,6 +27,26 @@ describe('ClassNode', () => {
25
27
  expect(ClassNode.classes['.simple input']).toBeInstanceOf(ClassNode);
26
28
  });
27
29
 
30
+ it("properly build classes on newly added elements in the dom", async () => {
31
+ document.body.innerHTML = `
32
+ <script type="text/vsn" vsn-script>
33
+ class .added-html {
34
+ func construct() {}
35
+ }
36
+ </script>
37
+ <div id="container"></div>
38
+ `;
39
+ const dom = new DOM(document);
40
+ await dom.ready;
41
+ await Registry.instance.classes.get('.added-html');
42
+ const newHtml: string = `<div class="added-html" id="added"></div>`;
43
+ dom.root.scope.set('newHtml', newHtml);
44
+ await dom.exec('#container.@html = newHtml');
45
+ const addedTag = await dom.exec('#added');
46
+ expect(addedTag).toBeInstanceOf(Tag);
47
+ expect(ClassNode.preppedTags['.added-html'].indexOf(addedTag)).toBeGreaterThan(-1);
48
+ });
49
+
28
50
  it("properly define a simple class", async () => {
29
51
  document.body.innerHTML = `
30
52
  <script type="text/vsn" vsn-script>