vsn 0.1.53 → 0.1.56

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/src/Tag.ts CHANGED
@@ -21,6 +21,8 @@ export enum TagState {
21
21
  Built,
22
22
  }
23
23
 
24
+ export const TaggedVariable:string = '_vsn_tag';
25
+
24
26
  export class Tag extends DOMObject {
25
27
  public readonly rawAttributes: { [key: string]: string; };
26
28
  public readonly parsedAttributes: { [key: string]: string[]; };
@@ -55,6 +57,7 @@ export class Tag extends DOMObject {
55
57
  ...props
56
58
  ) {
57
59
  super(element, props);
60
+ element[TaggedVariable] = this;
58
61
  this.rawAttributes = {};
59
62
  this.parsedAttributes = {};
60
63
  this.attributes = [];
@@ -232,6 +235,23 @@ export class Tag extends DOMObject {
232
235
  }
233
236
 
234
237
  public get parentTag(): Tag {
238
+ if (!this._parentTag) {
239
+ let parentElement: HTMLElement = this.element.parentElement as HTMLElement;
240
+ let foundParent = false;
241
+ while (parentElement) {
242
+ if (parentElement[TaggedVariable]) {
243
+ foundParent = true;
244
+ this.parentTag = parentElement[TaggedVariable];
245
+ break;
246
+ }
247
+
248
+ parentElement = parentElement.parentElement as HTMLElement;
249
+ }
250
+
251
+ if (!foundParent && DOM.instance.root !== this)
252
+ return DOM.instance.root;
253
+ }
254
+
235
255
  return this._parentTag;
236
256
  }
237
257
 
@@ -250,8 +270,11 @@ export class Tag extends DOMObject {
250
270
  if (!!this._scope)
251
271
  return this._scope;
252
272
 
253
- if (!!this._parentTag)
254
- return this._parentTag.scope;
273
+ if (this.uniqueScope)
274
+ return this.createScope();
275
+
276
+ if (!!this.parentTag)
277
+ return this.parentTag.scope;
255
278
 
256
279
  return null;
257
280
  }
@@ -290,7 +313,7 @@ export class Tag extends DOMObject {
290
313
  }
291
314
 
292
315
  public addToParentElement() {
293
- this._parentTag.element.appendChild(this.element)
316
+ this.parentTag.element.appendChild(this.element)
294
317
  }
295
318
 
296
319
  public hide() {
@@ -304,7 +327,6 @@ export class Tag extends DOMObject {
304
327
  public findAncestorByAttribute(attr: string, includeSelf: boolean = false): Tag {
305
328
  if (includeSelf && this.hasAttribute(attr))
306
329
  return this;
307
-
308
330
  return this.parentTag ? this.parentTag.findAncestorByAttribute(attr, true) : null;
309
331
  }
310
332
 
@@ -432,7 +454,6 @@ export class Tag extends DOMObject {
432
454
 
433
455
  if (requiresScope && !this.uniqueScope) {
434
456
  this._uniqueScope = true;
435
- this._scope = new Scope();
436
457
  }
437
458
 
438
459
  this._state = TagState.AttributesBuilt;
@@ -569,17 +590,21 @@ export class Tag extends DOMObject {
569
590
  }
570
591
  }
571
592
 
572
- public createScope() {
593
+ public createScope(force: boolean = false): Scope {
573
594
  // Standard attribute requires a unique scope
574
595
  // @todo: Does this cause any issues with attribute bindings on the parent scope prior to having its own scope? hmm...
575
- if (!this.uniqueScope) {
596
+ if ((!this.uniqueScope && force) || this.uniqueScope) {
576
597
  this._uniqueScope = true;
577
598
  this._scope = new Scope();
578
599
 
579
600
  if (this.parentTag) {
580
601
  this.scope.parentScope = this.parentTag.scope;
581
602
  }
603
+
604
+ return this._scope;
582
605
  }
606
+
607
+ return null;
583
608
  }
584
609
 
585
610
  async watchAttribute(attributeName: string) {
@@ -589,7 +614,7 @@ export class Tag extends DOMObject {
589
614
  }
590
615
  }
591
616
 
592
- this.createScope();
617
+ this.createScope(true);
593
618
 
594
619
  const standardAttribute = new StandardAttribute(this, attributeName);
595
620
  this.attributes.push(standardAttribute);
@@ -605,7 +630,7 @@ export class Tag extends DOMObject {
605
630
  }
606
631
  }
607
632
 
608
- this.createScope();
633
+ this.createScope(true);
609
634
 
610
635
  const styleAttribute = new StyleAttribute(this, 'style');
611
636
  this.attributes.push(styleAttribute);
@@ -25,9 +25,11 @@ export class List extends Attribute {
25
25
  public async setup() {
26
26
  if (this.tag.element.children.length > 0) {
27
27
  const template = this.tag.element.children[0];
28
+ const templateTag: Tag = await this.tag.dom.getTagForElement(template);
28
29
 
29
30
  if (template) {
30
31
  if (template.hasAttribute('vsn-template')) {
32
+ templateTag.parentTag = this.tag; // Set parentTag before removing from DOM
31
33
  template.removeAttribute('vsn-template');
32
34
  this.tag.element.removeChild(template);
33
35
  this.template = template;
@@ -10,18 +10,24 @@ export class ScopeAttribute extends Attribute {
10
10
  protected tree: Tree;
11
11
 
12
12
  public async compile() {
13
- this.tree = new Tree(this.getAttributeValue());
14
- await this.tree.prepare(this.tag.scope, this.tag.dom, this.tag);
13
+ const code = this.getAttributeValue();
14
+ if (code) {
15
+ this.tree = new Tree(code);
16
+ await this.tree.prepare(this.tag.scope, this.tag.dom, this.tag);
17
+ }
15
18
  await super.compile();
16
19
  }
17
20
 
18
21
  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]);
22
+ if (this.tree) {
23
+ const value = await this.tree.evaluate(this.tag.scope, this.tag.dom, this.tag);
24
+ if (!(value instanceof Scope)) {
25
+ throw new Error(`vsn-scope value must be an object, got ${typeof value}`);
26
+ }
27
+ for (const key of value.data.keys) {
28
+ this.tag.scope.set(key, value.data[key]);
29
+ }
25
30
  }
31
+ await super.extract();
26
32
  }
27
33
  }
@@ -68,6 +68,7 @@ describe('ListItem', () => {
68
68
  </ul>
69
69
  </div>
70
70
  `;
71
+ console.log('########### test');
71
72
  const dom = new DOM(document);
72
73
  dom.once('built', async () => {
73
74
  const list = await dom.getTagForElement(document.getElementById('test'));
@@ -20,4 +20,16 @@ describe('ScopeAttribute', () => {
20
20
  done();
21
21
  });
22
22
  });
23
+
24
+ it("vsn-scope should allow empty value to create a scope", (done) => {
25
+ document.body.innerHTML = `
26
+ <div vsn-scope></div>
27
+ `;
28
+ const dom = new DOM(document);
29
+ dom.once('built', async () => {
30
+ const element = (await dom.exec('?(div)'))[0];
31
+ expect(element.uniqueScope).toBe(true);
32
+ done();
33
+ });
34
+ });
23
35
  });