@pageboard/html 0.14.9 → 0.14.10
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/elements/fieldsets.js +40 -4
- package/elements/form.js +2 -4
- package/elements/grid.js +1 -1
- package/elements/image.js +0 -3
- package/elements/input-date.js +1 -7
- package/elements/input-file.js +1 -7
- package/elements/input-property.js +1 -4
- package/elements/inputs.js +33 -22
- package/elements/layout.js +13 -8
- package/elements/link.js +66 -0
- package/elements/media.js +2 -2
- package/elements/menu.js +1 -1
- package/elements/navigation.js +1 -1
- package/elements/pagination.js +1 -1
- package/elements/sitemap.js +1 -56
- package/lib/object-fit-images.js +8 -3
- package/package.json +2 -7
- package/ui/button.css +11 -0
- package/ui/fieldset-list.js +120 -122
- package/ui/fieldset.js +5 -5
- package/ui/form.css +5 -2
- package/ui/form.js +22 -14
- package/ui/image.js +0 -17
- package/ui/input-file.css +1 -6
- package/ui/select.css +15 -0
- package/ui/select.js +76 -61
- package/ui/site.css +0 -21
- package/ui/sitemap-helper.js +0 -73
- package/ui/sitemap.css +0 -53
- package/ui/sitemap.js +0 -78
package/ui/fieldset-list.js
CHANGED
|
@@ -1,72 +1,44 @@
|
|
|
1
|
-
class WalkIndex {
|
|
2
|
-
#walk;
|
|
3
|
-
#find;
|
|
4
|
-
#index;
|
|
5
|
-
constructor(root, fn) {
|
|
6
|
-
this.#find = fn;
|
|
7
|
-
this.#walk = root.ownerDocument.createTreeWalker(
|
|
8
|
-
root,
|
|
9
|
-
NodeFilter.SHOW_ELEMENT,
|
|
10
|
-
this
|
|
11
|
-
);
|
|
12
|
-
}
|
|
13
|
-
acceptNode(node) {
|
|
14
|
-
const index = this.#find(node);
|
|
15
|
-
if (index != null) {
|
|
16
|
-
this.#index = index;
|
|
17
|
-
return NodeFilter.FILTER_ACCEPT;
|
|
18
|
-
} else {
|
|
19
|
-
return NodeFilter.FILTER_SKIP;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
findBefore(node) {
|
|
23
|
-
this.#index = null;
|
|
24
|
-
this.#walk.currentNode = node;
|
|
25
|
-
this.#walk.previousNode();
|
|
26
|
-
return this.#index;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
1
|
class HTMLElementFieldsetList extends Page.Element {
|
|
31
|
-
#
|
|
32
|
-
#
|
|
2
|
+
#list;
|
|
3
|
+
#defaultList;
|
|
33
4
|
#prefix;
|
|
34
5
|
#model;
|
|
35
|
-
#walk;
|
|
36
6
|
|
|
37
|
-
fill(values
|
|
38
|
-
if (
|
|
39
|
-
// unflatten array-values
|
|
40
|
-
const vars = [];
|
|
7
|
+
fill(values) {
|
|
8
|
+
if (this.isContentEditable || this.prefix == null) return;
|
|
41
9
|
for (const [key, val] of Object.entries(values)) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (Array.isArray(val)) {
|
|
10
|
+
const parts = this.#prefixed(key);
|
|
11
|
+
if (!parts) continue;
|
|
12
|
+
if (parts.length == 1 && Number.isInteger(Number(parts[0])) && Array.isArray(val)) {
|
|
13
|
+
console.warn("fielset-list should receive flat lists", key, val);
|
|
14
|
+
} else if (parts.length == 0 && Array.isArray(val)) {
|
|
45
15
|
for (let i = 0; i < val.length; i++) {
|
|
46
16
|
values[key + '.' + i] = val[i];
|
|
47
17
|
}
|
|
48
18
|
delete values[key];
|
|
49
19
|
}
|
|
50
20
|
}
|
|
51
|
-
|
|
52
|
-
if (this.#
|
|
53
|
-
this.#resize(
|
|
54
|
-
return vars;
|
|
21
|
+
this.#list = this.#listFromValues({ ...values });
|
|
22
|
+
if (this.#defaultList == null) this.save();
|
|
23
|
+
this.#resize();
|
|
55
24
|
}
|
|
56
25
|
|
|
57
26
|
reset() {
|
|
58
|
-
this.#
|
|
27
|
+
this.#list = this.#defaultList.slice();
|
|
28
|
+
this.#refresh();
|
|
59
29
|
}
|
|
60
30
|
|
|
61
31
|
save() {
|
|
62
|
-
this.#
|
|
32
|
+
this.#defaultList = this.#list.slice();
|
|
63
33
|
}
|
|
64
34
|
|
|
65
35
|
#modelize(tpl) {
|
|
66
36
|
const keys = new Set();
|
|
67
37
|
const inputs = tpl.querySelectorAll('[name]');
|
|
68
38
|
for (const node of inputs) {
|
|
69
|
-
|
|
39
|
+
// because custom elements are not started in templates, do not use .name
|
|
40
|
+
const name = node.getAttribute('name');
|
|
41
|
+
keys.add(name);
|
|
70
42
|
}
|
|
71
43
|
const splits = Array.from(keys).map(name => this.#parts(name));
|
|
72
44
|
const prefix = [];
|
|
@@ -90,27 +62,24 @@ class HTMLElementFieldsetList extends Page.Element {
|
|
|
90
62
|
this.#prefix = prefix;
|
|
91
63
|
const model = {};
|
|
92
64
|
for (const key of keys) {
|
|
93
|
-
|
|
94
|
-
|
|
65
|
+
const keyParts = this.#prefixed(key);
|
|
66
|
+
if (keyParts) {
|
|
67
|
+
model[keyParts.join('.')] = undefined;
|
|
95
68
|
}
|
|
96
69
|
}
|
|
97
70
|
this.#model = model;
|
|
98
71
|
}
|
|
99
72
|
|
|
100
|
-
|
|
73
|
+
prepare(editable) {
|
|
101
74
|
const tpl = this.ownTpl;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (scope.$write) {
|
|
111
|
-
this.#modelize(this.ownTpl);
|
|
112
|
-
} else if (!this.#size) {
|
|
113
|
-
this.#resize(0, scope);
|
|
75
|
+
if (editable) {
|
|
76
|
+
this.#modelize(tpl);
|
|
77
|
+
} else {
|
|
78
|
+
tpl.prerender();
|
|
79
|
+
this.#modelize(tpl.content);
|
|
80
|
+
for (const node of tpl.content.querySelectorAll('[block-id]')) {
|
|
81
|
+
node.removeAttribute('block-id');
|
|
82
|
+
}
|
|
114
83
|
}
|
|
115
84
|
}
|
|
116
85
|
|
|
@@ -123,82 +92,97 @@ class HTMLElementFieldsetList extends Page.Element {
|
|
|
123
92
|
for (let i = 0; i < p.length; i++) {
|
|
124
93
|
if (parts[i] != p[i]) return false;
|
|
125
94
|
}
|
|
126
|
-
return
|
|
95
|
+
return parts.slice(p.length);
|
|
127
96
|
}
|
|
128
97
|
|
|
129
98
|
#incrementkey(index, name) {
|
|
130
|
-
|
|
99
|
+
const nameParts = this.#prefixed(name);
|
|
100
|
+
if (!nameParts) return null;
|
|
131
101
|
const parts = this.#prefix.slice();
|
|
132
102
|
parts.push(index);
|
|
133
|
-
parts.push(...
|
|
103
|
+
parts.push(...nameParts);
|
|
134
104
|
return parts.join('.');
|
|
135
105
|
}
|
|
136
106
|
|
|
137
|
-
#resize(
|
|
138
|
-
if (scope.$write) return;
|
|
139
|
-
const len = Math.max(Number(this.dataset.size) || 0, size);
|
|
140
|
-
if (this.#size === len) return;
|
|
141
|
-
this.#size = len;
|
|
107
|
+
#resize() {
|
|
142
108
|
let tpl = this.ownTpl.content.cloneNode(true);
|
|
143
|
-
|
|
144
|
-
return { index: i };
|
|
145
|
-
});
|
|
109
|
+
|
|
146
110
|
const inputs = tpl.querySelectorAll('[name]');
|
|
147
111
|
for (const node of inputs) {
|
|
148
|
-
const name =
|
|
149
|
-
|
|
112
|
+
const name = node.getAttribute('name');
|
|
113
|
+
const iname = this.#incrementkey('[field.$i]', name);
|
|
114
|
+
if (iname != null) {
|
|
150
115
|
const id = node.id;
|
|
151
|
-
if (id?.startsWith(`for-${
|
|
152
|
-
node.id = id.replace(
|
|
116
|
+
if (id?.startsWith(`for-${name}`)) {
|
|
117
|
+
node.id = id.replace(name, iname);
|
|
153
118
|
}
|
|
154
119
|
if (node.nextElementSibling?.htmlFor == id) {
|
|
155
120
|
node.nextElementSibling.htmlFor = node.id;
|
|
156
121
|
}
|
|
157
|
-
node.name
|
|
122
|
+
node.setAttribute('name', iname);
|
|
158
123
|
}
|
|
159
124
|
}
|
|
125
|
+
|
|
160
126
|
const conditionalFieldsets = tpl.querySelectorAll('[is="element-fieldset"]');
|
|
161
127
|
for (const node of conditionalFieldsets) {
|
|
162
|
-
const name = this.#incrementkey('[
|
|
128
|
+
const name = this.#incrementkey('[field.$i]', node.dataset.name);
|
|
163
129
|
if (name != null) {
|
|
164
130
|
node.dataset.name = name;
|
|
165
131
|
}
|
|
166
132
|
}
|
|
167
133
|
|
|
168
134
|
const subtpl = inputs.map(node => node.closest('.fields') ?? node).ancestor();
|
|
169
|
-
if (!subtpl) {
|
|
170
|
-
console.warn("fieldset-list should contain input[name]", this);
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
135
|
subtpl.appendChild(
|
|
174
|
-
subtpl.ownerDocument.createTextNode(
|
|
136
|
+
subtpl.ownerDocument.createTextNode(
|
|
137
|
+
`[$fields|at:${this.dataset.at || '*'}|repeat:field|const:]`
|
|
138
|
+
)
|
|
175
139
|
);
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
{
|
|
184
|
-
const hidden = tpl.ownerDocument.createElement('input');
|
|
185
|
-
hidden.type = "hidden";
|
|
186
|
-
hidden.name = this.#prefix.join('.');
|
|
187
|
-
tpl.appendChild(hidden);
|
|
188
|
-
}
|
|
140
|
+
const min = Number(this.dataset.min) || 0;
|
|
141
|
+
const max = Number(this.dataset.max) || Infinity;
|
|
142
|
+
let list = this.#list;
|
|
143
|
+
const placeholder = list.length == 0 && min == 0;
|
|
144
|
+
if (list.length == 0) {
|
|
145
|
+
list = [{...this.#model, $i: min == 0 ? -1 : 0}];
|
|
189
146
|
}
|
|
190
|
-
tpl = tpl.fuse({
|
|
147
|
+
tpl = tpl.fuse({
|
|
148
|
+
$fields: list,
|
|
149
|
+
$pathname: Page.pathname,
|
|
150
|
+
$query: Page.query
|
|
151
|
+
}, {
|
|
152
|
+
$hooks: {
|
|
153
|
+
before: {
|
|
154
|
+
get(ctx, val, args) {
|
|
155
|
+
const path = args[0];
|
|
156
|
+
if (path[0] == "field") {
|
|
157
|
+
args[0] = [path[0], path.slice(1).join('.')];
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
});
|
|
191
163
|
|
|
192
164
|
const view = this.ownView;
|
|
193
165
|
view.textContent = '';
|
|
194
166
|
view.appendChild(tpl);
|
|
195
167
|
|
|
168
|
+
if (placeholder) {
|
|
169
|
+
for (const node of view.querySelectorAll(`[name^="${this.#prefixStr}"]`)) {
|
|
170
|
+
node.disabled = true;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
196
174
|
view.querySelectorAll(this.#selector('up')).forEach((node, i) => {
|
|
197
175
|
node.disabled = i == 0;
|
|
198
176
|
});
|
|
199
177
|
view.querySelectorAll(this.#selector('down')).forEach((node, i, arr) => {
|
|
200
178
|
node.disabled = i == arr.length - 1;
|
|
201
179
|
});
|
|
180
|
+
view.querySelectorAll(this.#selector('del')).forEach((node) => {
|
|
181
|
+
node.disabled = this.#list.length <= min;
|
|
182
|
+
});
|
|
183
|
+
view.querySelectorAll(this.#selector('add')).forEach((node) => {
|
|
184
|
+
node.disabled = this.#list.length >= max;
|
|
185
|
+
});
|
|
202
186
|
}
|
|
203
187
|
|
|
204
188
|
#parts(key) {
|
|
@@ -208,14 +192,15 @@ class HTMLElementFieldsetList extends Page.Element {
|
|
|
208
192
|
#listFromValues(values) {
|
|
209
193
|
const list = [];
|
|
210
194
|
for (const [key, val] of Object.entries(values)) {
|
|
211
|
-
|
|
212
|
-
|
|
195
|
+
const parts = this.#prefixed(key);
|
|
196
|
+
if (!parts) continue;
|
|
213
197
|
const index = Number(parts.shift());
|
|
214
198
|
if (!Number.isInteger(index)) continue;
|
|
215
199
|
delete values[key];
|
|
216
200
|
let obj = list[index];
|
|
217
201
|
if (!obj) list[index] = obj = {};
|
|
218
202
|
obj[parts.join('.')] = val;
|
|
203
|
+
obj.$i = index;
|
|
219
204
|
}
|
|
220
205
|
return list;
|
|
221
206
|
}
|
|
@@ -224,6 +209,7 @@ class HTMLElementFieldsetList extends Page.Element {
|
|
|
224
209
|
for (let i = 0; i < list.length; i++) {
|
|
225
210
|
const obj = list[i] ?? {};
|
|
226
211
|
for (const [key, val] of Object.entries(obj)) {
|
|
212
|
+
if (key == "$i") continue;
|
|
227
213
|
const parts = this.#prefix.slice();
|
|
228
214
|
parts.push(i);
|
|
229
215
|
parts.push(...this.#parts(key));
|
|
@@ -232,33 +218,32 @@ class HTMLElementFieldsetList extends Page.Element {
|
|
|
232
218
|
}
|
|
233
219
|
}
|
|
234
220
|
|
|
221
|
+
#findIndex(btn) {
|
|
222
|
+
let node = btn;
|
|
223
|
+
const sel = `[name^="${this.#prefixStr}"]`;
|
|
224
|
+
while ((node = node.parentNode)) {
|
|
225
|
+
const input = Array.from(node.querySelectorAll(sel)).pop();
|
|
226
|
+
if (!input) continue;
|
|
227
|
+
const { index } = this.#parseName(input.name);
|
|
228
|
+
if (index >= 0 && index < this.#list.length) return index;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
235
232
|
handleClick(e, state) {
|
|
236
233
|
if (state.scope.$write) return;
|
|
237
234
|
const btn = e.target.closest('button');
|
|
238
235
|
if (!btn) return;
|
|
239
236
|
const action = btn.value;
|
|
240
237
|
if (["add", "del", "up", "down"].includes(action) == false) return;
|
|
241
|
-
|
|
242
|
-
const form = this.closest('form');
|
|
243
|
-
const values = form.read(true);
|
|
244
|
-
const list = this.#listFromValues(values);
|
|
245
|
-
|
|
246
|
-
if (!this.#walk) this.#walk = new WalkIndex(this, node => {
|
|
247
|
-
const { index } = this.#parseName(node.name);
|
|
248
|
-
if (index >= 0 && index < list.length) return index;
|
|
249
|
-
else return null;
|
|
250
|
-
});
|
|
238
|
+
const list = this.#listFromValues(this.closest('form').read(true));
|
|
251
239
|
let index;
|
|
252
240
|
|
|
253
|
-
const fileInputs = this.querySelectorAll('[name][type="file"]')
|
|
254
|
-
.map(n => n.cloneNode(true));
|
|
255
|
-
|
|
256
241
|
switch (action) {
|
|
257
242
|
case "add":
|
|
258
|
-
list.splice((this.#
|
|
243
|
+
list.splice((this.#findIndex(btn) ?? 0), 0, { ...this.#model });
|
|
259
244
|
break;
|
|
260
245
|
case "del":
|
|
261
|
-
list.splice(this.#
|
|
246
|
+
list.splice(this.#findIndex(btn) ?? 0, 1);
|
|
262
247
|
break;
|
|
263
248
|
case "up":
|
|
264
249
|
index = this.querySelectorAll(this.#selector('up')).indexOf(btn);
|
|
@@ -273,8 +258,22 @@ class HTMLElementFieldsetList extends Page.Element {
|
|
|
273
258
|
}
|
|
274
259
|
break;
|
|
275
260
|
}
|
|
276
|
-
this.#
|
|
277
|
-
|
|
261
|
+
this.#list = list;
|
|
262
|
+
this.#refresh();
|
|
263
|
+
state.dispatch(this, 'change');
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
#refresh() {
|
|
267
|
+
const form = this.closest('form');
|
|
268
|
+
const values = form.read(true);
|
|
269
|
+
for (const key of Object.keys(values)) {
|
|
270
|
+
if (this.#prefixed(key)) delete values[key];
|
|
271
|
+
}
|
|
272
|
+
const fileInputs = this.querySelectorAll('[name][type="file"]')
|
|
273
|
+
.map(n => n.cloneNode(true));
|
|
274
|
+
this.#listToValues(values, this.#list);
|
|
275
|
+
form.fill(values);
|
|
276
|
+
|
|
278
277
|
const liveFileInputs = this.querySelectorAll('[name][type="file"]');
|
|
279
278
|
for (const node of fileInputs) {
|
|
280
279
|
const { value } = node;
|
|
@@ -286,14 +285,13 @@ class HTMLElementFieldsetList extends Page.Element {
|
|
|
286
285
|
live.replaceWith(node);
|
|
287
286
|
}
|
|
288
287
|
}
|
|
289
|
-
state.dispatch(this, 'change');
|
|
290
288
|
}
|
|
291
289
|
|
|
292
290
|
#parseName(name) {
|
|
293
|
-
|
|
291
|
+
const parts = this.#prefixed(name);
|
|
292
|
+
if (!parts) {
|
|
294
293
|
return { index: -1 };
|
|
295
294
|
}
|
|
296
|
-
const parts = this.#parts(name).slice(this.#prefix.length);
|
|
297
295
|
const index = Number(parts.shift());
|
|
298
296
|
if (!Number.isInteger(index)) return { index: -1 };
|
|
299
297
|
return { index, sub: parts.join('.') };
|
|
@@ -308,11 +306,11 @@ class HTMLElementFieldsetList extends Page.Element {
|
|
|
308
306
|
return this.children.find(node => node.matches('.view'));
|
|
309
307
|
}
|
|
310
308
|
get prefix() {
|
|
311
|
-
if (this.#prefix == null) {
|
|
312
|
-
this.#prepare();
|
|
313
|
-
}
|
|
314
309
|
return this.#prefix;
|
|
315
310
|
}
|
|
311
|
+
get #prefixStr() {
|
|
312
|
+
return this.#prefix.length ? this.#prefix.join('.') + '.' : '';
|
|
313
|
+
}
|
|
316
314
|
}
|
|
317
315
|
|
|
318
316
|
Page.define('element-fieldset-list', HTMLElementFieldsetList);
|
package/ui/fieldset.js
CHANGED
|
@@ -4,8 +4,8 @@ class HTMLElementFieldSet extends Page.create(HTMLFieldSetElement) {
|
|
|
4
4
|
dataValue: null
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
fill(query
|
|
8
|
-
if (
|
|
7
|
+
fill(query) {
|
|
8
|
+
if (this.isContentEditable || !this.options?.name || !this.form) return;
|
|
9
9
|
if (!query) query = this.form.read(true);
|
|
10
10
|
const val = query[this.options.name];
|
|
11
11
|
const disabled = this.disabled = this.hidden = val != this.options.value;
|
|
@@ -16,12 +16,12 @@ class HTMLElementFieldSet extends Page.create(HTMLFieldSetElement) {
|
|
|
16
16
|
|
|
17
17
|
patch(state) {
|
|
18
18
|
// before/after form#fill
|
|
19
|
-
this.fill(null
|
|
20
|
-
state.finish(() => this.fill(null
|
|
19
|
+
this.fill(null);
|
|
20
|
+
state.finish(() => this.fill(null));
|
|
21
21
|
}
|
|
22
22
|
handleAllChange(e, state) {
|
|
23
23
|
if (this.form?.contains(e.target)) {
|
|
24
|
-
this.fill(null
|
|
24
|
+
this.fill(null);
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
}
|
package/ui/form.css
CHANGED
|
@@ -15,8 +15,11 @@ label[for] {
|
|
|
15
15
|
user-select: none;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
element-select {
|
|
19
|
-
z-index:1;
|
|
18
|
+
element-select.active {
|
|
19
|
+
z-index:1;
|
|
20
|
+
}
|
|
21
|
+
element-select.active.ui.dropdown .menu {
|
|
22
|
+
display:block;
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
.inline.fields element-select {
|
package/ui/form.js
CHANGED
|
@@ -122,7 +122,7 @@ class HTMLElementForm extends Page.create(HTMLFormElement) {
|
|
|
122
122
|
}
|
|
123
123
|
this.restore(state.scope);
|
|
124
124
|
} else {
|
|
125
|
-
for (const name of this.fill(state.query
|
|
125
|
+
for (const name of this.fill(state.query)) {
|
|
126
126
|
state.vars[name] = true;
|
|
127
127
|
}
|
|
128
128
|
}
|
|
@@ -224,11 +224,11 @@ class HTMLElementForm extends Page.create(HTMLFormElement) {
|
|
|
224
224
|
}
|
|
225
225
|
return query;
|
|
226
226
|
}
|
|
227
|
-
fill(query
|
|
227
|
+
fill(query) {
|
|
228
228
|
// fieldset-list are not custom inputs yet
|
|
229
229
|
const vars = [];
|
|
230
230
|
for (const node of this.querySelectorAll("element-fieldset-list")) {
|
|
231
|
-
|
|
231
|
+
node?.fill(query);
|
|
232
232
|
}
|
|
233
233
|
|
|
234
234
|
for (const elem of this.elements) {
|
|
@@ -242,8 +242,11 @@ class HTMLElementForm extends Page.create(HTMLFormElement) {
|
|
|
242
242
|
elem.fill?.(val);
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
|
+
for (const node of this.querySelectorAll("element-select")) {
|
|
246
|
+
node.fill?.(query);
|
|
247
|
+
}
|
|
245
248
|
for (const node of this.querySelectorAll('fieldset[is="element-fieldset"]')) {
|
|
246
|
-
node.fill?.(query
|
|
249
|
+
node.fill?.(query);
|
|
247
250
|
}
|
|
248
251
|
return vars;
|
|
249
252
|
}
|
|
@@ -253,17 +256,17 @@ class HTMLElementForm extends Page.create(HTMLFormElement) {
|
|
|
253
256
|
node.save();
|
|
254
257
|
}
|
|
255
258
|
for (const node of this.elements) {
|
|
256
|
-
|
|
259
|
+
node.save?.();
|
|
257
260
|
}
|
|
258
261
|
}
|
|
259
262
|
reset() {
|
|
260
263
|
this.classList.remove('unsaved');
|
|
264
|
+
for (const node of this.elements) {
|
|
265
|
+
node.reset?.();
|
|
266
|
+
}
|
|
261
267
|
for (const node of this.querySelectorAll("element-fieldset-list")) {
|
|
262
268
|
node.reset();
|
|
263
269
|
}
|
|
264
|
-
for (const node of this.elements) {
|
|
265
|
-
if (node.reset) node.reset();
|
|
266
|
-
}
|
|
267
270
|
}
|
|
268
271
|
backup() {
|
|
269
272
|
if (!this.action) return;
|
|
@@ -289,6 +292,7 @@ class HTMLElementForm extends Page.create(HTMLFormElement) {
|
|
|
289
292
|
window.sessionStorage.removeItem(this.action);
|
|
290
293
|
}
|
|
291
294
|
handleReset(e, state) {
|
|
295
|
+
e.preventDefault();
|
|
292
296
|
this.reset();
|
|
293
297
|
}
|
|
294
298
|
handleSubmit(e, state) {
|
|
@@ -422,18 +426,22 @@ HTMLFormElement.prototype.disable = function () {
|
|
|
422
426
|
}
|
|
423
427
|
};
|
|
424
428
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
429
|
HTMLSelectElement.prototype.fill = function (val) {
|
|
429
430
|
if (!Array.isArray(val)) val = [val];
|
|
430
431
|
for (let i = 0; i < this.options.length; i++) {
|
|
431
432
|
const opt = this.options[i];
|
|
432
|
-
opt.selected = val.
|
|
433
|
+
opt.selected = val.includes(opt.value);
|
|
433
434
|
}
|
|
434
435
|
};
|
|
435
436
|
HTMLSelectElement.prototype.reset = function () {
|
|
436
|
-
for (let i = 0; i < this.options.length; i++)
|
|
437
|
+
for (let i = 0; i < this.options.length; i++) {
|
|
438
|
+
this.options[i].selected = this.options[i].defaultSelected;
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
HTMLSelectElement.prototype.save = function () {
|
|
442
|
+
for (let i = 0; i < this.options.length; i++) {
|
|
443
|
+
this.options[i].defaultSelected = this.options[i].selected;
|
|
444
|
+
}
|
|
437
445
|
};
|
|
438
446
|
|
|
439
447
|
HTMLButtonElement.prototype.fill = HTMLInputElement.prototype.fill = function (val) {
|
|
@@ -465,7 +473,7 @@ HTMLButtonElement.prototype.fill = HTMLInputElement.prototype.fill = function (v
|
|
|
465
473
|
|
|
466
474
|
HTMLInputElement.prototype.reset = function () {
|
|
467
475
|
if (this.type == "radio" || this.type == "checkbox") {
|
|
468
|
-
this.fill(this.defaultChecked);
|
|
476
|
+
this.fill(this.defaultChecked ? this.value : '');
|
|
469
477
|
} else {
|
|
470
478
|
this.fill(this.defaultValue);
|
|
471
479
|
}
|
package/ui/image.js
CHANGED
|
@@ -72,22 +72,6 @@ const HTMLElementImageConstructor = Superclass => class extends Superclass {
|
|
|
72
72
|
return img;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
fix(img) {
|
|
76
|
-
if (!window.objectFitImages.supportsObjectFit) {
|
|
77
|
-
let style = "";
|
|
78
|
-
if (this.fit) {
|
|
79
|
-
style += `object-fit: ${this.fit};`;
|
|
80
|
-
}
|
|
81
|
-
if (this.position) {
|
|
82
|
-
const pos = this.position.replace(/(h|v)center/g, 'center');
|
|
83
|
-
style += `object-position: ${pos};`;
|
|
84
|
-
}
|
|
85
|
-
if (style.length) {
|
|
86
|
-
img.style.fontFamily = `'${style}'`;
|
|
87
|
-
window.objectFitImages(img);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
75
|
patch(state) {
|
|
92
76
|
this.classList.remove('loading');
|
|
93
77
|
if (this.currentSrc != this.options.src) {
|
|
@@ -171,7 +155,6 @@ const HTMLElementImageConstructor = Superclass => class extends Superclass {
|
|
|
171
155
|
captureLoad() {
|
|
172
156
|
this.#defer.resolve();
|
|
173
157
|
this.classList.remove('loading');
|
|
174
|
-
this.fix(this.image);
|
|
175
158
|
}
|
|
176
159
|
captureError() {
|
|
177
160
|
this.#defer.reject();
|
package/ui/input-file.css
CHANGED
|
@@ -29,12 +29,7 @@
|
|
|
29
29
|
.form .field.error > input[type="file"][value]::after {
|
|
30
30
|
color:inherit;
|
|
31
31
|
}
|
|
32
|
-
|
|
33
|
-
.form .field > input[type="file"]:not([value])::after {
|
|
34
|
-
content:attr(placeholder);
|
|
35
|
-
color: rgba(0 0 0 / 50%);
|
|
36
|
-
float: left;
|
|
37
|
-
}
|
|
32
|
+
|
|
38
33
|
input[type="file"]::file-selector-button {
|
|
39
34
|
display:block;
|
|
40
35
|
position:absolute;
|
package/ui/select.css
CHANGED
|
@@ -5,3 +5,18 @@ element-select.ui.multiple.dropdown > .label {
|
|
|
5
5
|
vertical-align: baseline;
|
|
6
6
|
line-height: inherit;
|
|
7
7
|
}
|
|
8
|
+
|
|
9
|
+
[contenteditable] .ui.dropdown[block-focused] > .menu {
|
|
10
|
+
overflow: visible;
|
|
11
|
+
width: auto;
|
|
12
|
+
height: auto;
|
|
13
|
+
top: 100% !important;
|
|
14
|
+
opacity: 1;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
[contenteditable] .field[block-focused] > .ui.dropdown {
|
|
18
|
+
z-index:1;
|
|
19
|
+
}
|
|
20
|
+
[contenteditable] .field[block-focused] .dropdown > .menu {
|
|
21
|
+
display: block !important;
|
|
22
|
+
}
|