@pageboard/html 0.11.14 → 0.11.16

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pageboard/html",
3
- "version": "0.11.14",
3
+ "version": "0.11.16",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -214,18 +214,17 @@ class HTMLElementFieldsetList extends VirtualHTMLElement {
214
214
  const form = this.closest('form');
215
215
  const values = form.read(true);
216
216
  const list = this.#listFromValues(values);
217
- const prefix = this.#prefix;
218
- if (!this.#walk) this.#walk = new WalkIndex(this, (node) => {
219
- if (node.name?.startsWith(prefix)) {
220
- const index = Number(node.name.substring(prefix.length).split('.').shift());
221
- if (Number.isInteger(index) || index >= 0 || index < list.length) {
222
- return index;
223
- }
224
- }
225
- return null;
217
+
218
+ if (!this.#walk) this.#walk = new WalkIndex(this, node => {
219
+ const { index } = this.#parseName(node.name);
220
+ if (index >= 0 && index < list.length) return index;
221
+ else return null;
226
222
  });
227
223
  let index;
228
224
 
225
+ const fileInputs = this.querySelectorAll('[name][type="file"]')
226
+ .map(n => n.cloneNode(true));
227
+
229
228
  switch (action) {
230
229
  case "add":
231
230
  list.splice((this.#walk.findBefore(btn) ?? -1) + 1, 0, this.#model);
@@ -248,6 +247,26 @@ class HTMLElementFieldsetList extends VirtualHTMLElement {
248
247
  }
249
248
  this.#listToValues(values, list);
250
249
  form.fill(values, state.scope);
250
+ const liveFileInputs = this.querySelectorAll('[name][type="file"]');
251
+ for (const node of fileInputs) {
252
+ const { value } = node;
253
+ const { sub } = this.#parseName(node.name);
254
+ const live = liveFileInputs.find(node => node.value == value);
255
+ if (!live) continue;
256
+ if (this.#parseName(live.name).sub === sub) {
257
+ node.name = live.name;
258
+ live.replaceWith(node);
259
+ }
260
+ }
261
+ }
262
+
263
+ #parseName(name) {
264
+ const prefix = this.prefix;
265
+ if (!name?.startsWith(prefix)) return { index: -1 };
266
+ const parts = name.substring(prefix.length).split('.');
267
+ const index = Number(parts.shift());
268
+ if (!Number.isInteger(index)) return { index: -1 };
269
+ return { index, sub: parts.join('.') };
251
270
  }
252
271
 
253
272
  get ownTpl() {
package/ui/fieldset.js CHANGED
@@ -8,9 +8,10 @@ class HTMLCustomFieldSetElement extends HTMLFieldSetElement {
8
8
  this.init?.();
9
9
  }
10
10
 
11
- #update() {
12
- if (this.isContentEditable || !this.options.name) return;
13
- const val = this.form?.read(true)?.[this.options.name];
11
+ fill(query) {
12
+ if (this.isContentEditable || !this.options?.name || !this.form) return;
13
+ if (!query) query = this.form.read(true);
14
+ const val = query[this.options.name];
14
15
  const disabled = this.disabled = this.hidden = val != this.options.value;
15
16
  for (const node of this.querySelectorAll('[name]')) {
16
17
  node.disabled = disabled;
@@ -19,8 +20,8 @@ class HTMLCustomFieldSetElement extends HTMLFieldSetElement {
19
20
 
20
21
  patch(state) {
21
22
  // before/after form#fill
22
- this.#update();
23
- state.finish(() => this.#update());
23
+ this.fill();
24
+ state.finish(() => this.fill());
24
25
  }
25
26
  setup() {
26
27
  this.form?.addEventListener('change', this);
@@ -30,7 +31,7 @@ class HTMLCustomFieldSetElement extends HTMLFieldSetElement {
30
31
  }
31
32
  handleEvent(e) {
32
33
  if (e.type == "change") {
33
- this.#update();
34
+ this.fill();
34
35
  }
35
36
  }
36
37
  }
package/ui/form.js CHANGED
@@ -123,54 +123,15 @@ class HTMLCustomFormElement extends HTMLFormElement {
123
123
  if (!name) continue;
124
124
  if (name in query && !vars.includes(name)) vars.push(name);
125
125
  const val = query[name];
126
- const str = ((v) => {
127
- if (v == null) {
128
- return "";
129
- } else if (Array.isArray(v)) {
130
- if (["radio", "checkbox", "select-multiple"].includes(elem.type)) {
131
- return v;
132
- } else {
133
- return v.shift();
134
- }
135
- } else if (typeof v == "object") {
136
- return v;
137
- } else {
138
- return v.toString();
139
- }
140
- })(val);
141
- switch (elem.type) {
142
- case 'submit':
143
- break;
144
- case 'radio':
145
- case 'checkbox':
146
- if (Array.isArray(val) && val.length == 0 && elem.value == "") {
147
- elem.checked = true;
148
- } else {
149
- elem.checked = (Array.isArray(val) ? val : [str]).some((str) => {
150
- return str.toString() == elem.value;
151
- });
152
- }
153
- break;
154
- case 'select-multiple':
155
- elem.fill(str);
156
- break;
157
- case 'textarea':
158
- elem.innerText = str;
159
- break;
160
- case 'hidden':
161
- if (val !== undefined) elem.value = str;
162
- break;
163
- case 'button':
164
- break;
165
- default:
166
- if (elem.fill) {
167
- elem.fill(str);
168
- } else {
169
- elem.value = str;
170
- }
171
- break;
126
+ if (val === undefined) {
127
+ elem.reset?.();
128
+ } else {
129
+ elem.fill?.(val);
172
130
  }
173
131
  }
132
+ for (const node of this.querySelectorAll('fieldset[is="element-fieldset"]')) {
133
+ node.fill(query);
134
+ }
174
135
  return vars;
175
136
  }
176
137
  save() {
@@ -266,7 +227,7 @@ class HTMLCustomFormElement extends HTMLFormElement {
266
227
 
267
228
  form.classList.add('loading');
268
229
 
269
- const data = { $query };
230
+ const data = { $query };
270
231
  return Promise.all(Array.from(form.elements).filter((node) => {
271
232
  return Boolean(node.presubmit);
272
233
  }).map((input) => {
@@ -356,12 +317,11 @@ Page.ready(() => {
356
317
  VirtualHTMLElement.define(`element-form`, HTMLCustomFormElement, 'form');
357
318
  });
358
319
 
359
-
360
- HTMLSelectElement.prototype.fill = function (values) {
361
- if (!Array.isArray(values)) values = [values];
320
+ HTMLSelectElement.prototype.fill = function (val) {
321
+ if (!Array.isArray(val)) val = [val];
362
322
  for (let i = 0; i < this.options.length; i++) {
363
323
  const opt = this.options[i];
364
- opt.selected = values.indexOf(opt.value) > -1;
324
+ opt.selected = val.indexOf(opt.value) > -1;
365
325
  }
366
326
  };
367
327
  HTMLSelectElement.prototype.reset = function () {
@@ -371,12 +331,24 @@ HTMLSelectElement.prototype.reset = function () {
371
331
  HTMLInputElement.prototype.fill = function (val) {
372
332
  if (val == null) val = "";
373
333
  if (this.type == "radio" || this.type == "checkbox") {
374
- this.checked = val;
375
- } else if (this.type == "file") {
376
- if (val == '' || val == null) this.removeAttribute('value');
377
- else this.setAttribute('value', val);
334
+ if (Array.isArray(val) && val.length == 0 && this.value == "") {
335
+ this.checked = true;
336
+ } else {
337
+ this.checked = (Array.isArray(val) ? val : [val]).some(str => {
338
+ return str.toString() == this.value;
339
+ });
340
+ }
378
341
  } else {
379
- this.value = val;
342
+ if (Array.isArray(val)) {
343
+ console.warn("Avoid fill(array) on scalar input", this, val);
344
+ val = val.shift();
345
+ }
346
+ if (this.type == "file") {
347
+ if (val === '') this.removeAttribute('value');
348
+ else this.setAttribute('value', val);
349
+ } else {
350
+ this.value = val;
351
+ }
380
352
  }
381
353
  };
382
354
 
@@ -398,6 +370,10 @@ HTMLInputElement.prototype.save = function () {
398
370
  }
399
371
  };
400
372
 
373
+ HTMLTextAreaElement.prototype.fill = function (val) {
374
+ this.value = val == null ? '' : val;
375
+ };
376
+
401
377
  HTMLTextAreaElement.prototype.reset = function () {
402
378
  this.value = this.defaultValue;
403
379
  };