vsn 0.1.50 → 0.1.53

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 (45) hide show
  1. package/README.md +4 -56
  2. package/demo/demo.html +61 -182
  3. package/demo/markup-default.html +2 -0
  4. package/demo/vsn.js +1 -1
  5. package/dist/AST/XHRNode.js +2 -0
  6. package/dist/AST/XHRNode.js.map +1 -1
  7. package/dist/AST.js +1 -1
  8. package/dist/AST.js.map +1 -1
  9. package/dist/DOM.d.ts +1 -1
  10. package/dist/DOM.js +1 -1
  11. package/dist/Scope/QueryReference.js +2 -2
  12. package/dist/Tag.d.ts +3 -1
  13. package/dist/Tag.js +25 -19
  14. package/dist/Tag.js.map +1 -1
  15. package/dist/attributes/LazyAttribute.d.ts +8 -0
  16. package/dist/attributes/LazyAttribute.js +120 -0
  17. package/dist/attributes/LazyAttribute.js.map +1 -0
  18. package/dist/attributes/List.js +1 -1
  19. package/dist/attributes/ScopeAttribute.d.ts +4 -0
  20. package/dist/attributes/ScopeAttribute.js +75 -0
  21. package/dist/attributes/ScopeAttribute.js.map +1 -1
  22. package/dist/attributes/_imports.d.ts +1 -0
  23. package/dist/attributes/_imports.js +3 -1
  24. package/dist/attributes/_imports.js.map +1 -1
  25. package/dist/helpers/VisionHelper.d.ts +1 -0
  26. package/dist/helpers/VisionHelper.js +15 -0
  27. package/dist/helpers/VisionHelper.js.map +1 -1
  28. package/dist/vsn.js +1 -1
  29. package/package.json +7 -2
  30. package/src/AST/XHRNode.ts +3 -2
  31. package/src/AST.ts +1 -2
  32. package/src/DOM.ts +1 -1
  33. package/src/Scope/QueryReference.ts +2 -2
  34. package/src/Tag.ts +23 -15
  35. package/src/attributes/LazyAttribute.ts +26 -0
  36. package/src/attributes/List.ts +1 -1
  37. package/src/attributes/ScopeAttribute.ts +19 -0
  38. package/src/attributes/_imports.ts +1 -0
  39. package/src/helpers/VisionHelper.ts +19 -0
  40. package/src/vsn.ts +1 -1
  41. package/test/Controller.spec.ts +4 -4
  42. package/test/DOM.spec.ts +2 -2
  43. package/test/attributes/ScopeAttribute.spec.ts +23 -0
  44. package/test/attributes/Styles.spec.ts +1 -1
  45. package/examples/attribute-binding.html +0 -29
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TypeAttribute = exports.Template = exports.StyleAttribute = exports.StandardAttribute = exports.SetAttribute = exports.ScopeChange = exports.ScopeAttribute = exports.RootAttribute = exports.Referenced = exports.On = exports.Name = exports.ModelAttribute = exports.ListItemModel = exports.ListItem = exports.List = exports.KeyUp = exports.KeyDown = exports.JSONAttribute = exports.If = exports.Format = exports.Exec = exports.DisableIf = exports.ControllerAttribute = exports.Bind = exports.AddClassIf = void 0;
3
+ exports.TypeAttribute = exports.Template = exports.StyleAttribute = exports.StandardAttribute = exports.SetAttribute = exports.ScopeChange = exports.ScopeAttribute = exports.RootAttribute = exports.Referenced = exports.On = exports.Name = exports.ModelAttribute = exports.ListItemModel = exports.ListItem = exports.List = exports.LazyAttribute = exports.KeyUp = exports.KeyDown = exports.JSONAttribute = exports.If = exports.Format = exports.Exec = exports.DisableIf = exports.ControllerAttribute = exports.Bind = exports.AddClassIf = void 0;
4
4
  var AddClassIf_1 = require("./AddClassIf");
5
5
  Object.defineProperty(exports, "AddClassIf", { enumerable: true, get: function () { return AddClassIf_1.AddClassIf; } });
6
6
  var Bind_1 = require("./Bind");
@@ -21,6 +21,8 @@ var KeyDown_1 = require("./KeyDown");
21
21
  Object.defineProperty(exports, "KeyDown", { enumerable: true, get: function () { return KeyDown_1.KeyDown; } });
