vsn 0.1.49 → 0.1.52
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.
- package/demo/demo.html +61 -182
- package/demo/markup-default.html +2 -0
- package/demo/markup.html +1 -1
- package/demo/vsn.js +1 -1
- package/dist/AST/ElementQueryNode.d.ts +4 -2
- package/dist/AST/ElementQueryNode.js +8 -2
- package/dist/AST/ElementQueryNode.js.map +1 -1
- package/dist/AST/XHRNode.js +2 -0
- package/dist/AST/XHRNode.js.map +1 -1
- package/dist/AST.d.ts +2 -0
- package/dist/AST.js +6 -5
- package/dist/AST.js.map +1 -1
- package/dist/DOM.d.ts +1 -1
- package/dist/DOM.js +1 -1
- package/dist/Scope/QueryReference.js +2 -2
- package/dist/Tag.d.ts +3 -1
- package/dist/Tag.js +25 -19
- package/dist/Tag.js.map +1 -1
- package/dist/attributes/LazyAttribute.d.ts +8 -0
- package/dist/attributes/LazyAttribute.js +120 -0
- package/dist/attributes/LazyAttribute.js.map +1 -0
- package/dist/attributes/List.js +1 -1
- package/dist/attributes/_imports.d.ts +1 -0
- package/dist/attributes/_imports.js +3 -1
- package/dist/attributes/_imports.js.map +1 -1
- package/dist/helpers/VisionHelper.d.ts +1 -0
- package/dist/helpers/VisionHelper.js +15 -0
- package/dist/helpers/VisionHelper.js.map +1 -1
- package/dist/vsn.js +1 -1
- package/package.json +7 -2
- package/src/AST/ElementQueryNode.ts +9 -3
- package/src/AST/XHRNode.ts +3 -2
- package/src/AST.ts +9 -7
- package/src/DOM.ts +1 -1
- package/src/Scope/QueryReference.ts +2 -2
- package/src/Tag.ts +23 -15
- package/src/attributes/LazyAttribute.ts +26 -0
- package/src/attributes/List.ts +1 -1
- package/src/attributes/ScopeAttribute.ts +19 -0
- package/src/attributes/_imports.ts +1 -0
- package/src/helpers/VisionHelper.ts +19 -0
- package/src/vsn.ts +1 -1
- package/test/Controller.spec.ts +4 -4
- package/test/DOM.spec.ts +2 -2
- package/test/attributes/ScopeAttribute.spec.ts +23 -0
- package/test/attributes/Styles.spec.ts +1 -1
- 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;
|
|
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.
|
|
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.
|
|
3
|
+
"version": "0.1.52",
|
|
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": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {Scope} from "../Scope";
|
|
2
2
|
import {DOM} from "../DOM";
|
|
3
3
|
import {Tag} from "../Tag";
|
|
4
|
-
import {TreeNode} from "../AST";
|
|
4
|
+
import {Token, TreeNode} from "../AST";
|
|
5
5
|
import {Node} from "./Node";
|
|
6
6
|
|
|
7
7
|
export class ElementQueryNode extends Node implements TreeNode {
|
|
@@ -9,14 +9,15 @@ export class ElementQueryNode extends Node implements TreeNode {
|
|
|
9
9
|
|
|
10
10
|
constructor(
|
|
11
11
|
public readonly query: string,
|
|
12
|
-
public readonly first: boolean = false
|
|
12
|
+
public readonly first: boolean = false,
|
|
13
|
+
public readonly global: boolean = false,
|
|
13
14
|
) {
|
|
14
15
|
super();
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
async evaluate(scope: Scope, dom: DOM, tag: Tag = null, forceList: boolean = false): Promise<any> {
|
|
18
19
|
tag = tag || await dom.getTagForScope(scope);
|
|
19
|
-
const elements = await dom.get(this.query, true, tag);
|
|
20
|
+
const elements = await dom.get(this.query, true, this.global ? null : tag);
|
|
20
21
|
return this.first && !forceList ? elements[0] : elements;
|
|
21
22
|
}
|
|
22
23
|
|
|
@@ -24,4 +25,9 @@ export class ElementQueryNode extends Node implements TreeNode {
|
|
|
24
25
|
tag = tag || await dom.getTagForScope(scope);
|
|
25
26
|
await dom.get(this.query, true, tag);
|
|
26
27
|
}
|
|
28
|
+
|
|
29
|
+
public static parse(lastNode, token, tokens: Token[]): ElementQueryNode {
|
|
30
|
+
tokens.shift();
|
|
31
|
+
return new ElementQueryNode(token.value, false, !token.full.startsWith('?>'));
|
|
32
|
+
}
|
|
27
33
|
}
|
package/src/AST/XHRNode.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
@@ -38,7 +38,9 @@ interface TokenPattern {
|
|
|
38
38
|
|
|
39
39
|
export interface Token {
|
|
40
40
|
type: TokenType,
|
|
41
|
-
value: string
|
|
41
|
+
value: string,
|
|
42
|
+
full: string,
|
|
43
|
+
groups: string[]
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
export enum BlockType {
|
|
@@ -206,7 +208,7 @@ const TOKEN_PATTERNS: TokenPattern[] = [
|
|
|
206
208
|
},
|
|
207
209
|
{
|
|
208
210
|
type: TokenType.ELEMENT_QUERY,
|
|
209
|
-
pattern:
|
|
211
|
+
pattern: /^\?>?\(([#.\[\]:,=\-_a-zA-Z0-9*\s]*[\]_a-zA-Z0-9*])\)/
|
|
210
212
|
},
|
|
211
213
|
{
|
|
212
214
|
type: TokenType.NAME,
|
|
@@ -294,7 +296,7 @@ const TOKEN_PATTERNS: TokenPattern[] = [
|
|
|
294
296
|
},
|
|
295
297
|
{
|
|
296
298
|
type: TokenType.STRING_LITERAL,
|
|
297
|
-
pattern: /^'([^']*)'/
|
|
299
|
+
pattern: /^'([^']*)'/
|
|
298
300
|
},
|
|
299
301
|
{
|
|
300
302
|
type: TokenType.AND,
|
|
@@ -352,7 +354,6 @@ export interface TreeNode<T = any> {
|
|
|
352
354
|
prepare(scope: Scope, dom: DOM, tag?: Tag);
|
|
353
355
|
}
|
|
354
356
|
|
|
355
|
-
|
|
356
357
|
export interface IBlockInfo {
|
|
357
358
|
type: BlockType,
|
|
358
359
|
open: TokenType,
|
|
@@ -426,7 +427,9 @@ export class Tree {
|
|
|
426
427
|
if (match) {
|
|
427
428
|
tokens.push({
|
|
428
429
|
type: tp.type,
|
|
429
|
-
value: match[match.length - 1]
|
|
430
|
+
value: match[match.length - 1],
|
|
431
|
+
full: match[0],
|
|
432
|
+
groups: match
|
|
430
433
|
});
|
|
431
434
|
|
|
432
435
|
code = code.substring(match[0].length);
|
|
@@ -491,8 +494,7 @@ export class Tree {
|
|
|
491
494
|
node = new ElementQueryNode(tokens[0].value, true);
|
|
492
495
|
tokens.shift()
|
|
493
496
|
} else if (tokens[0].type === TokenType.ELEMENT_QUERY) {
|
|
494
|
-
node =
|
|
495
|
-
tokens.shift()
|
|
497
|
+
node = ElementQueryNode.parse(node, tokens[0], tokens);
|
|
496
498
|
} else if (tokens[0].type === TokenType.L_BRACKET) {
|
|
497
499
|
if (node) {
|
|
498
500
|
node = IndexNode.parse(node, token, tokens);
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
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
|
-
|
|
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
|
+
}
|
package/src/attributes/List.ts
CHANGED
|
@@ -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.
|
|
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
package/test/Controller.spec.ts
CHANGED
|
@@ -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.
|
|
37
|
-
expect(await dom.
|
|
38
|
-
await dom.
|
|
39
|
-
expect(await dom.
|
|
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.
|
|
32
|
-
expect(await dom.
|
|
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-styles to just work", (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.
|
|
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>
|