divhunt 2.0.19 → 2.0.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.
@@ -82,17 +82,21 @@ divhunt.AddonReady('directives', function()
82
82
  event.stopPropagation();
83
83
  }
84
84
 
85
- await methods.submit();
85
+ const form = event.target.closest('form') || event.target;
86
+
87
+ await methods.submit(form);
86
88
  };
87
89
  };
88
90
 
89
- methods.submit = async () =>
91
+ methods.submit = async (form) =>
90
92
  {
91
93
  if(compile.data[config.bind].loading)
92
94
  {
93
95
  return;
94
96
  }
95
97
 
98
+ const formData = divhunt.FormGet(form);
99
+
96
100
  compile.data[config.bind].loading = true;
97
101
  compile.data[config.bind].error = null;
98
102
 
@@ -100,7 +104,6 @@ divhunt.AddonReady('directives', function()
100
104
 
101
105
  try
102
106
  {
103
- const formData = divhunt.FormGet(config.form);
104
107
  const result = config.api
105
108
  ? await commands.Fn('api', config.command, formData)
106
109
  : await commands.Fn('run', config.command, formData);
@@ -119,7 +122,7 @@ divhunt.AddonReady('directives', function()
119
122
  compile.data[config.bind].error = null;
120
123
  compile.data[config.bind].loading = false;
121
124
 
122
- config.reset && config.form.reset();
125
+ config.reset && form.reset();
123
126
  config.onSuccess && config.onSuccess(compile.data[config.bind]);
124
127
  }
125
128
  catch(error)
@@ -52,7 +52,7 @@ directives.Fn('process.data', function(attributes, node, compile)
52
52
  {
53
53
  try
54
54
  {
55
- attribute.value = divhunt.Function(attribute.value, compile, false);
55
+ attribute.value = divhunt.Function(attribute.value, compile.data, false);
56
56
  }
57
57
  catch(error)
58
58
  {
@@ -17,7 +17,8 @@ directives.ItemAdd({
17
17
 
18
18
  if (!result)
19
19
  {
20
- node.remove();
20
+ const placeholder = document.createComment('dh-if:' + identifier);
21
+ node.replaceWith(placeholder);
21
22
  return false;
22
23
  }
23
24
  }
@@ -57,10 +57,18 @@ directives.ItemAdd({
57
57
  loopData[forIndex] = index;
58
58
 
59
59
  const compiled = item.Compile(html, loopData);
60
+ const key = divhunt.GenerateHash(typeof value === 'object' ? JSON.stringify(value) : String(value));
60
61
 
61
62
  while(compiled.element.firstChild)
62
63
  {
63
- fragment.appendChild(compiled.element.firstChild);
64
+ const child = compiled.element.firstChild;
65
+
66
+ if(child.nodeType === Node.ELEMENT_NODE)
67
+ {
68
+ child.setAttribute('dh-key', key);
69
+ }
70
+
71
+ fragment.appendChild(child);
64
72
  }
65
73
  });
66
74
 
@@ -144,13 +144,13 @@ directives.ItemAdd({
144
144
  methods.submit = async () =>
145
145
  {
146
146
  const state = compile.data[config.bind];
147
+ const formData = methods.extract();
147
148
 
148
149
  state.loading = true;
149
150
  state.error = null;
150
151
 
151
152
  try
152
153
  {
153
- const formData = methods.extract();
154
154
  const submitData = Object.assign({}, formData, config.data);
155
155
  const response = await methods.fetch(submitData);
156
156
 
@@ -1,3 +1,9 @@
1
+ import divhunt from '#framework/load.js';
1
2
  import pages from './addon.js';
2
3
 
4
+ divhunt.$dh.page = function(route, parameters = {})
5
+ {
6
+ return pages.Fn('change', route, parameters, { path: true });
7
+ };
8
+
3
9
  export default pages;
@@ -15,7 +15,7 @@ class DivhuntAddonRender
15
15
  this.Callback = callback;
16
16
 
17
17
  this._updateTimeout = null;
18
- this.Data = { state: window.__STATE__ || {} };
18
+ this.Data = { state: addon.divhunt.StateGet() };
19
19
  this.Attributes = {};
20
20
  this.Item = null;
21
21
  this.Slots = {};
@@ -52,20 +52,11 @@ const RenderCompile =
52
52
 
53
53
  compile.nodes[identifier] = node;
54
54
 
55
- const originalRemove = node.remove;
56
- let wasRemoved = false;
57
-
58
- node.remove = function()
59
- {
60
- wasRemoved = true;
61
- originalRemove.call(this);
62
- };
55
+ const parent = node.parentNode;
63
56
 
64
57
  this.GetDivhunt().Emit('addon.render.compile.node', this, compile, node, identifier);
65
58
 
66
- node.remove = originalRemove;
67
-
68
- if(wasRemoved)
59
+ if(node.parentNode !== parent)
69
60
  {
70
61
  return;
71
62
  }
@@ -178,7 +178,6 @@ const RenderMethods =
178
178
  return this.EventOn('resize', callback);
179
179
  },
180
180
 
181
-
182
181
  OnError(callback)
183
182
  {
184
183
  return this.EventOn('error', callback);
@@ -2,7 +2,7 @@ const RenderSet =
2
2
  {
3
3
  SetData(data)
4
4
  {
5
- this.Data = Object.assign({ state: window.__STATE__ || {} }, data);
5
+ this.Data = Object.assign({ state: this.GetDivhunt().StateGet() }, data);
6
6
  return this;
7
7
  },
8
8
 
@@ -18,6 +18,7 @@ import DivhuntError from './mixins/error.js';
18
18
  import DivhuntCrypto from './mixins/crypto.js';
19
19
  import DivhuntForm from './mixins/form.js';
20
20
  import DivhuntCookie from './mixins/cookie.js';
21
+ import DivhuntState from './mixins/state.js';
21
22
 
22
23
  class Divhunt
23
24
  {
@@ -89,5 +90,6 @@ Object.assign(Divhunt.prototype, DivhuntError);
89
90
  Object.assign(Divhunt.prototype, DivhuntCrypto);
90
91
  Object.assign(Divhunt.prototype, DivhuntForm);
91
92
  Object.assign(Divhunt.prototype, DivhuntCookie);
93
+ Object.assign(Divhunt.prototype, DivhuntState);
92
94
 
93
95
  export default Divhunt;
@@ -61,9 +61,17 @@ const DivhuntDOM =
61
61
 
62
62
  if(current.nodeType === Node.ELEMENT_NODE)
63
63
  {
64
+ const isInput = current.nodeName === 'INPUT' || current.nodeName === 'TEXTAREA' || current.nodeName === 'SELECT';
65
+ const savedValue = isInput ? current.value : null;
66
+
64
67
  this.DOMPatchAttributes(current, target);
65
68
  this.DOMPatchChildren(current, target);
66
69
 
70
+ if(isInput && savedValue !== null && !target.hasAttribute('value'))
71
+ {
72
+ current.value = savedValue;
73
+ }
74
+
67
75
  for(const key in target)
68
76
  {
69
77
  if(key.startsWith('dh') && typeof target[key] === 'function')
@@ -101,27 +109,78 @@ const DivhuntDOM =
101
109
 
102
110
  DOMPatchChildren(current, target)
103
111
  {
104
- const currentChildren = Array.from(current.childNodes);
105
- const targetChildren = Array.from(target.childNodes);
112
+ const isWhitespace = (node) => node.nodeType === Node.TEXT_NODE && !node.textContent.trim();
113
+
114
+ const currentChildren = Array.from(current.childNodes).filter(n => !isWhitespace(n));
115
+ const targetChildren = Array.from(target.childNodes).filter(n => !isWhitespace(n));
106
116
 
107
- const maxLength = Math.max(currentChildren.length, targetChildren.length);
117
+ const getKey = (node) => node.nodeType === Node.ELEMENT_NODE && node.getAttribute('dh-key');
118
+ const hasKeys = targetChildren.some(n => getKey(n));
108
119
 
109
- for(let i = 0; i < maxLength; i++)
120
+ if(hasKeys)
110
121
  {
111
- const currentChild = currentChildren[i];
112
- const targetChild = targetChildren[i];
122
+ const currentByKey = new Map();
113
123
 
114
- if(!targetChild)
124
+ currentChildren.forEach(child =>
115
125
  {
116
- current.removeChild(currentChild);
117
- }
118
- else if(!currentChild)
126
+ const key = getKey(child);
127
+
128
+ if(key)
129
+ {
130
+ currentByKey.set(key, child);
131
+ }
132
+ });
133
+
134
+ const used = new Set();
135
+
136
+ targetChildren.forEach(targetChild =>
119
137
  {
120
- current.appendChild(targetChild);
121
- }
122
- else
138
+ const key = getKey(targetChild);
139
+ const match = key && currentByKey.get(key);
140
+
141
+ if(match)
142
+ {
143
+ used.add(key);
144
+ current.appendChild(match);
145
+ this.DOMPatch(match, targetChild);
146
+ }
147
+ else
148
+ {
149
+ current.appendChild(targetChild);
150
+ }
151
+ });
152
+
153
+ currentChildren.forEach(child =>
154
+ {
155
+ const key = getKey(child);
156
+
157
+ if(key && !used.has(key) && child.parentNode === current)
158
+ {
159
+ current.removeChild(child);
160
+ }
161
+ });
162
+ }
163
+ else
164
+ {
165
+ const maxLength = Math.max(currentChildren.length, targetChildren.length);
166
+
167
+ for(let i = 0; i < maxLength; i++)
123
168
  {
124
- this.DOMPatch(currentChild, targetChild);
169
+ const currentChild = currentChildren[i];
170
+ const targetChild = targetChildren[i];
171
+
172
+ if(!targetChild)
173
+ {
174
+ current.removeChild(currentChild);
175
+ }
176
+ else if(!currentChild)
177
+ {
178
+ current.appendChild(targetChild);
179
+ }
180
+ else
181
+ {
182
+ this.DOMPatch(currentChild, targetChild);
183
+ }
125
184
  }
126
185
  }
127
186
  },
@@ -0,0 +1,38 @@
1
+ const DivhuntState =
2
+ {
3
+ StateGet(key)
4
+ {
5
+ const state = this.environment === 'front' ? window.__STATE__ : global.__STATE__;
6
+
7
+ if(!state)
8
+ {
9
+ return key ? undefined : {};
10
+ }
11
+
12
+ return key ? state[key] : state;
13
+ },
14
+
15
+ StateSet(key, value)
16
+ {
17
+ if(this.environment === 'front')
18
+ {
19
+ if(!window.__STATE__)
20
+ {
21
+ window.__STATE__ = {};
22
+ }
23
+
24
+ window.__STATE__[key] = value;
25
+ }
26
+ else
27
+ {
28
+ if(!global.__STATE__)
29
+ {
30
+ global.__STATE__ = {};
31
+ }
32
+
33
+ global.__STATE__[key] = value;
34
+ }
35
+ }
36
+ };
37
+
38
+ export default DivhuntState;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "divhunt",
3
- "version": "2.0.19",
3
+ "version": "2.0.20",
4
4
  "description": "Full-stack isomorphic JavaScript framework built from scratch. One addon abstraction powers databases, servers, commands, pages, directives, queues, and more.",
5
5
  "type": "module",
6
6
  "main": "lib/load.js",