@pageboard/html 0.12.2 → 0.12.3

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.12.2",
3
+ "version": "0.12.3",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "repository": {
package/ui/consent.js CHANGED
@@ -13,7 +13,7 @@ class HTMLElementConsent extends Page.create(HTMLFormElement) {
13
13
  return !tacit;
14
14
  }
15
15
  setup(state) {
16
- if (this.isContentEditable) return;
16
+ if (state.scope.$write) return;
17
17
  if (this.options.transient) {
18
18
  const tmpl = this.ownTpl.prerender();
19
19
  if (tmpl.content && tmpl.children.length == 0) {
@@ -30,7 +30,7 @@ class HTMLElementConsent extends Page.create(HTMLFormElement) {
30
30
  }
31
31
  handleSubmit(e, state) {
32
32
  if (e.type == "submit") e.preventDefault();
33
- if (this.isContentEditable) return;
33
+ if (state.scope.$write) return;
34
34
  const fd = window.HTMLElementForm.prototype.read.call(this);
35
35
  const consent = fd.consent;
36
36
  if (consent == null) {
@@ -44,7 +44,7 @@ class HTMLElementConsent extends Page.create(HTMLFormElement) {
44
44
  this.handleSubmit(e, state);
45
45
  }
46
46
  patch(state) {
47
- if (this.isContentEditable) return;
47
+ if (state.scope.$write) return;
48
48
  if (this.options.transient) {
49
49
  this.ownTpl.prerender();
50
50
  }
package/ui/embed.js CHANGED
@@ -9,7 +9,7 @@ class HTMLElementEmbed extends Page.Element {
9
9
  reveal(state) {
10
10
  this.classList.add('waiting');
11
11
  state.consent(this);
12
- return this.#defer;
12
+ // return this.#defer; // do not hang the chain
13
13
  }
14
14
  consent(state) {
15
15
  const consent = state.scope.$consent;
@@ -83,10 +83,10 @@ class HTMLElementFieldsetList extends Page.Element {
83
83
  this.#model = model;
84
84
  }
85
85
 
86
- #prepare() {
86
+ #prepare(scope) {
87
87
  const tpl = this.ownTpl;
88
88
  tpl.prerender();
89
- if (this.isContentEditable) {
89
+ if (scope.$write) {
90
90
  this.#modelize(tpl);
91
91
  return;
92
92
  }
@@ -96,13 +96,13 @@ class HTMLElementFieldsetList extends Page.Element {
96
96
  }
97
97
  }
98
98
 
99
- patch(state) {
100
- this.#prepare();
101
- if (!this.#size) this.#resize(0, state.scope);
99
+ patch({ scope }) {
100
+ this.#prepare(scope);
101
+ if (!this.#size) this.#resize(0, scope);
102
102
  }
103
103
 
104
- setup() {
105
- this.#prepare();
104
+ setup({ scope }) {
105
+ this.#prepare(scope);
106
106
  }
107
107
 
108
108
  #selector(name) {
@@ -110,7 +110,7 @@ class HTMLElementFieldsetList extends Page.Element {
110
110
  }
111
111
 
112
112
  #resize(size, scope) {
113
- if (this.isContentEditable) return;
113
+ if (scope.$write) return;
114
114
  const len = Math.max(Number(this.dataset.size) || 0, size);
115
115
  if (this.#size === len) return;
116
116
  this.#size = len;
@@ -205,7 +205,7 @@ class HTMLElementFieldsetList extends Page.Element {
205
205
  }
206
206
 
207
207
  handleClick(e, state) {
208
- if (this.isContentEditable) return;
208
+ if (state.scope.$write) return;
209
209
  const btn = e.target.closest('button');
210
210
  if (!btn) return;
211
211
  const action = btn.value;
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 (this.isContentEditable || !this.options?.name || !this.form) return;
7
+ fill(query, scope) {
8
+ if (scope.$write || !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,8 +16,8 @@ class HTMLElementFieldSet extends Page.create(HTMLFieldSetElement) {
16
16
 
17
17
  patch(state) {
18
18
  // before/after form#fill
19
- this.fill();
20
- state.finish(() => this.fill());
19
+ this.fill(null, state.scope);
20
+ state.finish(() => this.fill(null, state.scope));
21
21
  }
22
22
  setup() {
23
23
  this.form?.addEventListener('change', this);
@@ -25,9 +25,9 @@ class HTMLElementFieldSet extends Page.create(HTMLFieldSetElement) {
25
25
  close() {
26
26
  this.form?.removeEventListener('change', this);
27
27
  }
28
- handleEvent(e) {
28
+ handleEvent(e, state) {
29
29
  if (e.type == "change") {
30
- this.fill();
30
+ this.fill(null, state.scope);
31
31
  }
32
32
  }
33
33
  }
package/ui/form.js CHANGED
@@ -96,7 +96,7 @@ class HTMLElementForm extends Page.create(HTMLFormElement) {
96
96
  return window.HTMLElementTemplate.prototype.getRedirect.call(this, status, this);
97
97
  }
98
98
  patch(state) {
99
- if (this.isContentEditable) return;
99
+ if (state.scope.$write) return;
100
100
  if (this.method != "get") {
101
101
  // ?submit=<name> for auto-submit
102
102
  const name = state.query.submit;
@@ -220,7 +220,7 @@ class HTMLElementForm extends Page.create(HTMLFormElement) {
220
220
  }
221
221
  }
222
222
  for (const node of this.querySelectorAll('fieldset[is="element-fieldset"]')) {
223
- node.fill(query);
223
+ node.fill(query, scope);
224
224
  }
225
225
  return vars;
226
226
  }
@@ -268,7 +268,7 @@ class HTMLElementForm extends Page.create(HTMLFormElement) {
268
268
  }
269
269
  handleSubmit(e, state) {
270
270
  if (e.type == "submit") e.preventDefault();
271
- if (this.isContentEditable) return;
271
+ if (state.scope.$write) return;
272
272
  this.toggleMessages();
273
273
  if (this.matches('.loading')) return;
274
274
  if (e.type != "submit" && this.querySelector('[type="submit"]')) return;
@@ -299,17 +299,18 @@ class HTMLElementForm extends Page.create(HTMLFormElement) {
299
299
  if (loc.samePathname(state)) {
300
300
  loc.query = { ...state.query, ...loc.query };
301
301
  }
302
- let status = 200;
303
- const p = this.ignoreInputChange
302
+ const nstate = this.ignoreInputChange
304
303
  ? state.replace(loc)
305
304
  : state.push(loc);
306
- return p.catch(err => {
307
- if (err.status != null) status = err.status;
308
- else status = 0;
309
- }).then(() => {
305
+ nstate.catch(state => {
306
+ const status = state.error?.status ?? 0;
310
307
  this.toggleMessages(status);
311
308
  });
312
309
  }
310
+ catch(state) {
311
+ const status = state.error?.status ?? 0;
312
+ this.toggleMessages(status);
313
+ }
313
314
  async postMethod(e, state) {
314
315
  if (e.type != "submit") return;
315
316
  const form = this;
@@ -365,7 +366,7 @@ class HTMLElementForm extends Page.create(HTMLFormElement) {
365
366
  }
366
367
  scope.$vary = vary;
367
368
  }
368
- return state.push(loc, { vary });
369
+ state.push(loc, { vary });
369
370
  }
370
371
  }
371
372
  window.HTMLElementForm = HTMLElementForm;
package/ui/image.js CHANGED
@@ -7,7 +7,7 @@ const HTMLElementImageConstructor = Superclass => class extends Superclass {
7
7
  static defaultWidth = 240;
8
8
  static defaultHeight = 180;
9
9
 
10
- #defer = new Deferred();
10
+ #defer;
11
11
 
12
12
  static getZoom({ w, h, rw, rh, fit }) {
13
13
  let z = 100;
@@ -93,11 +93,17 @@ const HTMLElementImageConstructor = Superclass => class extends Superclass {
93
93
  if (this.currentSrc != this.options.src) {
94
94
  this.classList.remove('error');
95
95
  }
96
- this.dataset.width ??= this.constructor.defaultWidth || "";
97
- this.dataset.height ??= this.constructor.defaultHeight || "";
96
+ const d = this.dataset;
97
+ if (d.width == null || d.height == null) {
98
+ const meta = state.scope.$hrefs?.[this.options.src];
99
+ if (meta?.width) d.width = meta.width;
100
+ if (meta?.height) d.height = meta.height;
101
+ }
102
+ d.width ??= this.constructor.defaultWidth || "";
103
+ d.height ??= this.constructor.defaultHeight || "";
98
104
  const { w, h } = this.dimensions;
99
- if (w) this.image.width = w || this.dataset.width;
100
- if (h) this.image.height = h || this.dataset.height;
105
+ if (w) this.image.width = w || d.width;
106
+ if (h) this.image.height = h || d.height;
101
107
  if (!this.currentSrc) {
102
108
  this.placeholder();
103
109
  }
@@ -115,6 +121,9 @@ const HTMLElementImageConstructor = Superclass => class extends Superclass {
115
121
  this.placeholder(true);
116
122
  return;
117
123
  }
124
+ if (this.classList.contains('loading')) {
125
+ return;
126
+ }
118
127
  const fit = this.fit;
119
128
  const r = this.crop;
120
129
 
@@ -146,16 +155,17 @@ const HTMLElementImageConstructor = Superclass => class extends Superclass {
146
155
  const rh = rect.height;
147
156
  if (rw == 0 && rh == 0) {
148
157
  // don't show
149
- return this.#defer;
158
+ return;
150
159
  }
151
160
  loc.query.rs = "z-" + this.constructor.getZoom({ w, h, rw, rh, fit });
152
161
  }
153
162
  const curSrc = loc.toString();
154
163
  if (curSrc != this.currentSrc) {
155
164
  this.classList.add('loading');
165
+ this.#defer = new Deferred();
156
166
  img.setAttribute('src', curSrc);
167
+ return this.#defer;
157
168
  }
158
- return this.#defer;
159
169
  }
160
170
  captureLoad() {
161
171
  this.#defer.resolve();
package/ui/input-range.js CHANGED
@@ -82,7 +82,7 @@ class HTMLElementInputRange extends Page.create(HTMLInputElement) {
82
82
  start: opts.multiple ? [null, null] : [null],
83
83
  connect: true
84
84
  }, this.convertOptions(opts))).on('change', (values) => {
85
- if (this.isContentEditable) return;
85
+ if (state.scope.$write) return;
86
86
  const isInt = parseInt(opts.step) == opts.step;
87
87
  helper.classList.remove('indeterminate');
88
88
  if (isInt) values = values.map(n => parseInt(n));
@@ -96,8 +96,8 @@ class HTMLElementInputRange extends Page.create(HTMLInputElement) {
96
96
  helper.addEventListener('dblclick', this, true);
97
97
  this.patch(state);
98
98
  }
99
- handleEvent(e) {
100
- if (this.isContentEditable) return;
99
+ handleEvent(e, state) {
100
+ if (state.scope.$write) return;
101
101
  if (e.type == "dblclick" || e.keyCode == 8 || e.keyCode == 46) {
102
102
  this.fill();
103
103
  this.dispatchEvent(new Event('change', {
package/ui/layout.js CHANGED
@@ -8,6 +8,8 @@ class HTMLElementLayout extends Page.create(HTMLDivElement) {
8
8
  dataPosition:null
9
9
  };
10
10
 
11
+ #defer;
12
+
11
13
  get fit() {
12
14
  return this.options.size || 'none';
13
15
  }
@@ -63,11 +65,14 @@ class HTMLElementLayout extends Page.create(HTMLDivElement) {
63
65
  // pass
64
66
  }
65
67
  this.style.backgroundImage = `url(${curSrc})`;
68
+ this.#defer = new Deferred();
69
+ const img = new Image();
70
+ img.addEventListener('load', this.#defer.resolve);
71
+ img.addEventListener('error', this.#defer.resolve);
72
+ img.src = curSrc;
73
+ return this.#defer;
66
74
  }
67
75
  }
68
- captureLoad() {}
69
- captureError() {}
70
- placeholder() {}
71
76
  }
72
77
 
73
78
  (function(HTMLElementImage) {
package/ui/media.js CHANGED
@@ -14,11 +14,11 @@ const HTMLElementMediaConstructor = Superclass => class extends Superclass {
14
14
  }
15
15
  this.setAttribute('src', curSrc);
16
16
  }
17
- if (this.isContentEditable) this.pause();
18
- return this.#defer;
17
+ if (state.scope.$write) this.pause();
18
+ // return this.#defer; // do not hang chain
19
19
  }
20
- handleClick(e) {
21
- if (this.isContentEditable) e.preventDefault();
20
+ handleClick(e, state) {
21
+ if (state.scope.$write) e.preventDefault();
22
22
  }
23
23
  captureLoad() {
24
24
  this.#defer.resolve();
package/ui/menu.js CHANGED
@@ -24,7 +24,7 @@ class HTMLElementMenu extends Page.Element {
24
24
  });
25
25
  }
26
26
  setup(state) {
27
- if (this.isContentEditable || this.matches('.vertical')) return;
27
+ if (state.scope.$write || this.matches('.vertical')) return;
28
28
  const menu = this.firstElementChild;
29
29
  const helper = this.lastElementChild;
30
30
  if (helper == menu) {
package/ui/pagination.js CHANGED
@@ -1,6 +1,6 @@
1
1
  class HTMLElementPagination extends Page.create(HTMLAnchorElement) {
2
2
  patch(state) {
3
- if (this.isContentEditable) return;
3
+ if (state.scope.$write) return;
4
4
  state.finish(() => {
5
5
  this.#update(state);
6
6
  });
package/ui/query-tags.js CHANGED
@@ -27,7 +27,7 @@ class HTMLElementQueryTags extends Page.Element {
27
27
  const query = state.query;
28
28
  state.finish(() => {
29
29
  this.labels.textContent = '';
30
- if (this.isContentEditable) this.insertLabel('', '', 'Auto');
30
+ if (state.scope.$write) this.insertLabel('', '', 'Auto');
31
31
  else for (const [name, val] of Object.entries(query)) {
32
32
  this.add(name, val);
33
33
  }
package/ui/scroll-link.js CHANGED
@@ -4,7 +4,7 @@ class HTMLScrollLinkElement extends Page.create(HTMLAnchorElement) {
4
4
  };
5
5
 
6
6
  handleClick(e, state) {
7
- if (this.isContentEditable) return;
7
+ if (state.scope.$write) return;
8
8
  if (this.options.to == "home") {
9
9
  const main = document.querySelector('body > main') || document.body;
10
10
  main.scrollIntoView({
package/ui/select.js CHANGED
@@ -24,7 +24,7 @@ class HTMLElementSelect extends Page.Element {
24
24
  }
25
25
 
26
26
  handleClick(e, state) {
27
- if (this.isContentEditable) return;
27
+ if (state.scope.$write) return;
28
28
  const node = e.target;
29
29
  const item = node.closest('element-select .item');
30
30
  if (item) {
@@ -143,7 +143,7 @@ class HTMLElementSelect extends Page.Element {
143
143
  }
144
144
 
145
145
  build(state) {
146
- if (this.isContentEditable) return;
146
+ if (state.scope.$write) return;
147
147
  if (this.children.length == 1) {
148
148
  this.insertAdjacentHTML(
149
149
  'afterBegin',
@@ -169,7 +169,7 @@ class HTMLElementSelect extends Page.Element {
169
169
  }
170
170
 
171
171
  patch(state) {
172
- if (this.isContentEditable) return;
172
+ if (this.state.scope.$write) return;
173
173
  if (this.children.length == 1) this.build(state);
174
174
 
175
175
  state.finish(() => {
package/ui/sitemap.css CHANGED
@@ -2,6 +2,7 @@
2
2
  min-height:2em;
3
3
  position:relative;
4
4
  display: block;
5
+ width: 100%;
5
6
  }
6
7
  [block-type="sitemap"] .caret-icon::before {
7
8
  right:auto;
package/ui/sitemap.js CHANGED
@@ -53,7 +53,7 @@ class HTMLElementSitemap extends Page.Element {
53
53
  }
54
54
 
55
55
  async build(state) {
56
- if (this.firstElementChild.children.length > 0 && this.isContentEditable) {
56
+ if (this.firstElementChild.children.length > 0 && state.scope.$write) {
57
57
  // workaround... build is called a second time with pagecut-placeholder set
58
58
  return;
59
59
  }
package/ui/transition.js CHANGED
@@ -131,7 +131,7 @@ Page.constructor.prototype.mergeBody = function (body, corpse) {
131
131
  if (this.referrer.scope.transition) {
132
132
  this.referrer.scope.transition.end();
133
133
  }
134
- if (body.isContentEditable || body.getAttribute('block-type') != corpse.getAttribute('block-type')) {
134
+ if (this.scope.$write || body.getAttribute('block-type') != corpse.getAttribute('block-type')) {
135
135
  corpse.replaceWith(body);
136
136
  } else {
137
137
  this.scope.transition = new Transition(this, body, corpse);