22
22
  var KeyUp_1 = require("./KeyUp");
23
23
  Object.defineProperty(exports, "KeyUp", { enumerable: true, get: function () { return KeyUp_1.KeyUp; } });
24
+ var LazyAttribute_1 = require("./LazyAttribute");
25
+ Object.defineProperty(exports, "LazyAttribute", { enumerable: true, get: function () { return LazyAttribute_1.LazyAttribute; } });
24
26
  var List_1 = require("./List");
25
27
  Object.defineProperty(exports, "List", { enumerable: true, get: function () { return List_1.List; } });
26
28
  var ListItem_1 = require("./ListItem");
@@ -1 +1 @@
1
- {"version":3,"file":"_imports.js","sourceRoot":"","sources":["../../src/attributes/_imports.ts"],"names":[],"mappings":";;;AAAA,2CAAwC;AAAhC,wGAAA,UAAU,OAAA;AAClB,+BAA4B;AAApB,4FAAA,IAAI,OAAA;AACZ,6DAA0D;AAAlD,0HAAA,mBAAmB,OAAA;AAC3B,yCAAsC;AAA9B,sGAAA,SAAS,OAAA;AACjB,+BAA4B;AAApB,4FAAA,IAAI,OAAA;AACZ,mCAAgC;AAAxB,gGAAA,MAAM,OAAA;AACd,2BAAwB;AAAhB,wFAAA,EAAE,OAAA;AACV,iDAA8C;AAAtC,8GAAA,aAAa,OAAA;AACrB,qCAAkC;AAA1B,kGAAA,OAAO,OAAA;AACf,iCAA8B;AAAtB,8FAAA,KAAK,OAAA;AACb,+BAA4B;AAApB,4FAAA,IAAI,OAAA;AACZ,uCAAoC;AAA5B,oGAAA,QAAQ,OAAA;AAChB,iDAA8C;AAAtC,8GAAA,aAAa,OAAA;AACrB,mDAAgD;AAAxC,gHAAA,cAAc,OAAA;AACtB,+BAA4B;AAApB,4FAAA,IAAI,OAAA;AACZ,2BAAwB;AAAhB,wFAAA,EAAE,OAAA;AACV,2CAAwC;AAAhC,wGAAA,UAAU,OAAA;AAClB,iDAA8C;AAAtC,8GAAA,aAAa,OAAA;AACrB,mDAAgD;AAAxC,gHAAA,cAAc,OAAA;AACtB,6CAA0C;AAAlC,0GAAA,WAAW,OAAA;AACnB,+CAA4C;AAApC,4GAAA,YAAY,OAAA;AACpB,yDAAsD;AAA9C,sHAAA,iBAAiB,OAAA;AACzB,mDAAgD;AAAxC,gHAAA,cAAc,OAAA;AACtB,uCAAoC;AAA5B,oGAAA,QAAQ,OAAA;AAChB,iDAA8C;AAAtC,8GAAA,aAAa,OAAA"}
1
+ {"version":3,"file":"_imports.js","sourceRoot":"","sources":["../../src/attributes/_imports.ts"],"names":[],"mappings":";;;AAAA,2CAAwC;AAAhC,wGAAA,UAAU,OAAA;AAClB,+BAA4B;AAApB,4FAAA,IAAI,OAAA;AACZ,6DAA0D;AAAlD,0HAAA,mBAAmB,OAAA;AAC3B,yCAAsC;AAA9B,sGAAA,SAAS,OAAA;AACjB,+BAA4B;AAApB,4FAAA,IAAI,OAAA;AACZ,mCAAgC;AAAxB,gGAAA,MAAM,OAAA;AACd,2BAAwB;AAAhB,wFAAA,EAAE,OAAA;AACV,iDAA8C;AAAtC,8GAAA,aAAa,OAAA;AACrB,qCAAkC;AAA1B,kGAAA,OAAO,OAAA;AACf,iCAA8B;AAAtB,8FAAA,KAAK,OAAA;AACb,iDAA8C;AAAtC,8GAAA,aAAa,OAAA;AACrB,+BAA4B;AAApB,4FAAA,IAAI,OAAA;AACZ,uCAAoC;AAA5B,oGAAA,QAAQ,OAAA;AAChB,iDAA8C;AAAtC,8GAAA,aAAa,OAAA;AACrB,mDAAgD;AAAxC,gHAAA,cAAc,OAAA;AACtB,+BAA4B;AAApB,4FAAA,IAAI,OAAA;AACZ,2BAAwB;AAAhB,wFAAA,EAAE,OAAA;AACV,2CAAwC;AAAhC,wGAAA,UAAU,OAAA;AAClB,iDAA8C;AAAtC,8GAAA,aAAa,OAAA;AACrB,mDAAgD;AAAxC,gHAAA,cAAc,OAAA;AACtB,6CAA0C;AAAlC,0GAAA,WAAW,OAAA;AACnB,+CAA4C;AAApC,4GAAA,YAAY,OAAA;AACpB,yDAAsD;AAA9C,sHAAA,iBAAiB,OAAA;AACzB,mDAAgD;AAAxC,gHAAA,cAAc,OAAA;AACtB,uCAAoC;AAA5B,oGAAA,QAAQ,OAAA;AAChB,iDAA8C;AAAtC,8GAAA,aAAa,OAAA"}
@@ -6,6 +6,7 @@ export declare class VisionHelper {
6
6
  static get inDevelopment(): boolean;
7
7
  static get doBenchmark(): boolean;
8
8
  static get inLegacy(): boolean;
9
+ static getUriWithParams(url: string, params: Record<string, any>): string;
9
10
  static nice(callback: any, timeout?: number): void;
10
11
  static get wasmSupport(): boolean;
11
12
  }
