@pageboard/html 0.14.9 → 0.14.11
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 -48
- 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
|
@@ -19,40 +19,6 @@ class HTMLElementForm extends Page.create(HTMLFormElement) {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
static patch(state) {
|
|
22
|
-
state.scope.$filters.form = (ctx, val, action, name) => {
|
|
23
|
-
const form = name
|
|
24
|
-
? document.querySelector(`form[name="${name}"]`)
|
|
25
|
-
: ctx.dest.node.closest('form');
|
|
26
|
-
if (!form) {
|
|
27
|
-
// eslint-disable-next-line no-console
|
|
28
|
-
console.warn("No parent form found");
|
|
29
|
-
return val;
|
|
30
|
-
}
|
|
31
|
-
if (action == "toggle") {
|
|
32
|
-
action = val ? "enable" : "disable";
|
|
33
|
-
}
|
|
34
|
-
const isQuery = ctx.expr.path[0] == "$query" && ctx.expr.path.length == 1;
|
|
35
|
-
|
|
36
|
-
state.finish(() => {
|
|
37
|
-
if (action == "enable") {
|
|
38
|
-
form.enable?.();
|
|
39
|
-
} else if (action == "disable") {
|
|
40
|
-
form.disable?.();
|
|
41
|
-
} else if (action == "fill") {
|
|
42
|
-
if (val == null) {
|
|
43
|
-
form.reset?.();
|
|
44
|
-
} else if (typeof val == "object") {
|
|
45
|
-
const vars = form.fill?.(this.linearizeValues(val), state.scope) ?? [];
|
|
46
|
-
if (isQuery) {
|
|
47
|
-
for (const name of vars) state.vars[name] = true;
|
|
48
|
-
}
|
|
49
|
-
form.save?.();
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
return val;
|
|
55
|
-
};
|
|
56
22
|
state.finish(() => {
|
|
57
23
|
let index = 0;
|
|
58
24
|
for (const node of document.querySelectorAll('label[for]')) {
|
|
@@ -122,7 +88,7 @@ class HTMLElementForm extends Page.create(HTMLFormElement) {
|
|
|
122
88
|
}
|
|
123
89
|
this.restore(state.scope);
|
|
124
90
|
} else {
|
|
125
|
-
for (const name of this.fill(state.query
|
|
91
|
+
for (const name of this.fill(state.query)) {
|
|
126
92
|
state.vars[name] = true;
|
|
127
93
|
}
|
|
128
94
|
}
|
|
@@ -224,11 +190,11 @@ class HTMLElementForm extends Page.create(HTMLFormElement) {
|
|
|
224
190
|
}
|
|
225
191
|
return query;
|
|
226
192
|
}
|
|
227
|
-
fill(query
|
|
193
|
+
fill(query) {
|
|
228
194
|
// fieldset-list are not custom inputs yet
|
|
229
195
|
const vars = [];
|
|
230
196
|
for (const node of this.querySelectorAll("element-fieldset-list")) {
|
|
231
|
-
|
|
197
|
+
node?.fill(query);
|
|
232
198
|
}
|
|
233
199
|
|
|
234
200
|
for (const elem of this.elements) {
|
|
@@ -242,8 +208,11 @@ class HTMLElementForm extends Page.create(HTMLFormElement) {
|
|
|
242
208
|
elem.fill?.(val);
|
|
243
209
|
}
|
|
244
210
|
}
|
|
211
|
+
for (const node of this.querySelectorAll("element-select")) {
|
|
212
|
+
node.fill?.(query);
|
|
213
|
+
}
|
|
245
214
|
for (const node of this.querySelectorAll('fieldset[is="element-fieldset"]')) {
|
|
246
|
-
node.fill?.(query
|
|
215
|
+
node.fill?.(query);
|
|
247
216
|
}
|
|
248
217
|
return vars;
|
|
249
218
|
}
|
|
@@ -253,17 +222,17 @@ class HTMLElementForm extends Page.create(HTMLFormElement) {
|
|
|
253
222
|
node.save();
|
|
254
223
|
}
|
|
255
224
|
for (const node of this.elements) {
|
|
256
|
-
|
|
225
|
+
node.save?.();
|
|
257
226
|
}
|
|
258
227
|
}
|
|
259
228
|
reset() {
|
|
260
229
|
this.classList.remove('unsaved');
|
|
230
|
+
for (const node of this.elements) {
|
|
231
|
+
node.reset?.();
|
|
232
|
+
}
|
|
261
233
|
for (const node of this.querySelectorAll("element-fieldset-list")) {
|
|
262
234
|
node.reset();
|
|
263
235
|
}
|
|
264
|
-
for (const node of this.elements) {
|
|
265
|
-
if (node.reset) node.reset();
|
|
266
|
-
}
|
|
267
236
|
}
|
|
268
237
|
backup() {
|
|
269
238
|
if (!this.action) return;
|
|
@@ -289,6 +258,7 @@ class HTMLElementForm extends Page.create(HTMLFormElement) {
|
|
|
289
258
|
window.sessionStorage.removeItem(this.action);
|
|
290
259
|
}
|
|
291
260
|
handleReset(e, state) {
|
|
261
|
+
e.preventDefault();
|
|
292
262
|
this.reset();
|
|
293
263
|
}
|
|
294
264
|
handleSubmit(e, state) {
|
|
@@ -422,18 +392,22 @@ HTMLFormElement.prototype.disable = function () {
|
|
|
422
392
|
}
|
|
423
393
|
};
|
|
424
394
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
395
|
HTMLSelectElement.prototype.fill = function (val) {
|
|
429
396
|
if (!Array.isArray(val)) val = [val];
|
|
430
397
|
for (let i = 0; i < this.options.length; i++) {
|
|
431
398
|
const opt = this.options[i];
|
|
432
|
-
opt.selected = val.
|
|
399
|
+
opt.selected = val.includes(opt.value);
|
|
433
400
|
}
|
|
434
401
|
};
|
|
435
402
|
HTMLSelectElement.prototype.reset = function () {
|
|
436
|
-
for (let i = 0; i < this.options.length; i++)
|
|
403
|
+
for (let i = 0; i < this.options.length; i++) {
|
|
404
|
+
this.options[i].selected = this.options[i].defaultSelected;
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
HTMLSelectElement.prototype.save = function () {
|
|
408
|
+
for (let i = 0; i < this.options.length; i++) {
|
|
409
|
+
this.options[i].defaultSelected = this.options[i].selected;
|
|
410
|
+
}
|
|
437
411
|
};
|
|
438
412
|
|
|
439
413
|
HTMLButtonElement.prototype.fill = HTMLInputElement.prototype.fill = function (val) {
|
|
@@ -465,7 +439,7 @@ HTMLButtonElement.prototype.fill = HTMLInputElement.prototype.fill = function (v
|
|
|
465
439
|
|
|
466
440
|
HTMLInputElement.prototype.reset = function () {
|
|
467
441
|
if (this.type == "radio" || this.type == "checkbox") {
|
|
468
|
-
this.fill(this.defaultChecked);
|
|
442
|
+
this.fill(this.defaultChecked ? this.value : '');
|
|
469
443
|
} else {
|
|
470
444
|
this.fill(this.defaultValue);
|
|
471
445
|
}
|
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
|
+
}
|