wallace 0.0.6 → 0.0.8

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/lib/component.js CHANGED
@@ -1,15 +1,15 @@
1
1
  /**
2
2
  * The base component.
3
3
  */
4
- export function Component(parent) {
5
- this.parent = parent; // The parent component
4
+ export function Component() {
5
+ this.ctrl = undefined; // The controller.
6
6
  this.props = undefined; // The props passed to the component. May be changed.
7
- this.el = null; // the element - will be set during build
8
- this.ref = {}; // user set references to elements or components
7
+ this.el = null; // the element - will be set during build.
8
+ this.ref = {}; // user set references to elements or components.
9
9
  // Internal state objects
10
- this._o = []; // stashed objects like pools.
11
- this._e = {}; // stashed elements.
12
- this._p = {}; // The previous values for watches to compare against
10
+ this._e = {}; // The dynamic elements in the DOM.
11
+ this._p = {}; // The previous values for watches to compare against.
12
+ this._s = []; // A stash for misc objects.
13
13
  }
14
14
 
15
15
  var proto = Component.prototype;
@@ -21,10 +21,11 @@ Object.defineProperty(proto, "hidden", {
21
21
  });
22
22
 
23
23
  /**
24
- * Sets the props and updates the component.
24
+ * The render function that gets called by parent components.
25
25
  */
26
- proto.render = function (props) {
26
+ proto.render = function (props, ctrl) {
27
27
  this.props = props;
28
+ this.ctrl = ctrl;
28
29
  this.update();
29
30
  };
30
31
 
@@ -36,29 +37,83 @@ proto.update = function () {
36
37
  let i = 0,
37
38
  watch,
38
39
  element,
39
- shieldQuery,
40
- shieldQueryResult,
41
- shouldBeVisible;
40
+ parent,
41
+ displayToggle,
42
+ detacher,
43
+ lookupReturn,
44
+ lookupTrue,
45
+ shouldBeVisible,
46
+ visibilityChanged,
47
+ detachedElements,
48
+ detachedElement,
49
+ index,
50
+ adjustedIndex,
51
+ thisElement;
42
52
 
43
- const watches = this.__wc;
53
+ const watches = this._w;
44
54
  const lookup = this._l;
45
55
  const props = this.props;
46
56
  lookup.reset();
47
57
  const il = watches.length;
58
+ /*
59
+ Watches is an array of objects with keys:
60
+ e: the element reference (string)
61
+ c: the callbacks (object)
62
+ ?v: visibility toggle (object)
63
+
64
+ The display toggle has keys:
65
+ q: the query key in lookup
66
+ s: the number of watches to skip as their node is underneath
67
+ r: reversed
68
+ ?d: detacher
69
+
70
+ The detacher has keys:
71
+ i: the initial element index
72
+ s: the stash key of the detacher (plain object)
73
+ e: the parent element key
74
+ */
48
75
  while (i < il) {
49
76
  watch = watches[i];
50
- element = this._e[watch.wk];
51
- shieldQuery = watch.sq;
77
+ element = this._e[watch.e];
78
+ displayToggle = watch.v;
52
79
  i++;
53
80
  shouldBeVisible = true;
54
- if (shieldQuery) {
55
- shieldQueryResult = !!lookup.get(this, props, shieldQuery).n;
56
- shouldBeVisible = watch.rv ? shieldQueryResult : !shieldQueryResult;
57
- element.hidden = !shouldBeVisible;
58
- i += shouldBeVisible ? 0 : watch.sc;
81
+ if (displayToggle) {
82
+ lookupReturn = lookup.get(this, props, displayToggle.q);
83
+ lookupTrue = !!lookupReturn.n;
84
+ shouldBeVisible = displayToggle.r ? lookupTrue : !lookupTrue;
85
+ visibilityChanged = lookupTrue != !!lookupReturn.o;
86
+ detacher = displayToggle.d;
87
+ if (detacher) {
88
+ index = detacher.i;
89
+ parent = this._e[detacher.e];
90
+ detachedElements = this._s[detacher.s];
91
+ detachedElement = detachedElements[index];
92
+ if (shouldBeVisible && detachedElement) {
93
+ adjustedIndex =
94
+ index -
95
+ Object.keys(detachedElements).filter(function (k) {
96
+ return k < index && detachedElements[k];
97
+ }).length;
98
+ parent.insertBefore(
99
+ detachedElement,
100
+ parent.childNodes[adjustedIndex],
101
+ );
102
+ detachedElements[index] = null;
103
+ } else if (!shouldBeVisible && !detachedElement) {
104
+ thisElement = this._e[watch.e];
105
+ parent.removeChild(thisElement);
106
+ detachedElements[index] = thisElement;
107
+ }
108
+ } else {
109
+ element.hidden = !shouldBeVisible;
110
+ }
111
+ if (!shouldBeVisible) {
112
+ i += displayToggle.s;
113
+ }
59
114
  }
60
115
  if (shouldBeVisible) {
61
- lookup.applyCallbacks(this, props, element, watch.cb);
116
+ lookup.applyCallbacks(this, props, element, watch.c);
62
117
  }
63
118
  }
64
119
  };
package/lib/index.js CHANGED
@@ -1,16 +1,16 @@
1
- import { createComponent, createProxy, mount } from "./utils";
1
+ import { createComponent, watch, mount } from "./utils";
2
2
  import { Component } from "./component";
3
- import { KeyedPool, SequentialPool } from "./pool";
3
+ import { KeyedRepeater, SequentialRepeater } from "./repeaters";
4
4
  import {
5
5
  extendComponent,
6
6
  findElement,
7
- getKeyedPool,
8
- getSequentialPool,
7
+ getKeyedRepeater,
8
+ getSequentialRepeater,
9
9
  onEvent,
10
10
  nestComponent,
11
11
  defineComponent,
12
12
  extendPrototype,
13
- saveMiscObject,
13
+ stashMisc,
14
14
  saveRef,
15
15
  } from "./initCalls";
16
16
 
@@ -18,17 +18,17 @@ export {
18
18
  extendComponent,
19
19
  Component,
20
20
  createComponent,
21
- createProxy,
21
+ watch,
22
22
  defineComponent,
23
23
  extendPrototype,
24
24
  findElement,
25
- getKeyedPool,
26
- getSequentialPool,
27
- KeyedPool,
25
+ getKeyedRepeater,
26
+ getSequentialRepeater,
27
+ KeyedRepeater,
28
28
  mount,
29
29
  nestComponent,
30
30
  onEvent,
31
- saveMiscObject,
31
+ stashMisc,
32
32
  saveRef,
33
- SequentialPool,
33
+ SequentialRepeater,
34
34
  };
package/lib/initCalls.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Component } from "./component";
2
2
  import { Lookup } from "./lookup";
3
3
  import { buildComponent, replaceNode } from "./utils";
4
- import { KeyedPool, SequentialPool } from "./pool";
4
+ import { KeyedRepeater, SequentialRepeater } from "./repeaters";
5
5
  const throwAway = document.createElement("template");
6
6
 
7
7
  /**
@@ -20,15 +20,15 @@ export const findElement = (rootElement, path) => {
20
20
  return path.reduce((acc, index) => acc.childNodes[index], rootElement);
21
21
  };
22
22
 
23
- export const nestComponent = (rootElement, path, cls, parent) => {
23
+ export const nestComponent = (rootElement, path, cls) => {
24
24
  const el = findElement(rootElement, path),
25
- child = buildComponent(cls, parent);
25
+ child = buildComponent(cls);
26
26
  replaceNode(el, child.el);
27
27
  return child;
28
28
  };
29
29
 
30
30
  /**
31
- * Saves a reference to element or nested component. Can be used to wrap a stash call.
31
+ * Saves a reference to element or nested component. Returns the element.
32
32
  */
33
33
  export const saveRef = (element, component, name) => {
34
34
  component.ref[name] = element;
@@ -36,10 +36,11 @@ export const saveRef = (element, component, name) => {
36
36
  };
37
37
 
38
38
  /**
39
- * Saves a misc object (anything that's not an element). Can be used to wrap a stash call.
39
+ * Stash something on the component. Returns the element.
40
+ * The generated code is expected to keep track of the position.
40
41
  */
41
- export const saveMiscObject = (element, component, object) => {
42
- component._o.push(object);
42
+ export const stashMisc = (element, component, object) => {
43
+ component._s.push(object);
43
44
  return element;
44
45
  };
45
46
 
@@ -48,15 +49,12 @@ export const onEvent = (element, eventName, callback) => {
48
49
  return element;
49
50
  };
50
51
 
51
- /**
52
- * Creates a pool.
53
- */
54
- export const getKeyedPool = (cls, keyFn) => {
55
- return new KeyedPool(cls, keyFn);
52
+ export const getKeyedRepeater = (cls, keyFn) => {
53
+ return new KeyedRepeater(cls, keyFn);
56
54
  };
57
55
 
58
- export const getSequentialPool = (cls) => {
59
- return new SequentialPool(cls);
56
+ export const getSequentialRepeater = (cls) => {
57
+ return new SequentialRepeater(cls);
60
58
  };
61
59
 
62
60
  export function defineComponent(
@@ -82,21 +80,16 @@ export function extendComponent(
82
80
  lookups,
83
81
  buildFunction,
84
82
  ) {
85
- prototype.__wc = watches.map((arr) => ({
86
- wk: arr[0], // The key of the corresponding element.
87
- sq: arr[1], // The shield query key
88
- rv: arr[2], // whether shieldQuery should be flipped
89
- sc: arr[3], // The number of items to shield
90
- cb: arr[4], // The callbacks - object
91
- }));
83
+ //Ensure these do not clash with fields on the component itself.
84
+ prototype._w = watches;
92
85
  prototype._l = new Lookup(lookups);
93
86
  prototype._b = buildFunction;
94
87
  prototype._n = makeEl(html);
95
88
  }
96
89
 
97
90
  export function extendPrototype(base, prototypeExtras) {
98
- const Constructor = function (parent) {
99
- base.call(this, parent);
91
+ const Constructor = function () {
92
+ base.call(this);
100
93
  };
101
94
  Constructor.prototype = Object.create(base && base.prototype, {
102
95
  constructor: {
@@ -3,17 +3,17 @@ import { createComponent } from "./utils";
3
3
  /*
4
4
  * Gets a component from the pool.
5
5
  */
6
- const getComponent = (pool, componentClass, key, item, parent) => {
6
+ function getComponent(pool, componentDefinition, ctrl, key, props) {
7
7
  let component;
8
8
  if (pool.hasOwnProperty(key)) {
9
9
  component = pool[key];
10
- component.render(item);
10
+ component.render(props, ctrl);
11
11
  } else {
12
- component = createComponent(componentClass, parent, item);
12
+ component = createComponent(componentDefinition, props, ctrl);
13
13
  pool[key] = component;
14
14
  }
15
15
  return component;
16
- };
16
+ }
17
17
 
18
18
  /**
19
19
  * Trims the unwanted child elements from the end.
@@ -44,29 +44,27 @@ function pull(arr, item, to) {
44
44
  }
45
45
 
46
46
  /**
47
- * Pools same type components, retrieving by key.
48
- * Must not be shared.
47
+ * Repeats nested components, reusing items based on key.
49
48
  *
50
- * @param {class} componentClass - The class of Component to create.
51
- * @param {function} keyFn - A function which obtains the key to pool by
49
+ * @param {function} componentDefinition - The ComponentDefinition to create.
50
+ * @param {function} keyFn - A function which obtains the key.
52
51
  */
53
- export function KeyedPool(componentClass, keyFn) {
54
- this._v = componentClass;
52
+ export function KeyedRepeater(componentDefinition, keyFn) {
53
+ this._v = componentDefinition;
55
54
  this._f = keyFn;
56
55
  this._k = []; // keys
57
56
  this._p = {}; // pool of component instances
58
57
  }
59
- const proto = KeyedPool.prototype;
58
+ const proto = KeyedRepeater.prototype;
60
59
 
61
60
  /**
62
61
  * Retrieves a single component. Though not used in wallace itself, it may
63
62
  * be used elsewhere, such as in the router.
64
63
  *
65
64
  * @param {Object} item - The item which will be passed as props.
66
- * @param {Component} parent - The parent component.
67
65
  */
68
- proto.getOne = function (item, parent) {
69
- return getComponent(this._p, this._v, this._f(item), item, parent);
66
+ proto.getOne = function (item, ctrl) {
67
+ return getComponent(this._p, this._v, ctrl, this._f(item), item);
70
68
  };
71
69
 
72
70
  /**
@@ -75,13 +73,12 @@ proto.getOne = function (item, parent) {
75
73
  *
76
74
  * @param {DOMElement} e - The DOM element to patch.
77
75
  * @param {Array} items - Array of items which will be passed as props.
78
- * @param {Component} parent - The parent component.
79
76
  */
80
- proto.patch = function (e, items, parent) {
77
+ proto.patch = function (e, items, ctrl) {
81
78
  // Attempt to speed up by reducing lookups. Does this even do anything?
82
79
  // Does webpack undo this/do it for for me? Does the engine?
83
80
  const pool = this._p;
84
- const componentClass = this._v;
81
+ const componentDefinition = this._v;
85
82
  const keyFn = this._f;
86
83
  const childNodes = e.childNodes;
87
84
  const itemsLength = items.length;
@@ -94,7 +91,7 @@ proto.patch = function (e, items, parent) {
94
91
  for (let i = 0; i < itemsLength; i++) {
95
92
  item = items[i];
96
93
  key = keyFn(item);
97
- component = getComponent(pool, componentClass, key, item, parent);
94
+ component = getComponent(pool, componentDefinition, ctrl, key, item);
98
95
  newKeys.push(key);
99
96
  if (i > childElementCount) {
100
97
  e.appendChild(component.el);
@@ -108,12 +105,12 @@ proto.patch = function (e, items, parent) {
108
105
  };
109
106
 
110
107
  /**
111
- * Pools same type components, retrieving by sequence.
108
+ * Repeats nested components, yielding from its pool sequentially.
112
109
  *
113
- * @param {class} componentClass - The class of Component to create.
110
+ * @param {componentDefinition} componentDefinition - The class ComponentDefinition to create.
114
111
  */
115
- export function SequentialPool(componentClass) {
116
- this._v = componentClass;
112
+ export function SequentialRepeater(componentDefinition) {
113
+ this._v = componentDefinition;
117
114
  this._p = []; // pool of component instances
118
115
  this._c = 0; // Child element count
119
116
  }
@@ -124,11 +121,11 @@ export function SequentialPool(componentClass) {
124
121
  *
125
122
  * @param {DOMElement} e - The DOM element to patch.
126
123
  * @param {Array} items - Array of items which will be passed as props.
127
- * @param {Component} parent - The parent component.
124
+ * @param {any} ctrl - The parent item's controller.
128
125
  */
129
- SequentialPool.prototype.patch = function (e, items, parent) {
126
+ SequentialRepeater.prototype.patch = function (e, items, ctrl) {
130
127
  const pool = this._p;
131
- const componentClass = this._v;
128
+ const componentDefinition = this._v;
132
129
  const childNodes = e.childNodes;
133
130
  const itemsLength = items.length;
134
131
  let item,
@@ -140,9 +137,9 @@ SequentialPool.prototype.patch = function (e, items, parent) {
140
137
  item = items[i];
141
138
  if (i < poolCount) {
142
139
  component = pool[i];
143
- component.render(item);
140
+ component.render(item, ctrl);
144
141
  } else {
145
- component = createComponent(componentClass, parent, item);
142
+ component = createComponent(componentDefinition, item, ctrl);
146
143
  pool.push(component);
147
144
  poolCount++;
148
145
  }
package/lib/types.d.ts CHANGED
@@ -27,9 +27,10 @@ declare module "wallace" {
27
27
  element: string | HTMLElement,
28
28
  component: Accepts<T>,
29
29
  props?: T,
30
+ ctrl?: any,
30
31
  ): Component<T>;
31
32
 
32
- export function createProxy<T>(obj: T, component: Component<T>): T;
33
+ export function watch<T>(obj: T, callback: CallableFunction): T;
33
34
 
34
35
  export function extendPrototype<T>(
35
36
  base: Accepts<T>,
package/lib/utils.js CHANGED
@@ -4,10 +4,9 @@
4
4
  * @param {unsure} elementOrId Either a string representing an id, or an element.
5
5
  * @param {class} cls The class of Component to create
6
6
  * @param {object} props The props to pass to the component (optional)
7
- * @param {object} parent The parent component (optional)
8
7
  */
9
- export function mount(elementOrId, cls, props, parent) {
10
- const component = createComponent(cls, parent, props);
8
+ export function mount(elementOrId, cls, props, ctrl) {
9
+ const component = createComponent(cls, props, ctrl);
11
10
  replaceNode(getElement(elementOrId), component.el);
12
11
  return component;
13
12
  }
@@ -26,35 +25,34 @@ export function getElement(elementOrId) {
26
25
  * Creates a component and initialises it.
27
26
  *
28
27
  * @param {class} cls The class of Component to create
29
- * @param {object} parent The parent component (optional)
30
28
  * @param {object} props The props to pass to the component (optional)
31
29
  */
32
- export function createComponent(cls, parent, props) {
33
- const component = buildComponent(cls, parent);
34
- component.render(props);
30
+ export function createComponent(cls, props, ctrl) {
31
+ const component = buildComponent(cls);
32
+ component.render(props, ctrl);
35
33
  return component;
36
34
  }
37
35
 
38
36
  /**
39
- * Builds a component.
37
+ * Builds a component's initial DOM.
40
38
  */
41
- export function buildComponent(cls, parent) {
42
- const component = new cls(parent);
43
- const prototype = cls.prototype;
44
- const dom = prototype._n.cloneNode(true);
39
+ export function buildComponent(cls) {
40
+ const component = new cls();
41
+ const proto = cls.prototype;
42
+ const dom = proto._n.cloneNode(true);
45
43
  component.el = dom;
46
- component._b(component, dom);
44
+ proto._b(component, dom);
47
45
  return component;
48
46
  }
49
47
 
50
48
  /**
51
- * Wraps target in a Proxy which calls component.update() whenever it is modified.
49
+ * Wraps target in a Proxy which calls a function whenever it is modified.
52
50
  *
53
51
  * @param {*} target - Any object, including arrays.
54
- * @param {*} component - A component.
55
- * @returns a Proxy object.
52
+ * @param {*} callback - A callback function.
53
+ * @returns a Proxy of the object.
56
54
  */
57
- export const createProxy = (target, component) => {
55
+ export function watch(target, callback) {
58
56
  const handler = {
59
57
  get(target, key) {
60
58
  if (key == "isProxy") return true;
@@ -67,9 +65,9 @@ export const createProxy = (target, component) => {
67
65
  },
68
66
  set(target, key, value) {
69
67
  target[key] = value;
70
- component.update();
68
+ callback();
71
69
  return true;
72
70
  },
73
71
  };
74
72
  return new Proxy(target, handler);
75
- };
73
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wallace",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "author": "Andrew Buchan",
5
5
  "description": "The framework that brings you glee.",
6
6
  "license": "ISC",
@@ -13,8 +13,8 @@
13
13
  "test": "jest --clearCache && jest"
14
14
  },
15
15
  "dependencies": {
16
- "babel-plugin-wallace": "^0.0.6",
16
+ "babel-plugin-wallace": "^0.0.8",
17
17
  "browserify": "^17.0.1"
18
18
  },
19
- "gitHead": "3742fbcfdc21146c90252c2436fde91634fafa9e"
19
+ "gitHead": "7548afec467b0e4f6e433a401cca08acb3dc7bc7"
20
20
  }