@@ -56,6 +56,21 @@ var VisionHelper = /** @class */ (function () {
56
56
  enumerable: false,
57
57
  configurable: true
58
58
  });
59
+ VisionHelper.getUriWithParams = function (url, params) {
60
+ var base = window.location.origin;
61
+ if (url.startsWith('.') || !url.startsWith('/')) {
62
+ base += window.location.pathname;
63
+ }
64
+ var _url = new URL(url, base);
65
+ var urlParams = new URLSearchParams(_url.search);
66
+ for (var key in params) {
67
+ if (params[key] !== undefined) {
68
+ urlParams.set(key, params[key]);
69
+ }
70
+ }
71
+ _url.search = urlParams.toString();
72
+ return _url.toString();
73
+ };
59
74
  VisionHelper.nice = function (callback, timeout) {
60
75
  if (timeout === void 0) { timeout = 100; }
61
76
  if (VisionHelper.window && window['requestIdleCallback']) {
@@ -1 +1 @@
1
- {"version":3,"file":"VisionHelper.js","sourceRoot":"","sources":["../../src/helpers/VisionHelper.ts"],"names":[],"mappings":";;;AAGA;IAAA;IA2DA,CAAC;IA1DiB,0BAAa,GAA3B,UAA4B,GAAQ;QAChC,OAAO,GAAG;YACN,GAAG,CAAC,cAAc,CAAC,WAAW,CAAC;YAC/B,CAAC,CAAC,GAAG,CAAC,SAAS;YACf,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW;YAC3B,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC;IACzC,CAAC;IAED,sBAAkB,wBAAQ;aAA1B;YACI,OAAO,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;QAC1D,CAAC;;;OAAA;IAED,sBAAkB,sBAAM;aAAxB;YACI,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;QACtD,CAAC;;;OAAA;IAEa,qBAAQ,GAAtB;QACI,IAAI,KAAK,GAAG,KAAK,CAAC;QAClB,IAAI,SAAS,IAAI,YAAY,CAAC,MAAM,EAAE;YAClC,CAAC,UAAU,CAAC;gBACR,IAAI,0TAA0T,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,ykDAAykD,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;oBAAE,KAAK,GAAG,IAAI,CAAC;YAC37D,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;SAClE;QACD,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,sBAAkB,6BAAa;aAA/B;YACI,OAAO,cAAc,CAAC;QAC1B,CAAC;;;OAAA;IAED,sBAAkB,2BAAW;aAA7B;YACI,OAAO,YAAY,CAAC;QACxB,CAAC;;;OAAA;IAED,sBAAkB,wBAAQ;aAA1B;YACI,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,KAAK,CAAC;QAC9C,CAAC;;;OAAA;IAEa,iBAAI,GAAlB,UAAmB,QAAQ,EAAE,OAAqB;QAArB,wBAAA,EAAA,aAAqB;QAC9C,IAAI,YAAY,CAAC,MAAM,IAAI,MAAM,CAAC,qBAAqB,CAAC,EAAE;YACtD,MAAM,CAAC,qBAAqB,CAAC,CAAC,QAAQ,CAAC,CAAC;SAC3C;aAAM;YACH,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;SACjC;IACL,CAAC;IAED,sBAAkB,2BAAW;aAA7B;YACI,IAAI;gBACA,IAAI,OAAO,WAAW,KAAK,QAAQ;uBAC5B,OAAO,WAAW,CAAC,WAAW,KAAK,UAAU,EAAE;oBAClD,IAAM,QAAM,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;oBACpG,IAAI,QAAM,YAAY,WAAW,CAAC,MAAM;wBACpC,OAAO,IAAI,WAAW,CAAC,QAAQ,CAAC,QAAM,CAAC,YAAY,WAAW,CAAC,QAAQ,CAAC;iBAC/E;aACJ;YAAC,OAAO,CAAC,EAAE;aACX;YACD,OAAO,KAAK,CAAC;QACjB,CAAC;;;OAAA;IACL,mBAAC;AAAD,CAAC,AA3DD,IA2DC;AA3DY,oCAAY"}
1
+ {"version":3,"file":"VisionHelper.js","sourceRoot":"","sources":["../../src/helpers/VisionHelper.ts"],"names":[],"mappings":"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"}
package/dist/vsn.js CHANGED
@@ -107,7 +107,7 @@ var Vision = /** @class */ (function (_super) {
107
107
  return __awaiter(this, void 0, void 0, function () {
108
108
  return __generator(this, function (_a) {
109
109
  switch (_a.label) {
110
- case 0: return [4 /*yield*/, this._dom.eval(code)];
110
+ case 0: return [4 /*yield*/, this._dom.exec(code)];
111
111
  case 1: return [2 /*return*/, _a.sent()];
112
112
  }
113
113
  });
package/package.json CHANGED
@@ -1,10 +1,15 @@
1
1
  {
2
2
  "name": "vsn",
3
- "version": "0.1.50",
3
+ "version": "0.1.53",
4
4
  "description": "SEO Friendly Javascript/Typescript Framework",
5
5
  "keywords": [
6
6
  "framework",
7
- "typescript"
7
+ "typescript",
8
+ "html",
9
+ "ajax",
10
+ "hateoas",
11
+ "rest",
12
+ "seo"
8
13
  ],
9
14
  "main": "./dist/vsn.js",
10
15
  "scripts": {
@@ -4,6 +4,7 @@ import {Scope} from "../Scope";
4
4
  import {DOM} from "../DOM";
5
5
  import {Tag} from "../Tag";
6
6
  import {ScopeDataAbstract} from "../Scope/ScopeDataAbstract";
7
+ import {VisionHelper} from "../helpers/VisionHelper";
7
8
 
8
9
  export class XHRNode extends Node implements TreeNode {
9
10
  constructor(
@@ -22,7 +23,7 @@ export class XHRNode extends Node implements TreeNode {
22
23
  }
23
24
 
24
25
  async evaluate(scope: Scope, dom: DOM, tag?: Tag) {
25
- const url = await this.url.evaluate(scope, dom, tag);
26
+ let url = await this.url.evaluate(scope, dom, tag);
26
27
  let method: string;
27
28
  let data = this.left ? await this.left.evaluate(scope, dom, tag) : {};
28
29
 
@@ -51,7 +52,7 @@ export class XHRNode extends Node implements TreeNode {
51
52
  };
52
53
 
53
54
  if (request.method === 'GET') {
54
-
55
+ url = VisionHelper.getUriWithParams(url, data);
55
56
  } else {
56
57
  request['body'] = (typeof data === "string") ? data : JSON.stringify(data);
57
58
  }
package/src/AST.ts CHANGED
@@ -296,7 +296,7 @@ const TOKEN_PATTERNS: TokenPattern[] = [
296
296
  },
297
297
  {
298
298
  type: TokenType.STRING_LITERAL,
299
- pattern: /^'([^']*)'/ // Try to make this work: /^(?<!\\)(?:\\\\)*"([^(?<!\\)(?:\\\\)*"]*)(?<!\\)(?:\\\\)*"/
299
+ pattern: /^'([^']*)'/
300
300
  },
301
301
  {
302
302
  type: TokenType.AND,
@@ -354,7 +354,6 @@ export interface TreeNode<T = any> {
354
354
  prepare(scope: Scope, dom: DOM, tag?: Tag);
355
355
  }
356
356
 
357
-
358
357
  export interface IBlockInfo {
359
358
  type: BlockType,
360
359
  open: TokenType,
package/src/DOM.ts CHANGED
@@ -100,7 +100,7 @@ export class DOM extends EventDispatcher {
100
100
  return this.rootElement.querySelector(q);
101
101
  }
102
102
 
103
- public async eval(code: string) {
103
+ public async exec(code: string) {
104
104
  const tree = new Tree(code);
105
105
  await tree.prepare(this.root.scope, this);
106
106
  return await tree.evaluate(this.root.scope, this);
@@ -14,7 +14,7 @@ export class QueryReference extends ScopeReference {
14
14
  public async getScope() {
15
15
  let parts: string[] = this.path.split('.');
16
16
  parts = parts.splice(0, parts.length - 1);
17
- const qResult = await DOM.instance.eval(parts.join('.'));
17
+ const qResult = await DOM.instance.exec(parts.join('.'));
18
18
  return qResult.length === 1 ? qResult[0].scope : qResult.map((dobj) => dobj.scope);
19
19
  }
20
20
 
@@ -24,6 +24,6 @@ export class QueryReference extends ScopeReference {
24
24
  }
25
25
 
26
26
  public async getValue() {
27
- return await DOM.instance.eval(this.path);
27
+ return await DOM.instance.exec(this.path);
28
28
  }
29
29
  }
package/src/Tag.ts CHANGED
@@ -108,7 +108,7 @@ export class Tag extends DOMObject {
108
108
  }
109
109
  }
110
110
 
111
- public async eval(code: string) {
111
+ public async exec(code: string) {
112
112
  const tree = new Tree(code);
113
113
  await tree.prepare(this.scope, this.dom, this);
114
114
  return await tree.evaluate(this.scope, this.dom, this);
@@ -556,13 +556,20 @@ export class Tag extends DOMObject {
556
556
  this.onEventHandlers[eventType].push(handler);
557
557
  }
558
558
 
559
- async watchAttribute(attributeName: string) {
560
- for (const attribute of this.attributes) {
561
- if (attribute instanceof StandardAttribute && attribute.attributeName == attributeName) {
562
- return attribute;
559
+ public removeEventHandler(eventType: string, handler) {
560
+ if (!this.onEventHandlers[eventType])
561
+ return;
562
+
563
+ const index = this.onEventHandlers[eventType].indexOf(handler);
564
+ if (index > -1) {
565
+ this.onEventHandlers[eventType].splice(index, 1);
566
+ if (this.onEventHandlers[eventType].length === 0) {
567
+ this.element.removeEventListener(eventType, this.handleEvent.bind(this, eventType));
563
568
  }
564
569
  }
570
+ }
565
571
 
572
+ public createScope() {
566
573
  // Standard attribute requires a unique scope
567
574
  // @todo: Does this cause any issues with attribute bindings on the parent scope prior to having its own scope? hmm...
568
575
  if (!this.uniqueScope) {
@@ -573,6 +580,16 @@ export class Tag extends DOMObject {
573
580
  this.scope.parentScope = this.parentTag.scope;
574
581
  }
575
582
  }
583
+ }
584
+
585
+ async watchAttribute(attributeName: string) {
586
+ for (const attribute of this.attributes) {
587
+ if (attribute instanceof StandardAttribute && attribute.attributeName == attributeName) {
588
+ return attribute;
589
+ }
590
+ }
591
+
592
+ this.createScope();
576
593
 
577
594
  const standardAttribute = new StandardAttribute(this, attributeName);
578
595
  this.attributes.push(standardAttribute);
@@ -588,16 +605,7 @@ export class Tag extends DOMObject {
588
605
  }
589
606
  }
590
607
 
591
- // Standard attribute requires a unique scope
592
- // @todo: Does this cause any issues with attribute bindings on the parent scope prior to having its own scope? hmm...
593
- if (!this.uniqueScope) {
594
- this._uniqueScope = true;
595
- this._scope = new Scope();
596
-
597
- if (this.parentTag) {
598
- this.scope.parentScope = this.parentTag.scope;
599
- }
600
- }
608
+ this.createScope();
601
609
 
602
610
  const styleAttribute = new StyleAttribute(this, 'style');
603
611
  this.attributes.push(styleAttribute);
@@ -0,0 +1,26 @@
1
+ import {Registry} from "../Registry";
2
+ import {On} from "./On";
3
+
4
+ @Registry.attribute('vsn-lazy')
5
+ export class LazyAttribute extends On {
6
+ private loaded: boolean = false;
7
+ private eleTop: number;
8
+
9
+ public async setup() {
10
+ await super.setup();
11
+ this.eleTop = this.tag.element.getBoundingClientRect().top;
12
+ }
13
+
14
+ public async connect() {
15
+ this.tag.addEventHandler('scroll', ['passive'], this.handleEvent.bind(this));
16
+ await this.handleEvent();
17
+ }
18
+
19
+ async handleEvent(e?: Event) {
20
+ if (!this.loaded && window.scrollY + window.outerHeight >= this.eleTop) {
21
+ this.loaded = true;
22
+ await this.handler.evaluate(this.tag.scope, this.tag.dom, this.tag);
23
+ this.tag.removeEventHandler('scroll', this.handleEvent.bind(this));
24
+ }
25
+ }
26
+ }
@@ -37,7 +37,7 @@ export class List extends Attribute {
37
37
  }
38
38
  } else {
39
39
  if (this.tag.hasRawAttribute('template')) {
40
- let templateNode = await DOM.instance.eval(this.tag.getRawAttributeValue('template'));
40
+ let templateNode = await DOM.instance.exec(this.tag.getRawAttributeValue('template'));
41
41
  if (templateNode instanceof Array && templateNode.length === 1)
42
42
  templateNode = templateNode[0];
43
43
 
@@ -1,8 +1,27 @@
1
1
  import {Attribute} from "../Attribute";
2
2
  import {Registry} from "../Registry";
3
+ import {Tree} from "../AST";
4
+ import {Scope} from "../Scope";
3
5
 
4
6
  @Registry.attribute('vsn-scope')
5
7
  export class ScopeAttribute extends Attribute {
6
8
  public static readonly canDefer: boolean = false;
7
9
  public static readonly scoped: boolean = true;
10
+ protected tree: Tree;
11
+
12
+ public async compile() {
13
+ this.tree = new Tree(this.getAttributeValue());
14
+ await this.tree.prepare(this.tag.scope, this.tag.dom, this.tag);
15
+ await super.compile();
16
+ }
17
+
18
+ public async extract() {
19
+ const value = await this.tree.evaluate(this.tag.scope, this.tag.dom, this.tag);
20
+ if (!(value instanceof Scope)) {
21
+ throw new Error(`Scope value must be an object, got ${typeof value}`);
22
+ }
23
+ for (const key of value.data.keys) {
24
+ this.tag.scope.set(key, value.data[key]);
25
+ }
26
+ }
8
27
  }
@@ -8,6 +8,7 @@ export {If} from "./If";
8
8
  export {JSONAttribute} from "./JSONAttribute";
9
9
  export {KeyDown} from "./KeyDown";
10
10
  export {KeyUp} from "./KeyUp";
11
+ export {LazyAttribute} from "./LazyAttribute";
11
12
  export {List} from "./List";
12
13
  export {ListItem} from "./ListItem";
13
14
  export {ListItemModel} from "./ListItemModel";
@@ -40,6 +40,25 @@ export class VisionHelper {
40
40
  return process.env.BUILD_TARGET === 'es5';
41
41
  }
42
42
 
43
+ public static getUriWithParams(
44
+ url: string,
45
+ params: Record<string, any>
46
+ ): string {
47
+ let base = window.location.origin;
48
+ if (url.startsWith('.') || !url.startsWith('/')) {
49
+ base += window.location.pathname;
50
+ }
51
+ const _url = new URL(url, base);
52
+ const urlParams: URLSearchParams = new URLSearchParams(_url.search);
53
+ for (const key in params) {
54
+ if (params[key] !== undefined) {
55
+ urlParams.set(key, params[key]);
56
+ }
57
+ }
58
+ _url.search = urlParams.toString();
59
+ return _url.toString();
60
+ }
61
+
43
62
  public static nice(callback, timeout: number = 100) {
44
63
  if (VisionHelper.window && window['requestIdleCallback']) {
45
64
  window['requestIdleCallback'](callback);
package/src/vsn.ts CHANGED
@@ -44,7 +44,7 @@ export class Vision extends EventDispatcher {
44
44
  }
45
45
 
46
46
  public async eval(code: string) {
47
- return await this._dom.eval(code);
47
+ return await this._dom.exec(code);
48
48
  }
49
49
 
50
50
  public async setup() {
@@ -33,10 +33,10 @@ describe('Controller', () => {
33
33
  const dom = new DOM(document);
34
34
  const deferred = SimplePromise.defer();
35
35
  dom.once('built', async () => {
36
- expect(await dom.eval('test.test')).toBe('notTest');
37
- expect(await dom.eval('test.isValid()')).toBe(false);
38
- await dom.eval('test.test = "test"');
39
- expect(await dom.eval('test.isValid()')).toBe(true);
36
+ expect(await dom.exec('test.test')).toBe('notTest');
37
+ expect(await dom.exec('test.isValid()')).toBe(false);
38
+ await dom.exec('test.test = "test"');
39
+ expect(await dom.exec('test.isValid()')).toBe(true);
40
40
  deferred.resolve();
41
41
  });
42
42
  await deferred.promise;
package/test/DOM.spec.ts CHANGED
@@ -28,8 +28,8 @@ describe('DOM', () => {
28
28
  `;
29
29
  const dom = new DOM(document);
30
30
  dom.once('built', async () => {
31
- expect(await dom.eval('?(#parent).asd')).toBe(123);
32
- expect(await dom.eval('?(#testing).asd')).toBe(345);
31
+ expect(await dom.exec('?(#parent).asd')).toBe(123);
32
+ expect(await dom.exec('?(#testing).asd')).toBe(345);
33
33
  done();
34
34
  });
35
35
  });
@@ -0,0 +1,23 @@
1
+ import {DOM} from "../../src/DOM";
2
+ import "../../src/Types";
3
+ import "../../src/attributes/_imports";
4
+
5
+
6
+ describe('ScopeAttribute', () => {
7
+ it("vsn-scope should set simple values correctly", (done) => {
8
+ document.body.innerHTML = `
9
+ <div vsn-scope="{'asd':123, 'sdf': 'asd'}">
10
+ <span vsn-bind="asd"></span>
11
+ </div>
12
+ `;
13
+ const dom = new DOM(document);
14
+ dom.once('built', async () => {
15
+ const element = (await dom.exec('?(div)'))[0];
16
+ expect(element.scope.get('asd')).toBe(123);
17
+ expect(element.scope.get('sdf')).toBe('asd');
18
+ const span = (await element.exec('?>(:first-child)'))[0];
19
+ expect(span.element.innerText).toBe('123');
20
+ done();
21
+ });
22
+ });
23
+ });
@@ -35,7 +35,7 @@ describe('Styles', () => {
35
35
  `;
36
36
  const dom = new DOM(document);
37
37
  dom.once('built', async () => {
38
- await dom.eval('?(#styling).$marginTop = "50px"');
38
+ await dom.exec('?(#styling).$marginTop = "50px"');
39
39
  expect((await dom.get('#styling'))[0].element.style.marginTop).toBe('50px');
40
40
  done();
41
41
  });
@@ -1,29 +0,0 @@
1
- <h2>The Link</h2>
2
- <p>v-bind:href binds the scope variable to the element's href attribute. v-name creates a variable scope to hold the url and text variables. Note: You could remove the v-name and the link. from all of the bindings to set the values to the root scope.</p>
3
- <div>
4
- <a href="/index.html" v-name="link" v-bind:href="link.url" v-bind="link.text">Home</a>
5
- </div>
6
-
7
- <h2>Text Values</h2>
8
- <p>Bind an element's innerText with v-bind.</p>
9
- <div>URL: <span v-bind="link.url"></span>, Text: <span v-bind="link.text"></span></div>
10
-
11
- <h2>Change Values with Button Click</h2>
12
- <div>
13
- <button id="button-help" v-click="link.url='/help.html';link.text='Help';">Change to Help</button>
14
- <button id="button-info" v-click="link.url='/info.html';link.text='Info';">Change to Info</button>
15
- </div>
16
-
17
- <h2>Change Values with Inputs</h2>
18
- <p>v-bind on inputs binds the inputs values to the scope variable.</p>
19
- <div>
20
- <label>
21
- Link Text:
22
- <input type="text" v-bind="link.text" />
23
- </label>
24
-
25
- <label>
26
- Link URL:
27
- <input type="text" v-bind="link.url" />
28
- </label>
29
- </div>