vsn 0.1.130 → 0.1.132
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/examples/cascading-function-sheets.html +27 -7
- package/demo/examples/item-filtering.html +1 -1
- package/demo/examples/persist.html +17 -0
- package/demo/resources/xhr-lazy.html +4 -3
- package/demo/resources/xhr-persist.html +40 -0
- package/demo/vsn.js +2 -2
- package/dist/AST/AssignmentNode.js.map +1 -1
- package/dist/AST/ClassNode.d.ts +3 -0
- package/dist/AST/ClassNode.js +10 -6
- package/dist/AST/ClassNode.js.map +1 -1
- package/dist/AST/FunctionNode.js +11 -3
- package/dist/AST/FunctionNode.js.map +1 -1
- package/dist/AST/IndexNode.js +0 -1
- package/dist/AST/IndexNode.js.map +1 -1
- package/dist/Attribute.js.map +1 -1
- package/dist/DOM/AbstractDOM.d.ts +1 -0
- package/dist/DOM/AbstractDOM.js +116 -91
- package/dist/DOM/AbstractDOM.js.map +1 -1
- package/dist/DOM/DOMObject.js +3 -0
- package/dist/DOM/DOMObject.js.map +1 -1
- package/dist/Tag.d.ts +1 -0
- package/dist/Tag.js +22 -9
- package/dist/Tag.js.map +1 -1
- package/dist/attributes/PersistAttribute.d.ts +15 -0
- package/dist/attributes/PersistAttribute.js +215 -0
- package/dist/attributes/PersistAttribute.js.map +1 -0
- 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/demo.min.js +3 -0
- package/dist/demo.min.js.LICENSE.txt +9 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/vsn.min.js +3 -0
- package/dist/vsn.min.js.LICENSE.txt +9 -0
- package/package.json +1 -1
- package/src/AST/AssignmentNode.ts +1 -0
- package/src/AST/ClassNode.ts +9 -4
- package/src/AST/FunctionNode.ts +11 -3
- package/src/AST/IndexNode.ts +0 -1
- package/src/Attribute.ts +0 -1
- package/src/DOM/AbstractDOM.ts +18 -3
- package/src/DOM/DOMObject.ts +3 -0
- package/src/Tag.ts +19 -10
- package/src/attributes/PersistAttribute.ts +83 -0
- package/src/attributes/_imports.ts +1 -0
- package/src/version.ts +1 -1
- package/test/AST/ClassNode.spec.ts +5 -5
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
|
|
4
|
+
* This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
|
5
|
+
* The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
|
6
|
+
* The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
|
7
|
+
* Code distributed by Google as part of the polymer project is also
|
|
8
|
+
* subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
|
9
|
+
*/
|
package/package.json
CHANGED
package/src/AST/ClassNode.ts
CHANGED
|
@@ -14,6 +14,7 @@ export class ClassNode extends Node implements TreeNode {
|
|
|
14
14
|
public static readonly classParents: {[name: string]: string[]} = {};
|
|
15
15
|
public static readonly classChildren: {[name: string]: string[]} = {}; // List of child class selectors for a given class selector
|
|
16
16
|
public static readonly preppedTags: {[name: string]: Tag[]} = {};
|
|
17
|
+
public static readonly preppingElements: {[name: string]: HTMLElement[]} = {};
|
|
17
18
|
|
|
18
19
|
protected requiresPrep: boolean = true;
|
|
19
20
|
public readonly classScope: Scope = new Scope();
|
|
@@ -59,6 +60,7 @@ export class ClassNode extends Node implements TreeNode {
|
|
|
59
60
|
ClassNode.classes[this._fullSelector] = this;
|
|
60
61
|
ClassNode.classChildren[this._fullSelector] = [];
|
|
61
62
|
ClassNode.preppedTags[this._fullSelector] = [];
|
|
63
|
+
ClassNode.preppingElements[this._fullSelector] = []
|
|
62
64
|
|
|
63
65
|
if (ClassNode.classParents[this.selector] === undefined)
|
|
64
66
|
ClassNode.classParents[this.selector] = [];
|
|
@@ -79,8 +81,11 @@ export class ClassNode extends Node implements TreeNode {
|
|
|
79
81
|
|
|
80
82
|
public async findClassElements(dom: DOM, tag: Tag = null) {
|
|
81
83
|
const tags: Tag[] = [];
|
|
82
|
-
for (const element of Array.from(dom.querySelectorAll(this.
|
|
84
|
+
for (const element of Array.from(dom.querySelectorAll(this.fullSelector, tag))) {
|
|
85
|
+
if (ClassNode.preppingElements[this._fullSelector].indexOf(element as HTMLElement) > -1) continue;
|
|
86
|
+
ClassNode.preppingElements[this._fullSelector].push(element as HTMLElement);
|
|
83
87
|
tags.push(await ClassNode.addElementClass(this._fullSelector, element as HTMLElement, dom, element[Tag.TaggedVariable] || null));
|
|
88
|
+
ClassNode.preppingElements[this._fullSelector].splice(ClassNode.preppingElements[this._fullSelector].indexOf(element as HTMLElement), 1);
|
|
84
89
|
}
|
|
85
90
|
|
|
86
91
|
for (const childSelector of ClassNode.classChildren[this._fullSelector]) {
|
|
@@ -107,7 +112,7 @@ export class ClassNode extends Node implements TreeNode {
|
|
|
107
112
|
await this.block.prepare(tag.scope, dom, tag, meta);
|
|
108
113
|
if (hasConstruct) {
|
|
109
114
|
const fncCls: FunctionNode = this.classScope.get('construct') as FunctionNode;
|
|
110
|
-
const fnc = await fncCls.getFunction(tag.scope, dom, tag,
|
|
115
|
+
const fnc = await fncCls.getFunction(tag.scope, dom, tag, true);
|
|
111
116
|
await fnc();
|
|
112
117
|
}
|
|
113
118
|
tag.dispatch(`${this.fullSelector}.construct`, tag.element.id);
|
|
@@ -120,7 +125,7 @@ export class ClassNode extends Node implements TreeNode {
|
|
|
120
125
|
|
|
121
126
|
if (hasDeconstruct) {
|
|
122
127
|
const fncCls: FunctionNode = this.classScope.get('deconstruct') as FunctionNode;
|
|
123
|
-
const fnc = await fncCls.getFunction(tag.scope, dom, tag,
|
|
128
|
+
const fnc = await fncCls.getFunction(tag.scope, dom, tag, true);
|
|
124
129
|
await fnc();
|
|
125
130
|
}
|
|
126
131
|
for (const key of this.classScope.keys) {
|
|
@@ -131,7 +136,7 @@ export class ClassNode extends Node implements TreeNode {
|
|
|
131
136
|
}
|
|
132
137
|
tag.dispatch(`${this.fullSelector}.deconstruct`);
|
|
133
138
|
ClassNode.preppedTags[this.fullSelector].splice(ClassNode.preppedTags[this.fullSelector].indexOf(tag), 1);
|
|
134
|
-
|
|
139
|
+
ClassNode.removePreparedClassFromElement(tag.element, this.fullSelector);
|
|
135
140
|
}
|
|
136
141
|
|
|
137
142
|
public async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
|
package/src/AST/FunctionNode.ts
CHANGED
|
@@ -24,8 +24,15 @@ export class FunctionNode extends Node implements TreeNode {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
public async prepare(scope: Scope, dom: DOM, tag: Tag = null, meta?: any): Promise<void> {
|
|
27
|
-
if (
|
|
28
|
-
|
|
27
|
+
// if (meta?.ClassNode) {
|
|
28
|
+
// // Set on object instance
|
|
29
|
+
// if (tag && tag.scope.has('this')) {
|
|
30
|
+
// tag.scope.get('this').set(this.name, this);
|
|
31
|
+
// }
|
|
32
|
+
// } else {
|
|
33
|
+
// scope.set(this.name, this);
|
|
34
|
+
// }
|
|
35
|
+
scope.set(this.name, this);
|
|
29
36
|
await super.prepare(scope, dom, tag, meta);
|
|
30
37
|
}
|
|
31
38
|
|
|
@@ -35,7 +42,7 @@ export class FunctionNode extends Node implements TreeNode {
|
|
|
35
42
|
|
|
36
43
|
public async collectGarbage() {
|
|
37
44
|
for (const f of this.garbage) {
|
|
38
|
-
f.
|
|
45
|
+
f.deconstruct();
|
|
39
46
|
}
|
|
40
47
|
this.garbage = [];
|
|
41
48
|
}
|
|
@@ -46,6 +53,7 @@ export class FunctionNode extends Node implements TreeNode {
|
|
|
46
53
|
let functionScope;
|
|
47
54
|
if (createFunctionScope && !(scope instanceof FunctionScope)) {
|
|
48
55
|
functionScope = new FunctionScope(scope);
|
|
56
|
+
functionScope.set('this', scope);
|
|
49
57
|
self.garbage.push(functionScope);
|
|
50
58
|
} else {
|
|
51
59
|
functionScope = scope;
|
package/src/AST/IndexNode.ts
CHANGED
package/src/Attribute.ts
CHANGED
package/src/DOM/AbstractDOM.ts
CHANGED
|
@@ -177,6 +177,21 @@ export abstract class AbstractDOM extends EventDispatcher {
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
public getTagsFromParent(parent: Node, includeParent: boolean = true) {
|
|
181
|
+
const tags: Tag[] = [];
|
|
182
|
+
if (includeParent) {
|
|
183
|
+
if (parent[Tag.TaggedVariable]) {
|
|
184
|
+
tags.push(parent[Tag.TaggedVariable]);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
for (const ele of Array.from(parent.childNodes)) {
|
|
189
|
+
tags.push(...this.getTagsFromParent(ele, true));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return tags;
|
|
193
|
+
}
|
|
194
|
+
|
|
180
195
|
public async mutation(mutations: MutationRecord[]) {
|
|
181
196
|
for (const mutation of mutations) {
|
|
182
197
|
let tag: Tag = await this.getTagForElement(mutation.target as HTMLElement);
|
|
@@ -190,9 +205,9 @@ export abstract class AbstractDOM extends EventDispatcher {
|
|
|
190
205
|
}
|
|
191
206
|
|
|
192
207
|
for (const ele of Array.from(mutation.removedNodes)) {
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
208
|
+
for (const tag of this.getTagsFromParent(ele)) {
|
|
209
|
+
if (tag.hasAttribute('vsn-template')) continue;
|
|
210
|
+
tag.deconstruct();
|
|
196
211
|
}
|
|
197
212
|
}
|
|
198
213
|
}
|
package/src/DOM/DOMObject.ts
CHANGED
package/src/Tag.ts
CHANGED
|
@@ -89,6 +89,10 @@ export class Tag extends DOMObject {
|
|
|
89
89
|
return this._meta;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
public get state(): TagState {
|
|
93
|
+
return this._state;
|
|
94
|
+
}
|
|
95
|
+
|
|
92
96
|
protected onAttributeStateChange(event) {
|
|
93
97
|
if (event.previouseState === AttributeState.Deferred) // @todo: what is this?
|
|
94
98
|
this._nonDeferredAttributes.length = 0;
|
|
@@ -264,17 +268,18 @@ export class Tag extends DOMObject {
|
|
|
264
268
|
}
|
|
265
269
|
|
|
266
270
|
public findParentTag() {
|
|
267
|
-
let parentElement: HTMLElement = DOM.getParentElement(this.element);
|
|
268
271
|
let foundParent = false;
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
272
|
+
if (this.element) {
|
|
273
|
+
let parentElement: HTMLElement = DOM.getParentElement(this.element);
|
|
274
|
+
while (parentElement) {
|
|
275
|
+
if (parentElement[Tag.TaggedVariable]) {
|
|
276
|
+
foundParent = true;
|
|
277
|
+
this.parentTag = parentElement[Tag.TaggedVariable];
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
parentElement = DOM.getParentElement(parentElement);
|
|
274
281
|
}
|
|
275
|
-
parentElement = DOM.getParentElement(parentElement);
|
|
276
282
|
}
|
|
277
|
-
|
|
278
283
|
if (!foundParent && DOM.instance.root !== this)
|
|
279
284
|
return DOM.instance.root;
|
|
280
285
|
}
|
|
@@ -288,7 +293,7 @@ export class Tag extends DOMObject {
|
|
|
288
293
|
}
|
|
289
294
|
|
|
290
295
|
public set parentTag(tag: Tag) {
|
|
291
|
-
if (this.element === document.body)
|
|
296
|
+
if (this.element === document.body || tag.element === document.body)
|
|
292
297
|
return;
|
|
293
298
|
|
|
294
299
|
if (this._parentTag && this._parentTag !== tag) {
|
|
@@ -316,7 +321,7 @@ export class Tag extends DOMObject {
|
|
|
316
321
|
if (!!this.parentTag)
|
|
317
322
|
return this.parentTag.scope;
|
|
318
323
|
|
|
319
|
-
return
|
|
324
|
+
return DOM.instance.root.scope;
|
|
320
325
|
}
|
|
321
326
|
|
|
322
327
|
public get controller(): Controller {
|
|
@@ -802,6 +807,10 @@ export class Tag extends DOMObject {
|
|
|
802
807
|
this._controller.deconstruct();
|
|
803
808
|
this._controller = null;
|
|
804
809
|
}
|
|
810
|
+
if (this.element) {
|
|
811
|
+
this.element[Tag.TaggedVariable] = null;
|
|
812
|
+
(this as any).element = null;
|
|
813
|
+
}
|
|
805
814
|
super.deconstruct();
|
|
806
815
|
}
|
|
807
816
|
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {Registry} from "../Registry";
|
|
2
|
+
import {Attribute} from "../Attribute";
|
|
3
|
+
import {TagState} from "../Tag";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export interface IPersistedValue {
|
|
7
|
+
attribute: string,
|
|
8
|
+
value: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@Registry.attribute('vsn-persist')
|
|
12
|
+
export class PersistAttribute extends Attribute {
|
|
13
|
+
public static readonly persistedValues: Map<string, Map<string, string | string[]>> = new Map<string, Map<string, string | string[]>>();
|
|
14
|
+
public static readonly canDefer: boolean = true;
|
|
15
|
+
|
|
16
|
+
protected valueKeys: string[] = [];
|
|
17
|
+
|
|
18
|
+
public async extract() {
|
|
19
|
+
this.valueKeys = this.getAttributeValue().split(' ').map((v: string) => v.trim()).filter((v: string) => v.length > 0);
|
|
20
|
+
await super.extract();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public async connect() {
|
|
24
|
+
const elementId = this.tag.element.id;
|
|
25
|
+
|
|
26
|
+
if (!elementId)
|
|
27
|
+
throw new Error('vsn-persist requires an id attribute on the element');
|
|
28
|
+
|
|
29
|
+
const persistedValues = PersistAttribute.getPersistedValueStore(elementId);
|
|
30
|
+
for (const key of this.valueKeys) {
|
|
31
|
+
if (persistedValues.has(key)) {
|
|
32
|
+
if (key === '@class') {
|
|
33
|
+
const classes = persistedValues.get(key);
|
|
34
|
+
this.tag.element.classList.remove(...Array.from(this.tag.element.classList));
|
|
35
|
+
this.tag.element.classList.add(...classes);
|
|
36
|
+
} else if (key.startsWith('@')) {
|
|
37
|
+
this.tag.element.setAttribute(key.substring(1), persistedValues.get(key) as string);
|
|
38
|
+
if (this.tag.isInput) {
|
|
39
|
+
this.tag.once('$built', () => {
|
|
40
|
+
this.tag.element.dispatchEvent(new Event('input'));
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
await super.connect();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public mutate(mutation: MutationRecord) {
|
|
52
|
+
if (this.tag.state !== TagState.Built)
|
|
53
|
+
return;
|
|
54
|
+
|
|
55
|
+
this.updateFrom();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
protected updateFrom() {
|
|
59
|
+
const elementId = this.tag.element.id;
|
|
60
|
+
const persistedValues = PersistAttribute.getPersistedValueStore(elementId);
|
|
61
|
+
|
|
62
|
+
for (const key of this.valueKeys) {
|
|
63
|
+
if (key === '@class') {
|
|
64
|
+
const classes = Array.from(this.tag.element.classList);
|
|
65
|
+
persistedValues.set(key, classes);
|
|
66
|
+
} else if (key.startsWith('@')) {
|
|
67
|
+
persistedValues.set(key, this.tag.element.getAttribute(key.substring(1)));
|
|
68
|
+
if (this.tag.isInput) {
|
|
69
|
+
this.tag.dispatch('input');
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public static getPersistedValueStore(elementId: string) {
|
|
78
|
+
if (!PersistAttribute.persistedValues.has(elementId))
|
|
79
|
+
PersistAttribute.persistedValues.set(elementId, new Map<string, string>());
|
|
80
|
+
|
|
81
|
+
return PersistAttribute.persistedValues.get(elementId);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -16,6 +16,7 @@ export {ListItemModel} from "./ListItemModel";
|
|
|
16
16
|
export {ModelAttribute} from "./ModelAttribute";
|
|
17
17
|
export {Name} from "./Name";
|
|
18
18
|
export {On} from "./On";
|
|
19
|
+
export {PersistAttribute} from "./PersistAttribute";
|
|
19
20
|
export {Referenced} from "./Referenced";
|
|
20
21
|
export {RootAttribute} from "./RootAttribute";
|
|
21
22
|
export {ScopeAttribute} from "./ScopeAttribute";
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = '0.1.
|
|
1
|
+
export const VERSION = '0.1.132';
|
|
2
2
|
|
|
@@ -52,13 +52,13 @@ describe('ClassNode', () => {
|
|
|
52
52
|
<script type="text/vsn" vsn-script>
|
|
53
53
|
class .simple-construct {
|
|
54
54
|
func construct() {
|
|
55
|
-
a|integer = "15";
|
|
56
|
-
log('####### construct', a);
|
|
55
|
+
this.a|integer = "15";
|
|
56
|
+
log('####### construct', this.a);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
func test() {
|
|
60
|
-
a += 1;
|
|
61
|
-
log('####### testing', a);
|
|
60
|
+
this.a += 1;
|
|
61
|
+
log('####### testing', this.a);
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
</script>
|
|
@@ -82,7 +82,7 @@ describe('ClassNode', () => {
|
|
|
82
82
|
<script type="text/vsn" vsn-script>
|
|
83
83
|
class .testing {
|
|
84
84
|
func construct() {
|
|
85
|
-
a|integer = 0;
|
|
85
|
+
this.a|integer = 0;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
class .test {
|