@pageboard/html 0.11.28 → 0.12.0
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/accordion.js +0 -1
- package/elements/card.js +5 -5
- package/elements/consent.js +1 -1
- package/elements/embed.js +1 -1
- package/elements/fieldsets.js +2 -2
- package/elements/form.js +2 -2
- package/elements/grid.js +3 -3
- package/elements/heading.js +1 -1
- package/elements/image.js +4 -4
- package/elements/input-date.js +3 -4
- package/elements/inputs.js +12 -12
- package/elements/layout.js +8 -9
- package/elements/link.js +1 -1
- package/elements/menu.js +7 -7
- package/elements/navigation.js +3 -16
- package/elements/pagination.js +1 -1
- package/elements/paragraph.js +2 -2
- package/elements/sitemap.js +8 -8
- package/elements/sticky.js +2 -2
- package/elements/tab.js +1 -1
- package/elements/table.js +10 -10
- package/elements/template.js +1 -1
- package/lib/nouislider.js +28 -0
- package/package.json +1 -1
- package/ui/accordion.js +3 -21
- package/ui/consent.css +3 -3
- package/ui/consent.js +9 -13
- package/ui/embed.js +11 -17
- package/ui/fieldset-list.js +9 -9
- package/ui/fieldset.js +4 -8
- package/ui/form.js +143 -158
- package/ui/heading-helper.js +13 -19
- package/ui/image.js +19 -30
- package/ui/input-date-slot.js +2 -2
- package/ui/input-date.js +2 -7
- package/ui/input-file.js +58 -61
- package/ui/input-range.js +4 -8
- package/ui/layout.js +2 -6
- package/ui/media.js +15 -28
- package/ui/menu.js +23 -27
- package/ui/pagination.js +2 -2
- package/ui/query-tags.js +4 -4
- package/ui/rating.js +2 -2
- package/ui/scroll-link.js +2 -9
- package/ui/select.js +21 -23
- package/ui/sitemap-helper.js +5 -5
- package/ui/sitemap.js +15 -15
- package/ui/sticky.js +2 -6
- package/ui/tab-helper.js +32 -34
- package/ui/tab.js +2 -4
- package/ui/time.js +2 -7
- package/ui/transition.js +21 -21
package/ui/image.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class
|
|
1
|
+
const HTMLElementImageConstructor = Superclass => class extends Superclass {
|
|
2
2
|
static defaults = {
|
|
3
3
|
src: null,
|
|
4
4
|
crop: null
|
|
@@ -7,6 +7,8 @@ class HTMLElementImage extends VirtualHTMLElement {
|
|
|
7
7
|
static defaultWidth = 240;
|
|
8
8
|
static defaultHeight = 180;
|
|
9
9
|
|
|
10
|
+
#defer = new Deferred();
|
|
11
|
+
|
|
10
12
|
static getZoom({ w, h, rw, rh, fit }) {
|
|
11
13
|
let z = 100;
|
|
12
14
|
if (!rw && !rh) return z;
|
|
@@ -31,10 +33,6 @@ class HTMLElementImage extends VirtualHTMLElement {
|
|
|
31
33
|
}
|
|
32
34
|
return { w, h };
|
|
33
35
|
}
|
|
34
|
-
init() {
|
|
35
|
-
this.promise = Promise.resolve();
|
|
36
|
-
this.promise.done = function () { };
|
|
37
|
-
}
|
|
38
36
|
findClass(list) {
|
|
39
37
|
return list.find(name => this.matches(`.${name}`)) || list[0];
|
|
40
38
|
}
|
|
@@ -95,8 +93,8 @@ class HTMLElementImage extends VirtualHTMLElement {
|
|
|
95
93
|
if (this.currentSrc != this.options.src) {
|
|
96
94
|
this.classList.remove('error');
|
|
97
95
|
}
|
|
98
|
-
this.dataset.width = this.constructor.defaultWidth;
|
|
99
|
-
this.dataset.height = this.constructor.defaultHeight;
|
|
96
|
+
this.dataset.width = this.constructor.defaultWidth || "";
|
|
97
|
+
this.dataset.height = this.constructor.defaultHeight || "";
|
|
100
98
|
if (this.options.src) {
|
|
101
99
|
const loc = Page.parse(this.options.src);
|
|
102
100
|
const meta = state.scope.$hrefs?.[loc.pathname];
|
|
@@ -106,8 +104,8 @@ class HTMLElementImage extends VirtualHTMLElement {
|
|
|
106
104
|
}
|
|
107
105
|
}
|
|
108
106
|
const { w, h } = this.dimensions;
|
|
109
|
-
this.image.width = w || this.dataset.width;
|
|
110
|
-
this.image.height = h || this.dataset.height;
|
|
107
|
+
if (w) this.image.width = w || this.dataset.width;
|
|
108
|
+
if (h) this.image.height = h || this.dataset.height;
|
|
111
109
|
if (!this.currentSrc) {
|
|
112
110
|
this.placeholder();
|
|
113
111
|
}
|
|
@@ -156,27 +154,24 @@ class HTMLElementImage extends VirtualHTMLElement {
|
|
|
156
154
|
const rh = rect.height;
|
|
157
155
|
if (rw == 0 && rh == 0) {
|
|
158
156
|
// don't show
|
|
159
|
-
return this
|
|
157
|
+
return this.#defer;
|
|
160
158
|
}
|
|
161
|
-
loc.query.rs = "z-" +
|
|
159
|
+
loc.query.rs = "z-" + this.constructor.getZoom({ w, h, rw, rh, fit });
|
|
162
160
|
}
|
|
163
161
|
const curSrc = loc.toString();
|
|
164
162
|
if (curSrc != this.currentSrc) {
|
|
165
163
|
this.classList.add('loading');
|
|
166
|
-
let done;
|
|
167
|
-
this.promise = new Promise(resolve => done = resolve);
|
|
168
|
-
this.promise.done = done;
|
|
169
164
|
img.setAttribute('src', curSrc);
|
|
170
165
|
}
|
|
171
|
-
return this
|
|
166
|
+
return this.#defer;
|
|
172
167
|
}
|
|
173
168
|
captureLoad() {
|
|
174
|
-
this.
|
|
169
|
+
this.#defer.resolve();
|
|
175
170
|
this.classList.remove('loading');
|
|
176
171
|
this.fix(this.image);
|
|
177
172
|
}
|
|
178
173
|
captureError() {
|
|
179
|
-
this.
|
|
174
|
+
this.#defer.resolve();
|
|
180
175
|
this.classList.remove('loading');
|
|
181
176
|
this.classList.add('error');
|
|
182
177
|
this.placeholder(true);
|
|
@@ -184,21 +179,16 @@ class HTMLElementImage extends VirtualHTMLElement {
|
|
|
184
179
|
placeholder(error) {
|
|
185
180
|
this.image.removeAttribute('src');
|
|
186
181
|
}
|
|
187
|
-
}
|
|
182
|
+
};
|
|
188
183
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
if (this.init) this.init();
|
|
193
|
-
}
|
|
184
|
+
const HTMLElementImage = HTMLElementImageConstructor(Page.Element);
|
|
185
|
+
|
|
186
|
+
class HTMLElementInlineImage extends HTMLElementImageConstructor(Page.create(HTMLImageElement)) {
|
|
194
187
|
static defaults = {
|
|
195
188
|
dataSrc: null,
|
|
196
189
|
dataCrop: null
|
|
197
190
|
};
|
|
198
191
|
|
|
199
|
-
static defaultWidth = 40;
|
|
200
|
-
static defaultHeight = 30;
|
|
201
|
-
|
|
202
192
|
get image() {
|
|
203
193
|
return this;
|
|
204
194
|
}
|
|
@@ -213,12 +203,11 @@ class HTMLElementInlineImage extends HTMLImageElement {
|
|
|
213
203
|
}
|
|
214
204
|
|
|
215
205
|
get currentSrc() {
|
|
216
|
-
const cur =
|
|
206
|
+
const cur = Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, 'currentSrc').get.call(this);
|
|
217
207
|
if (!cur && this.image.src?.startsWith('data:')) return this.src;
|
|
218
208
|
else return cur;
|
|
219
209
|
}
|
|
220
210
|
}
|
|
221
211
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
VirtualHTMLElement.define(`element-img`, HTMLElementInlineImage, 'img');
|
|
212
|
+
Page.define('element-image', HTMLElementImage);
|
|
213
|
+
Page.define(`element-img`, HTMLElementInlineImage, 'img');
|
package/ui/input-date-slot.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class HTMLElementInputDateSlot extends
|
|
1
|
+
class HTMLElementInputDateSlot extends Page.Element {
|
|
2
2
|
handleChange(e, state) {
|
|
3
3
|
this.update(e.target);
|
|
4
4
|
}
|
|
@@ -74,5 +74,5 @@ class HTMLElementInputDateSlot extends VirtualHTMLElement {
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
Page.define('element-input-date-slot', HTMLElementInputDateSlot);
|
|
78
78
|
|
package/ui/input-date.js
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
class HTMLElementInputDate extends HTMLInputElement {
|
|
2
|
-
constructor() {
|
|
3
|
-
super();
|
|
4
|
-
if (this.init) this.init();
|
|
5
|
-
}
|
|
6
|
-
|
|
1
|
+
class HTMLElementInputDate extends Page.create(HTMLInputElement) {
|
|
7
2
|
patch() {
|
|
8
3
|
if (this.type == "date") this.removeAttribute('step');
|
|
9
4
|
}
|
|
@@ -70,4 +65,4 @@ class HTMLElementInputDate extends HTMLInputElement {
|
|
|
70
65
|
}
|
|
71
66
|
}
|
|
72
67
|
|
|
73
|
-
|
|
68
|
+
Page.define('element-input-date', HTMLElementInputDate, 'input');
|
package/ui/input-file.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
class HTMLElementInputFile extends HTMLInputElement {
|
|
1
|
+
class HTMLElementInputFile extends Page.create(HTMLInputElement) {
|
|
2
2
|
#xhr;
|
|
3
|
-
#
|
|
3
|
+
#defer;
|
|
4
4
|
#defaultValue;
|
|
5
5
|
|
|
6
6
|
/* Since input[type=file] does not allow setting "value" property,
|
|
@@ -10,11 +10,6 @@ class HTMLElementInputFile extends HTMLInputElement {
|
|
|
10
10
|
* and filled value attribute.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
constructor() {
|
|
14
|
-
super();
|
|
15
|
-
if (this.init) this.init();
|
|
16
|
-
this.save();
|
|
17
|
-
}
|
|
18
13
|
get defaultValue() {
|
|
19
14
|
return this.#defaultValue;
|
|
20
15
|
}
|
|
@@ -32,6 +27,9 @@ class HTMLElementInputFile extends HTMLInputElement {
|
|
|
32
27
|
super.value = "";
|
|
33
28
|
}
|
|
34
29
|
}
|
|
30
|
+
patch() {
|
|
31
|
+
this.save();
|
|
32
|
+
}
|
|
35
33
|
captureClick(e, state) {
|
|
36
34
|
if (this.value) {
|
|
37
35
|
e.preventDefault();
|
|
@@ -55,7 +53,7 @@ class HTMLElementInputFile extends HTMLInputElement {
|
|
|
55
53
|
}
|
|
56
54
|
|
|
57
55
|
presubmit() {
|
|
58
|
-
if (this.#
|
|
56
|
+
if (this.#defer) return this.#defer;
|
|
59
57
|
if (!this.files.length) return Promise.resolve();
|
|
60
58
|
const field = this.closest('.field');
|
|
61
59
|
field.classList.remove('success', 'error');
|
|
@@ -65,68 +63,67 @@ class HTMLElementInputFile extends HTMLInputElement {
|
|
|
65
63
|
}
|
|
66
64
|
track(0);
|
|
67
65
|
field.classList.add('loading');
|
|
68
|
-
|
|
69
|
-
const fail = (err) => {
|
|
70
|
-
field.classList.add('error');
|
|
71
|
-
field.classList.remove('loading');
|
|
72
|
-
this.#xhr = null;
|
|
73
|
-
reject(err);
|
|
74
|
-
this.#promise = null;
|
|
75
|
-
};
|
|
76
|
-
const pass = (obj) => {
|
|
77
|
-
if (!obj.items || obj.items.length == 0) return fail(new Error("File rejected"));
|
|
78
|
-
const val = obj.items[0];
|
|
79
|
-
this.value = val;
|
|
80
|
-
field.classList.add('success');
|
|
81
|
-
field.classList.remove('loading');
|
|
82
|
-
this.#xhr = null;
|
|
83
|
-
resolve();
|
|
84
|
-
this.#promise = null;
|
|
85
|
-
};
|
|
86
|
-
if (this.files.length == 0) return resolve(); // or reject ?
|
|
66
|
+
this.#defer = new Deferred();
|
|
87
67
|
|
|
88
|
-
|
|
89
|
-
|
|
68
|
+
const fail = (err) => {
|
|
69
|
+
field.classList.add('error');
|
|
70
|
+
field.classList.remove('loading');
|
|
71
|
+
this.#xhr = null;
|
|
72
|
+
this.#defer.reject(err);
|
|
73
|
+
this.#defer = null;
|
|
74
|
+
};
|
|
75
|
+
const pass = (obj) => {
|
|
76
|
+
if (!obj.items || obj.items.length == 0) return fail(new Error("File rejected"));
|
|
77
|
+
const val = obj.items[0];
|
|
78
|
+
this.value = val;
|
|
79
|
+
field.classList.add('success');
|
|
80
|
+
field.classList.remove('loading');
|
|
81
|
+
this.#xhr = null;
|
|
82
|
+
this.#defer.resolve();
|
|
83
|
+
this.#defer = null;
|
|
84
|
+
};
|
|
85
|
+
if (this.files.length == 0) return this.#defer.resolve(); // or reject ?
|
|
90
86
|
|
|
91
|
-
|
|
87
|
+
const fd = new FormData();
|
|
88
|
+
fd.append("files", this.files[0]);
|
|
92
89
|
|
|
93
|
-
|
|
94
|
-
if (e.lengthComputable) {
|
|
95
|
-
let percent = Math.round((e.loaded * 100) / e.total);
|
|
96
|
-
if (percent >= 100) percent = 99; // only load event can reach 100
|
|
97
|
-
track(percent);
|
|
98
|
-
}
|
|
99
|
-
});
|
|
90
|
+
const xhr = new XMLHttpRequest();
|
|
100
91
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
});
|
|
92
|
+
xhr.upload.addEventListener("progress", (e) => {
|
|
93
|
+
if (e.lengthComputable) {
|
|
94
|
+
let percent = Math.round((e.loaded * 100) / e.total);
|
|
95
|
+
if (percent >= 100) percent = 99; // only load event can reach 100
|
|
96
|
+
track(percent);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
109
99
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const msg = xhr.statusText || "Connection error";
|
|
113
|
-
const err = new Error(msg);
|
|
114
|
-
err.statusCode = xhr.status;
|
|
115
|
-
fail(err);
|
|
116
|
-
});
|
|
100
|
+
xhr.addEventListener('load', () => {
|
|
101
|
+
track(100);
|
|
117
102
|
try {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
this.#xhr = xhr;
|
|
122
|
-
} catch (err) {
|
|
123
|
-
fail(err);
|
|
103
|
+
pass(JSON.parse(xhr.responseText));
|
|
104
|
+
} catch (ex) {
|
|
105
|
+
fail(ex);
|
|
124
106
|
}
|
|
125
107
|
});
|
|
126
|
-
|
|
127
|
-
|
|
108
|
+
|
|
109
|
+
xhr.addEventListener('error', (e) => {
|
|
110
|
+
if (xhr.status == 0) return fail("Connection error");
|
|
111
|
+
const msg = xhr.statusText || "Connection error";
|
|
112
|
+
const err = new Error(msg);
|
|
113
|
+
err.statusCode = xhr.status;
|
|
114
|
+
fail(err);
|
|
115
|
+
});
|
|
116
|
+
try {
|
|
117
|
+
xhr.open("POST", `/.api/upload/${this.id}`, true);
|
|
118
|
+
xhr.setRequestHeader('Accept', "application/json; q=1.0");
|
|
119
|
+
xhr.send(fd);
|
|
120
|
+
this.#xhr = xhr;
|
|
121
|
+
} catch (err) {
|
|
122
|
+
fail(err);
|
|
123
|
+
}
|
|
124
|
+
return this.#defer;
|
|
128
125
|
}
|
|
129
126
|
}
|
|
130
127
|
|
|
131
|
-
|
|
128
|
+
Page.define('element-input-file', HTMLElementInputFile, 'input');
|
|
132
129
|
|
package/ui/input-range.js
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
class HTMLElementInputRange extends HTMLInputElement {
|
|
2
|
-
constructor() {
|
|
3
|
-
super();
|
|
4
|
-
if (this.init) this.init();
|
|
5
|
-
}
|
|
1
|
+
class HTMLElementInputRange extends Page.create(HTMLInputElement) {
|
|
6
2
|
static parse(x) {
|
|
7
3
|
return (x == null ? '' : x)
|
|
8
4
|
.split('⩽')
|
|
@@ -120,7 +116,7 @@ class HTMLElementInputRange extends HTMLInputElement {
|
|
|
120
116
|
}
|
|
121
117
|
}
|
|
122
118
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
119
|
+
|
|
120
|
+
Page.define('element-input-range', HTMLElementInputRange, 'input');
|
|
121
|
+
|
|
126
122
|
|
package/ui/layout.js
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
class HTMLElementLayout extends HTMLDivElement {
|
|
2
|
-
constructor() {
|
|
3
|
-
super();
|
|
4
|
-
if (this.init) this.init();
|
|
5
|
-
}
|
|
1
|
+
class HTMLElementLayout extends Page.create(HTMLDivElement) {
|
|
6
2
|
static defaults = {
|
|
7
3
|
dataSrc: null,
|
|
8
4
|
dataCrop: null,
|
|
@@ -93,4 +89,4 @@ for (const name of ['crop', 'dimensions']) {
|
|
|
93
89
|
}
|
|
94
90
|
})(window.customElements.get('element-image'));
|
|
95
91
|
|
|
96
|
-
|
|
92
|
+
Page.define(`element-layout`, HTMLElementLayout, 'div');
|
package/ui/media.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
this.promise.done = function() {};
|
|
5
|
-
},
|
|
1
|
+
const HTMLElementMediaConstructor = Superclass => class extends Superclass {
|
|
2
|
+
#defer = new Deferred();
|
|
3
|
+
|
|
6
4
|
patch(state) {
|
|
7
5
|
this.classList.remove('error', 'loading');
|
|
8
6
|
const loc = Page.parse(this.options.src);
|
|
@@ -10,55 +8,44 @@ const MixinMedia = {
|
|
|
10
8
|
if (!meta || !meta.width || !meta.height) return;
|
|
11
9
|
this.width = meta.width;
|
|
12
10
|
this.height = meta.height;
|
|
13
|
-
}
|
|
11
|
+
}
|
|
14
12
|
reveal(state) {
|
|
15
13
|
const curSrc = this.options.src;
|
|
16
14
|
if (curSrc != this.currentSrc) {
|
|
17
15
|
try {
|
|
18
16
|
this.currentSrc = curSrc;
|
|
19
|
-
} catch(e) {
|
|
17
|
+
} catch (e) {
|
|
20
18
|
// pass
|
|
21
19
|
}
|
|
22
20
|
this.setAttribute('src', curSrc);
|
|
23
21
|
}
|
|
24
22
|
if (this.isContentEditable) this.pause();
|
|
25
|
-
return this
|
|
26
|
-
}
|
|
23
|
+
return this.#defer;
|
|
24
|
+
}
|
|
27
25
|
handleClick(e) {
|
|
28
26
|
if (this.isContentEditable) e.preventDefault();
|
|
29
|
-
}
|
|
27
|
+
}
|
|
30
28
|
captureLoad() {
|
|
31
|
-
this.
|
|
29
|
+
this.#defer.resolve();
|
|
32
30
|
this.classList.remove('loading');
|
|
33
|
-
}
|
|
31
|
+
}
|
|
34
32
|
captureError() {
|
|
35
|
-
this.
|
|
33
|
+
this.#defer.resolve();
|
|
36
34
|
this.classList.remove('loading');
|
|
37
35
|
this.classList.add('error');
|
|
38
36
|
}
|
|
39
37
|
};
|
|
40
38
|
|
|
41
|
-
class HTMLElementVideo extends HTMLVideoElement {
|
|
42
|
-
constructor() {
|
|
43
|
-
super();
|
|
44
|
-
if (this.init) this.init();
|
|
45
|
-
}
|
|
39
|
+
class HTMLElementVideo extends HTMLElementMediaConstructor(Page.create(HTMLVideoElement)) {
|
|
46
40
|
static defaults = {
|
|
47
41
|
dataSrc: null
|
|
48
42
|
};
|
|
49
43
|
}
|
|
50
|
-
|
|
44
|
+
Page.define('element-video', HTMLElementVideo, 'video');
|
|
51
45
|
|
|
52
|
-
class HTMLElementAudio extends HTMLAudioElement {
|
|
53
|
-
constructor() {
|
|
54
|
-
super();
|
|
55
|
-
if (this.init) this.init();
|
|
56
|
-
}
|
|
46
|
+
class HTMLElementAudio extends HTMLElementMediaConstructor(Page.create(HTMLAudioElement)) {
|
|
57
47
|
static defaults = {
|
|
58
48
|
dataSrc: null
|
|
59
49
|
};
|
|
60
50
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
VirtualHTMLElement.define('element-video', HTMLElementVideo, 'video');
|
|
64
|
-
VirtualHTMLElement.define('element-audio', HTMLElementAudio, 'audio');
|
|
51
|
+
Page.define('element-audio', HTMLElementAudio, 'audio');
|
package/ui/menu.js
CHANGED
|
@@ -1,30 +1,28 @@
|
|
|
1
|
-
Page.
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
if (
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
loc.
|
|
1
|
+
class HTMLElementMenu extends Page.Element {
|
|
2
|
+
static patch(state) {
|
|
3
|
+
function isSameOrParent(loc, ref, isItem) {
|
|
4
|
+
if (!ref.sameDomain(loc)) {
|
|
5
|
+
return false;
|
|
6
|
+
} else if (ref.samePathname(loc)) {
|
|
7
|
+
if (!isItem && !loc.search || ref.sameQuery(loc)) return true;
|
|
8
|
+
} else {
|
|
9
|
+
return ref.pathname.startsWith(loc.pathname + '/');
|
|
10
10
|
}
|
|
11
|
-
if (state.sameQuery(loc)) return true;
|
|
12
|
-
} else {
|
|
13
|
-
return state.pathname.startsWith(loc.pathname + '/');
|
|
14
11
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if (!loc) continue;
|
|
20
|
-
if (isSameOrParent(Page.parse(loc), state, item.matches('.item'))) {
|
|
21
|
-
item.classList.add('active');
|
|
12
|
+
state.finish(() => {
|
|
13
|
+
const ref = state.parse(state);
|
|
14
|
+
for (const name of state.ivars) {
|
|
15
|
+
delete ref.query[name];
|
|
22
16
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
17
|
+
for (const item of document.querySelectorAll('[block-type="menu"] [href]')) {
|
|
18
|
+
const loc = item.getAttribute('href');
|
|
19
|
+
if (!loc) continue;
|
|
20
|
+
if (isSameOrParent(state.parse(loc), ref, item.matches('.item'))) {
|
|
21
|
+
item.classList.add('active');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
28
26
|
setup(state) {
|
|
29
27
|
if (this.isContentEditable || this.matches('.vertical')) return;
|
|
30
28
|
const menu = this.firstElementChild;
|
|
@@ -86,6 +84,4 @@ class HTMLElementMenu extends VirtualHTMLElement {
|
|
|
86
84
|
}
|
|
87
85
|
}
|
|
88
86
|
|
|
89
|
-
Page.
|
|
90
|
-
VirtualHTMLElement.define('element-menu', HTMLElementMenu);
|
|
91
|
-
});
|
|
87
|
+
Page.define('element-menu', HTMLElementMenu);
|
package/ui/pagination.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class HTMLElementPagination extends HTMLAnchorElement {
|
|
1
|
+
class HTMLElementPagination extends Page.create(HTMLAnchorElement) {
|
|
2
2
|
patch(state) {
|
|
3
3
|
if (this.isContentEditable) return;
|
|
4
4
|
state.finish(() => {
|
|
@@ -47,4 +47,4 @@ class HTMLElementPagination extends HTMLAnchorElement {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
Page.define('element-pagination', HTMLElementPagination, "a");
|
package/ui/query-tags.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class HTMLElementQueryTags extends
|
|
1
|
+
class HTMLElementQueryTags extends Page.Element {
|
|
2
2
|
find(name, value) {
|
|
3
3
|
let nodes;
|
|
4
4
|
const formName = this.getAttribute('for');
|
|
@@ -102,7 +102,7 @@ class HTMLElementQueryTags extends VirtualHTMLElement {
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
|
|
106
|
+
Page.define('element-query-tags', HTMLElementQueryTags);
|
|
107
|
+
|
|
108
108
|
|
package/ui/rating.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class HTMLElementRating extends
|
|
1
|
+
class HTMLElementRating extends Page.Element {
|
|
2
2
|
static defaults = {
|
|
3
3
|
maximum: 4,
|
|
4
4
|
value: (x) => parseFloat(x) || 0,
|
|
@@ -20,5 +20,5 @@ class HTMLElementRating extends VirtualHTMLElement {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Page.define('element-rating', HTMLElementRating);
|
|
24
24
|
|
package/ui/scroll-link.js
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
class HTMLScrollLinkElement extends HTMLAnchorElement {
|
|
2
|
-
constructor() {
|
|
3
|
-
super();
|
|
4
|
-
if (this.init) this.init();
|
|
5
|
-
}
|
|
1
|
+
class HTMLScrollLinkElement extends Page.create(HTMLAnchorElement) {
|
|
6
2
|
static defaults = {
|
|
7
3
|
dataTo: (x) => ["home", "end"].includes(x) ? x : "end"
|
|
8
4
|
};
|
|
@@ -25,7 +21,4 @@ class HTMLScrollLinkElement extends HTMLAnchorElement {
|
|
|
25
21
|
}
|
|
26
22
|
}
|
|
27
23
|
|
|
28
|
-
Page.
|
|
29
|
-
VirtualHTMLElement.define(`element-scroll-link`, HTMLScrollLinkElement, 'a');
|
|
30
|
-
});
|
|
31
|
-
|
|
24
|
+
Page.define(`element-scroll-link`, HTMLScrollLinkElement, 'a');
|
package/ui/select.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class HTMLElementSelect extends
|
|
1
|
+
class HTMLElementSelect extends Page.Element {
|
|
2
2
|
#observer;
|
|
3
3
|
|
|
4
4
|
static defaults = {
|
|
@@ -24,6 +24,7 @@ class HTMLElementSelect extends VirtualHTMLElement {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
handleClick(e, state) {
|
|
27
|
+
if (this.isContentEditable) return;
|
|
27
28
|
const node = e.target;
|
|
28
29
|
const item = node.closest('element-select .item');
|
|
29
30
|
if (item) {
|
|
@@ -55,9 +56,9 @@ class HTMLElementSelect extends VirtualHTMLElement {
|
|
|
55
56
|
handleChange(e, state) {
|
|
56
57
|
const opt = e.target;
|
|
57
58
|
if (opt.selected) {
|
|
58
|
-
this.#selectItem(opt
|
|
59
|
+
this.#selectItem(opt);
|
|
59
60
|
} else {
|
|
60
|
-
this.#deselectItem(opt
|
|
61
|
+
this.#deselectItem(opt);
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
64
|
#toggleMenu(show) {
|
|
@@ -65,8 +66,9 @@ class HTMLElementSelect extends VirtualHTMLElement {
|
|
|
65
66
|
if (show === undefined) show = !style.display;
|
|
66
67
|
style.display = show ? "block" : null;
|
|
67
68
|
}
|
|
68
|
-
#selectItem(
|
|
69
|
+
#selectItem(opt) {
|
|
69
70
|
const select = this.#select;
|
|
71
|
+
const val = opt.getAttribute('value');
|
|
70
72
|
const item = this.#menuOption(val);
|
|
71
73
|
|
|
72
74
|
if (this.options.multiple) {
|
|
@@ -80,11 +82,12 @@ class HTMLElementSelect extends VirtualHTMLElement {
|
|
|
80
82
|
this.#setText(item.innerText.trim());
|
|
81
83
|
}
|
|
82
84
|
|
|
83
|
-
const defaultOption = select.querySelector(`option[value
|
|
85
|
+
const defaultOption = select.querySelector(`option:not([value])`);
|
|
84
86
|
if (defaultOption && val) defaultOption.selected = false;
|
|
85
87
|
}
|
|
86
|
-
#deselectItem(
|
|
87
|
-
|
|
88
|
+
#deselectItem(opt) {
|
|
89
|
+
const val = opt.getAttribute('value');
|
|
90
|
+
if (this.options.multiple && val) {
|
|
88
91
|
const item = this.#child(`.label[data-value="${val}"]`);
|
|
89
92
|
if (item) item.remove();
|
|
90
93
|
}
|
|
@@ -112,9 +115,11 @@ class HTMLElementSelect extends VirtualHTMLElement {
|
|
|
112
115
|
}
|
|
113
116
|
|
|
114
117
|
#menuOption(val) {
|
|
118
|
+
if (val == null) val = "";
|
|
115
119
|
return this.querySelector(`element-select-option[data-value="${val}"]`);
|
|
116
120
|
}
|
|
117
121
|
#selectOption(val) {
|
|
122
|
+
if (val == null) val = "";
|
|
118
123
|
return this.querySelector(`select > option[value="${val}"]`);
|
|
119
124
|
}
|
|
120
125
|
|
|
@@ -124,20 +129,14 @@ class HTMLElementSelect extends VirtualHTMLElement {
|
|
|
124
129
|
this.#observer = null;
|
|
125
130
|
}
|
|
126
131
|
}
|
|
127
|
-
#fillSelect() {
|
|
132
|
+
#fillSelect(state) {
|
|
128
133
|
const select = this.#select;
|
|
129
134
|
if (!select) return;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const val = item.dataset.value;
|
|
133
|
-
select.insertAdjacentHTML(
|
|
134
|
-
'beforeEnd',
|
|
135
|
-
`<option value="${val == null ? '' : val}">${item.innerHTML}</option>`
|
|
136
|
-
);
|
|
137
|
-
});
|
|
135
|
+
select.insertAdjacentHTML('afterBegin', '<option value="[item.dataset.value]">[children|at:*|repeat:item|.innerText]</option>');
|
|
136
|
+
select.fuse(this.#menu, state.scope);
|
|
138
137
|
}
|
|
139
138
|
setup(state) {
|
|
140
|
-
this.#observer = new MutationObserver(mutations => this.#fillSelect());
|
|
139
|
+
this.#observer = new MutationObserver(mutations => this.#fillSelect(state));
|
|
141
140
|
this.#observer.observe(this.#menu, {
|
|
142
141
|
childList: true
|
|
143
142
|
});
|
|
@@ -166,24 +165,23 @@ class HTMLElementSelect extends VirtualHTMLElement {
|
|
|
166
165
|
menu.insertAdjacentHTML('afterBegin', `<element-select-option data-value="" block-type="input_select_option" class="item">-</element-select-option>`);
|
|
167
166
|
}
|
|
168
167
|
}
|
|
169
|
-
this.#fillSelect();
|
|
168
|
+
this.#fillSelect(state);
|
|
170
169
|
}
|
|
171
170
|
|
|
172
171
|
patch(state) {
|
|
173
|
-
if (this.isContentEditable) return;
|
|
172
|
+
if (this.isContentEditable) return;
|
|
174
173
|
if (this.children.length == 1) this.build(state);
|
|
175
174
|
|
|
176
175
|
state.finish(() => {
|
|
177
176
|
// synchronize after form has filled select
|
|
178
177
|
this.#select.children.forEach(opt => {
|
|
179
178
|
if (opt.value) {
|
|
180
|
-
if (opt.selected) this.#selectItem(opt
|
|
181
|
-
else this.#deselectItem(opt
|
|
179
|
+
if (opt.selected) this.#selectItem(opt);
|
|
180
|
+
else this.#deselectItem(opt);
|
|
182
181
|
}
|
|
183
182
|
});
|
|
184
183
|
});
|
|
185
184
|
}
|
|
186
185
|
}
|
|
187
186
|
|
|
188
|
-
|
|
189
|
-
|
|
187
|
+
Page.define('element-select', HTMLElementSelect);
|