vsn 0.1.19 → 0.1.20

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
@@ -8,6 +8,8 @@ import {On} from "./attributes/On";
8
8
  import {Registry} from "./Registry";
9
9
  import {benchmarkEnd, benchmarkStart} from "./Bencmark";
10
10
  import {DOMObject} from "./DOM/DOMObject";
11
+ import { Tree } from "./AST";
12
+ import {StyleAttribute} from "./attributes/StyleAttribute";
11
13
 
12
14
  export enum TagState {
13
15
  Instantiated,
@@ -104,6 +106,12 @@ export class Tag extends DOMObject {
104
106
  }
105
107
  }
106
108
 
109
+ public async eval(code: string) {
110
+ const tree = new Tree(code);
111
+ await tree.prepare(this.scope, this.dom, this);
112
+ return await tree.evaluate(this.scope, this.dom, this);
113
+ }
114
+
107
115
  public async evaluate() {
108
116
  for (const attr of this.nonDeferredAttributes) {
109
117
  await attr.evaluate();
@@ -480,6 +488,31 @@ export class Tag extends DOMObject {
480
488
  return standardAttribute;
481
489
  }
482
490
 
491
+ async watchStyle(styleName: string) {
492
+ for (const attribute of this.attributes) {
493
+ if (attribute instanceof StyleAttribute) {
494
+ return attribute;
495
+ }
496
+ }
497
+
498
+ // Standard attribute requires a unique scope
499
+ // @todo: Does this cause any issues with attribute bindings on the parent scope prior to having its own scope? hmm...
500
+ if (!this.uniqueScope) {
501
+ this._uniqueScope = true;
502
+ this._scope = new Scope();
503
+
504
+ if (this.parentTag) {
505
+ this.scope.parentScope = this.parentTag.scope;
506
+ }
507
+ }
508
+
509
+ const styleAttribute = new StyleAttribute(this, 'style');
510
+ this.attributes.push(styleAttribute);
511
+ await this.setupAttribute(styleAttribute);
512
+
513
+ return styleAttribute;
514
+ }
515
+
483
516
  private async setupAttribute(attribute: Attribute) {
484
517
  await attribute.compile();
485
518
  await attribute.setup();
package/src/Vision.ts CHANGED
@@ -72,5 +72,5 @@ export * from './Registry';
72
72
  export * from './Attribute';
73
73
  export * from './AST';
74
74
  export {DOM} from './DOM';
75
- export {WrappedArray, Scope} from './Scope';
75
+ export {WrappedArray, Scope, ScopeReference} from './Scope';
76
76
  export const vision: Vision = Vision.instance;
@@ -0,0 +1,68 @@
1
+ import {Registry} from "../Registry";
2
+ import {Attribute} from "../Attribute";
3
+ import {Scope, ScopeReference} from "../Scope";
4
+
5
+
6
+ @Registry.attribute('vsn-styles')
7
+ export class StyleAttribute extends Attribute {
8
+ private scopeRef: ScopeReference;
9
+ private styleScope: Scope;
10
+
11
+ public async setup() {
12
+ const key = this.getAttributeValue() || null;
13
+ if (key) {
14
+ this.scopeRef = this.tag.scope.getReference(key, true);
15
+ const parentScope = await this.scopeRef.getScope();
16
+ const styleKey = await this.scopeRef.getKey();
17
+ this.styleScope = parentScope.get(styleKey);
18
+ if (!this.styleScope) {
19
+ this.styleScope = new Scope(parentScope);
20
+ parentScope.set(styleKey, this.styleScope);
21
+ }
22
+ } else {
23
+ this.styleScope = this.tag.scope;
24
+ }
25
+
26
+ await super.setup();
27
+ }
28
+
29
+ public async connect() {
30
+ this.styleScope.bind(`change`, this.handleEvent.bind(this));
31
+ await super.connect();
32
+ }
33
+
34
+ public async extract() {
35
+ this.updateFrom();
36
+ await super.extract();
37
+ }
38
+
39
+ updateFrom() {
40
+ const toSkip = [
41
+ 'cssText',
42
+ 'length'
43
+ ]
44
+ for (const k in this.tag.style) {
45
+ if (toSkip.indexOf(k) > -1 || isFinite(k as any))
46
+ continue;
47
+ const value = this.tag.style[k];
48
+ const key = `$${k}`;
49
+ if (value && value !== this.styleScope.get(key))
50
+ this.styleScope.set(key, value);
51
+ }
52
+ }
53
+
54
+ public mutate(mutation: MutationRecord) {
55
+ super.mutate(mutation);
56
+ this.updateFrom();
57
+ }
58
+
59
+ public async handleEvent(k, v) {
60
+ if (k.startsWith('$')) {
61
+ const key = k.substr(1);
62
+
63
+ if (v.value !== v.previousValue) {
64
+ this.tag.element.style[key] = v.value;
65
+ }
66
+ }
67
+ }
68
+ }
@@ -23,5 +23,6 @@ export {ScopeAttribute} from "./ScopeAttribute";
23
23
  export {ScopeChange} from "./ScopeChange";
24
24
  export {SetAttribute} from "./SetAttribute";
25
25
  export {StandardAttribute} from "./StandardAttribute";
26
+ export {StyleAttribute} from "./StyleAttribute";
26
27
  export {Template} from "./Template";
27
28
  export {TypeAttribute} from "./TypeAttribute";
@@ -0,0 +1,32 @@
1
+ import {DOM} from "../../src/DOM";
2
+ import "../../src/Types";
3
+ import "../../src/attributes/_imports";
4
+
5
+
6
+ describe('Styles', () => {
7
+ it("vsn-styles to just work", (done) => {
8
+ document.body.innerHTML = `
9
+ <span vsn-styles="testing.styles" style="margin-top: 50px;">testing</span>
10
+ `;
11
+ const dom = new DOM(document);
12
+ dom.once('built', async () => {
13
+ const scope = dom.root.scope;
14
+ console.log(scope.get('testing'));
15
+ expect(scope.get('testing')).toBeTruthy();
16
+ expect(scope.get('testing').get('styles')).toBeTruthy();
17
+ done();
18
+ });
19
+ });
20
+
21
+ it("$ operator should work", (done) => {
22
+ document.body.innerHTML = `
23
+ <span id="styling">testing</span>
24
+ `;
25
+ const dom = new DOM(document);
26
+ dom.once('built', async () => {
27
+ await dom.eval('?(#styling).$marginTop = "50px"');
28
+ expect((await dom.get('#styling'))[0].element.style.marginTop).toBe('50px');
29
+ done();
30
+ });
31
+ });
32
+ });