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.
Files changed (48) hide show
  1. package/demo/examples/cascading-function-sheets.html +27 -7
  2. package/demo/examples/item-filtering.html +1 -1
  3. package/demo/examples/persist.html +17 -0
  4. package/demo/resources/xhr-lazy.html +4 -3
  5. package/demo/resources/xhr-persist.html +40 -0
  6. package/demo/vsn.js +2 -2
  7. package/dist/AST/AssignmentNode.js.map +1 -1
  8. package/dist/AST/ClassNode.d.ts +3 -0
  9. package/dist/AST/ClassNode.js +10 -6
  10. package/dist/AST/ClassNode.js.map +1 -1
  11. package/dist/AST/FunctionNode.js +11 -3
  12. package/dist/AST/FunctionNode.js.map +1 -1
  13. package/dist/AST/IndexNode.js +0 -1
  14. package/dist/AST/IndexNode.js.map +1 -1
  15. package/dist/Attribute.js.map +1 -1
  16. package/dist/DOM/AbstractDOM.d.ts +1 -0
  17. package/dist/DOM/AbstractDOM.js +116 -91
  18. package/dist/DOM/AbstractDOM.js.map +1 -1
  19. package/dist/DOM/DOMObject.js +3 -0
  20. package/dist/DOM/DOMObject.js.map +1 -1
  21. package/dist/Tag.d.ts +1 -0
  22. package/dist/Tag.js +22 -9
  23. package/dist/Tag.js.map +1 -1
  24. package/dist/attributes/PersistAttribute.d.ts +15 -0
  25. package/dist/attributes/PersistAttribute.js +215 -0
  26. package/dist/attributes/PersistAttribute.js.map +1 -0
  27. package/dist/attributes/_imports.d.ts +1 -0
  28. package/dist/attributes/_imports.js +3 -1
  29. package/dist/attributes/_imports.js.map +1 -1
  30. package/dist/demo.min.js +3 -0
  31. package/dist/demo.min.js.LICENSE.txt +9 -0
  32. package/dist/version.d.ts +1 -1
  33. package/dist/version.js +1 -1
  34. package/dist/vsn.min.js +3 -0
  35. package/dist/vsn.min.js.LICENSE.txt +9 -0
  36. package/package.json +1 -1
  37. package/src/AST/AssignmentNode.ts +1 -0
  38. package/src/AST/ClassNode.ts +9 -4
  39. package/src/AST/FunctionNode.ts +11 -3
  40. package/src/AST/IndexNode.ts +0 -1
  41. package/src/Attribute.ts +0 -1
  42. package/src/DOM/AbstractDOM.ts +18 -3
  43. package/src/DOM/DOMObject.ts +3 -0
  44. package/src/Tag.ts +19 -10
  45. package/src/attributes/PersistAttribute.ts +83 -0
  46. package/src/attributes/_imports.ts +1 -0
  47. package/src/version.ts +1 -1
  48. 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vsn",
3
- "version": "0.1.130",
3
+ "version": "0.1.132",
4
4
  "description": "SEO Friendly Javascript/Typescript Framework",
5
5
  "keywords": [
6
6
  "framework",
@@ -117,6 +117,7 @@ export class AssignmentNode extends Node implements TreeNode {
117
117
  left /= right;
118
118
  break;
119
119
  }
120
+
120
121
  scope.set(key, left);
121
122
  return left;
122
123
  }
@@ -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.selector, tag))) {
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, false);
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, false);
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
- await ClassNode.removePreparedClassFromElement(tag.element, this.fullSelector);
139
+ ClassNode.removePreparedClassFromElement(tag.element, this.fullSelector);
135
140
  }
136
141
 
137
142
  public async evaluate(scope: Scope, dom: DOM, tag: Tag = null) {
@@ -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 (!meta?.ClassNode) // Don't muddle up tag scope if we're in a class
28
- scope.set(this.name, this);
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.collectGarbage();
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;
@@ -11,7 +11,6 @@ export class IndexNode extends Node implements TreeNode {
11
11
  public readonly indexTwo: Node = null
12
12
  ) {
13
13
  super();
14
- console.log('index node', object, index, indexTwo);
15
14
  }
16
15
 
17
16
  protected _getChildNodes(): Node[] {
package/src/Attribute.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import {Tag} from "./Tag";
2
- import {VisionHelper} from "./helpers/VisionHelper";
3
2
  import {EventDispatcher} from "./EventDispatcher";
4
3
  import {Modifiers} from "./Modifiers";
5
4
 
@@ -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 toRemove: Tag = await this.getTagForElement(ele as HTMLElement);
194
- if (toRemove) {
195
- toRemove.deconstruct();
208
+ for (const tag of this.getTagsFromParent(ele)) {
209
+ if (tag.hasAttribute('vsn-template')) continue;
210
+ tag.deconstruct();
196
211
  }
197
212
  }
198
213
  }
@@ -60,6 +60,9 @@ export abstract class DOMObject extends EventDispatcher {
60
60
  public deconstruct() {
61
61
  if (this._uniqueScope)
62
62
  this.scope?.deconstruct();
63
+ this.onEventHandlers = {};
64
+ this.slot = null;
65
+ this.delegates.length = 0;
63
66
  super.deconstruct();
64
67
  }
65
68
  }
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
- while (parentElement) {
270
- if (parentElement[Tag.TaggedVariable]) {
271
- foundParent = true;
272
- this.parentTag = parentElement[Tag.TaggedVariable];
273
- break;
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 null;
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.130';
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 {