@loadbare/app 0.19.1 → 0.21.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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  A page shows server data by naming queries and columns in its HTML, and asks
4
4
  the server to change that data by naming requests. The developer writes
5
- sixteen `lb-` attributes. The server declares every query a page may show and
5
+ seventeen `lb-` attributes. The server declares every query a page may show and
6
6
  every request it may send, and refuses anything it has not declared.
7
7
 
8
8
  Everything is a query. A query is a name for rows, of kind `row` or `rows`,
@@ -54,6 +54,7 @@ each with its key, and permits the three requests on `roster`; see
54
54
  | `lb-select` | A checkbox in a row template | Nothing: it selects its live row; see [Selecting rows](#selecting-rows) |
55
55
  | `lb-request` | Any element | The request it sends when it commits |
56
56
  | `lb-url-link` | An `<a>` | A link between pages; see [chrome](./chrome.md#links) |
57
+ | `lb-url-parm` | An `<a lb-url-link>` in a row | Columns of the row its `href` carries as parms; see [chrome](./chrome.md#a-link-from-a-row) |
57
58
  | `lb-url-push` | An element with `lb-request` | A URL change that pushes a history entry |
58
59
  | `lb-url-unknown` | A `<dialog>` in the chrome | The dialog for a URL that names no page |
59
60
 
@@ -66,8 +67,10 @@ builder writes a stamp, and a stylesheet or a custom element reads it.
66
67
  | `lb-key-value` | The key of a live row, or of a `row` landed on an element |
67
68
  | `lb-row-live` | The element is a live row |
68
69
  | `lb-query-row-count` | The number of live rows an element shows |
70
+ | `lb-query-unsorted-count` | The number of them out of order; see [Rows the user is working in](#rows-the-user-is-working-in) |
71
+ | `lb-query-order` | The order placing them; see [Order](#order) |
69
72
  | `lb-group-live`, `lb-group-column`, `lb-group-value` | A group, the column it breaks on, and its value; see [Groups](#groups) |
70
- | `lb-row-created`, `lb-row-changed`, `lb-row-moved`, `lb-row-requested` | What happened to a row; see [What happened to a row](#what-happened-to-a-row) |
73
+ | `lb-row-created`, `lb-row-changed`, `lb-row-moved`, `lb-row-requested`, `lb-row-unsorted` | What happened to a row; see [What happened to a row](#what-happened-to-a-row) |
71
74
  | `lb-row-leaving`, `lb-group-leaving` | A row or group on its way out |
72
75
  | `lb-row-editing` | The row a form is pointed at; see [Editing a row in one form](#editing-a-row-in-one-form) |
73
76
  | `lb-row-selected` | A row whose `lb-select` is ticked |
@@ -147,6 +150,10 @@ no row fills.
147
150
  | Any other custom element | `lb-column-value` only |
148
151
  | Any other element | Its text content, and `lb-column-value` |
149
152
 
153
+ A column lands in one attribute besides: the `href` of a link carrying
154
+ `lb-url-parm` that names it; see
155
+ [A link from a row](./chrome.md#a-link-from-a-row).
156
+
150
157
  A control is an `<input>`, `<select>` or `<textarea>`, or a form-associated
151
158
  custom element with a `value` property that fires `change`. The hub sets a
152
159
  control's `value`, and gathers it back under the same column. A custom
@@ -218,7 +225,9 @@ places it immediately before the template:
218
225
  The hub matches each row to a live row by its key. All rows decide
219
226
  membership: a live row whose key did not arrive leaves. A patch changes only
220
227
  the rows it names, and every other live row keeps its content. The hub
221
- places every live row by the query's order; see [Order](#order). A row that
228
+ places live rows by the query's order, except that an edit from inside the
229
+ list leaves them where they stand; see [Order](#order) and
230
+ [Rows the user is working in](#rows-the-user-is-working-in). A row that
222
231
  does not pass the user's filter is `hidden`; see [Filters](#filters).
223
232
 
224
233
  A live row whose values arrive as it already shows them is not filled
@@ -290,10 +299,71 @@ numerically whatever JSON type its values arrive as, and a value that is no
290
299
  value of its declared type compares as `null` does. `readAs` in
291
300
  `@loadbare/app/types` is the rule the hub applies.
292
301
 
302
+ The element carrying `lb-query` carries `lb-query-order`, the order
303
+ placing its rows as an order's text, the user's when one is chosen and
304
+ the server's otherwise. Rows with no order carry none.
305
+
293
306
  Rows that compare equal keep the order they arrived in, a patch's new rows
294
307
  after the rows already showing. A row moves only when the order
295
308
  puts it somewhere else, so all rows landing again unchanged move nothing.
296
309
 
310
+ ### Rows the user is working in
311
+
312
+ A landing that answers a request sent from inside a list moves none of that
313
+ list's rows. The request is from inside the list when the list is the
314
+ nearest element carrying `lb-query` around the element that sent it: a
315
+ control in a live row, or a ghost row. A form that
316
+ [`--lb-edit`](#editing-a-row-in-one-form) pointed at a live row finishes an
317
+ edit begun in that row, so its request is from inside the row's list,
318
+ wherever the form sits. Any other form elsewhere on the page is not inside
319
+ the list. A user who changes a value sees the value change, and the row
320
+ stays where they were working:
321
+
322
+ | The answer | The row |
323
+ |------------------------------------------|---------------------------------------------------|
324
+ | Changes a column the order reads | Stays where it stands |
325
+ | Creates a row | Goes after the last row of its group, or last of all |
326
+ | Drops a row | Leaves |
327
+ | Changes a row so the filter hides it | Stays showing |
328
+ | Changes the column its group breaks on | Stays under its group's heading |
329
+
330
+ A patch and all rows answering the same edit land the same way. A row left
331
+ where the order or the filter would not leave it is stamped
332
+ `lb-row-unsorted`, and the element carrying `lb-query` carries
333
+ `lb-query-unsorted-count`, the number of such rows. Another element naming
334
+ the same query places its rows by the order: the user was not working
335
+ there.
336
+
337
+ The rows are placed by the order again, and every `lb-row-unsorted` is
338
+ cleared, when the user asks: when the page loads, when the user's order or
339
+ filter changes, or on `--lb-sort`. A button names the list with HTML's
340
+ `commandfor`, and a stylesheet shows it only while it has something to do:
341
+
342
+ ```html
343
+ <div id="roster" lb-query="roster">
344
+ <button type="button" class="resort" commandfor="roster" command="--lb-sort">Re-sort</button>
345
+ <ul>
346
+ <template><li><input lb-column="name" lb-request="lb-row-update" /></li></template>
347
+ </ul>
348
+ </div>
349
+ ```
350
+
351
+ ```css
352
+ .resort {
353
+ display: none;
354
+ }
355
+ [lb-query-unsorted-count]:not([lb-query-unsorted-count="0"]) .resort {
356
+ display: revert;
357
+ }
358
+ ```
359
+
360
+ `--lb-sort` places the rows the hub holds, with no round trip. Aimed at an
361
+ element that carries no `lb-query`, or shows no rows the hub holds, it is
362
+ reported to the console. A custom element that reorders rows by a request of
363
+ its own dispatches the same command on the list once the answer lands, with
364
+ `new CommandEvent("command", { command: "--lb-sort" })`: the user asked for
365
+ the move.
366
+
297
367
  ### Filters
298
368
 
299
369
  Write `lb-filter` on the element carrying `lb-query`, naming the columns of
@@ -311,7 +381,9 @@ its rows the user may filter, separated by commas. The column of
311
381
  ```
312
382
 
313
383
  A row that does not pass every filter is `hidden`, and a ticked `lb-select`
314
- in it is cleared. A group whose rows are all hidden is hidden too
384
+ in it is cleared. A row an edit from inside the list changed stays showing
385
+ until the rows are placed again; see
386
+ [Rows the user is working in](#rows-the-user-is-working-in). A group whose rows are all hidden is hidden too
315
387
  ([miswart](./miswarts.md#rows-hidden-by-a-filter)). An empty
316
388
  choice filters nothing.
317
389
 
@@ -393,7 +465,9 @@ Content after the nested template lands after the group's rows, which is
393
465
  where a group's footer goes.
394
466
 
395
467
  A heading is filled from its group's first row, so it may show a column
396
- other than the one the group breaks on. The hub stamps each top-level
468
+ other than the one the group breaks on. A row an edit from inside the list
469
+ moved to another group stays under its old heading, and the heading shows
470
+ the row as it stood, until the rows are placed again. The hub stamps each top-level
397
471
  element of a group with `lb-group-live`, `lb-group-column` and
398
472
  `lb-group-value`. A row creates its group, and a group leaves with its last
399
473
  row. When the order changes, a group whose run goes on is kept and moved,
@@ -442,6 +516,7 @@ Every change to a list is one a stylesheet can see:
442
516
  | `lb-row-changed` | Its values changed when the hub last touched it |
443
517
  | `lb-row-moved` | Its values changed, and it now stands elsewhere |
444
518
  | `lb-row-requested` | `created`, `changed` or `moved` by this page's request |
519
+ | `lb-row-unsorted` | Stands where the order would not put it |
445
520
  | `lb-row-leaving` | A row on its way out |
446
521
  | `lb-group-leaving` | A group on its way out |
447
522
 
@@ -450,6 +525,9 @@ The hub touches a row when an answer names it. `lb-row-created`,
450
525
  applied again is removed and added as two changes, so an animation keyed to
451
526
  it plays again. `lb-row-requested` is cleared at every landing of the row's
452
527
  query, and set only by a landing that answers a request from the page.
528
+ `lb-row-unsorted` is a state, not an event: it stays until the rows are
529
+ placed by the order; see
530
+ [Rows the user is working in](#rows-the-user-is-working-in).
453
531
 
454
532
  A row or a group that leaves loses `lb-row-live` or `lb-group-live`, takes
455
533
  `lb-row-leaving` or `lb-group-leaving` and `inert`
@@ -498,7 +576,9 @@ insert form above: it sits inside `lb-query="roster"` so its request is for
498
576
 
499
577
  The hub stamps every element that holds a row template with
500
578
  `lb-query-row-count`, the number of live rows it shows. A row a filter
501
- hides is not counted. An empty query is a stylesheet rule:
579
+ hides is not counted. Beside it, `lb-query-unsorted-count` is the number of
580
+ rows out of order; see
581
+ [Rows the user is working in](#rows-the-user-is-working-in). An empty query is a stylesheet rule:
502
582
 
503
583
  ```html
504
584
  <div lb-query="roster">
@@ -956,6 +1036,12 @@ An `lb-show` in the form reads from the row it was pointed at. With no row,
956
1036
  every column is null, so `lb-show="!id"` shows only while entering a new
957
1037
  row.
958
1038
 
1039
+ A request from a form Edit pointed is sent from inside the row's list, so
1040
+ the row stays where the user was working, even when the filter would now
1041
+ hide it or the order would move it; see
1042
+ [Rows the user is working in](#rows-the-user-is-working-in). A form New
1043
+ pointed is not inside any list, and its rows are placed by the order.
1044
+
959
1045
  A successful request from the form lets it go, as Cancel does: the form
960
1046
  empties, its controls return to their defaults, and the stamps go. A failed
961
1047
  one leaves the form as the user had it, to correct.
@@ -980,8 +1066,8 @@ submits the form instead.
980
1066
 
981
1067
  A command the hub cannot carry out is reported to the console: Edit from
982
1068
  outside a live row of the form's query, Edit for a key the hub holds no row
983
- for, and any command aimed at an element that is not a form carrying
984
- `lb-query`.
1069
+ for, and any of these three commands aimed at an element that is not a form
1070
+ carrying `lb-query`.
985
1071
 
986
1072
  ### Selecting rows
987
1073
 
@@ -1228,7 +1314,7 @@ The developer writes `lb-` attributes in markup, and script never assigns
1228
1314
  them. The builder checks the markup of the chrome and of every page, after
1229
1315
  expansion, and refuses to build:
1230
1316
 
1231
- - an `lb-` attribute that is not one of the sixteen the developer writes;
1317
+ - an `lb-` attribute that is not one of the seventeen the developer writes;
1232
1318
  `lb-exp-slot` and `lb-exp-template` are consumed by expansion and never
1233
1319
  reach the check
1234
1320
  - `lb-request` naming an `lb-` request other than the three Loadbare provides
@@ -1241,6 +1327,9 @@ expansion, and refuses to build:
1241
1327
  a form's own when the form carries `lb-query`, and otherwise the nearest
1242
1328
  `lb-query` around the element
1243
1329
  - `lb-url-link` on anything but an `<a>`
1330
+ - `lb-url-parm` on anything but an `<a>` carrying `lb-url-link`, naming no
1331
+ column, naming columns not separated by commas or one beginning `lb-`, or
1332
+ with no row around it
1244
1333
  - `lb-url-push` on an element without `lb-request`
1245
1334
  - `lb-url-unknown` on anything but a `<dialog>`, or outside `<lb-hub>`
1246
1335
  - `lb-show` on a `<template>`, or on a row template's root
@@ -1250,8 +1339,8 @@ expansion, and refuses to build:
1250
1339
  no column
1251
1340
  - `lb-select` on anything but `<input type="checkbox">`, outside a row
1252
1341
  template, or beside `lb-column` or `lb-request`
1253
- - a `command` beginning `--lb-` that is not one of the three commands
1254
- - one of the three commands with no `commandfor`
1342
+ - a `command` beginning `--lb-` that is not one of the four commands
1343
+ - one of the four commands with no `commandfor`
1255
1344
  - `lb-group` on anything but a `<template>`, or on one holding no
1256
1345
  `<template>` for its contents
1257
1346
  - an aggregate on a `<template>`, or any but `lb-count` naming no column
@@ -66,7 +66,7 @@ A widget package declares these. An application never does.
66
66
 
67
67
  ## Attributes
68
68
 
69
- The developer writes sixteen attributes in pages and the chrome, and the
69
+ The developer writes seventeen attributes in pages and the chrome, and the
70
70
  builder refuses any other `lb-` attribute there. `lb-exp-slot` and
71
71
  `lb-exp-template` are written for expansion, which removes them before the
72
72
  check. The hub and the builder write the rest, as stamps, and script never
@@ -84,6 +84,7 @@ assigns one.
84
84
  | `lb-select` | Developer | [Selecting rows](./data-binding.md#selecting-rows) |
85
85
  | `lb-request` | Developer | [Requests](./data-binding.md#requests) |
86
86
  | `lb-url-link` | Developer | [Links](./chrome.md#links) |
87
+ | `lb-url-parm` | Developer | [A link from a row](./chrome.md#a-link-from-a-row) |
87
88
  | `lb-url-push` | Developer | [Query parms](./chrome.md#query-parms) |
88
89
  | `lb-url-unknown` | Developer | [An unknown page](./chrome.md#an-unknown-page) |
89
90
  | `lb-exp-slot` | Developer, consumed by expansion | [The slot](./custom-elements.md#the-slot) |
@@ -92,6 +93,8 @@ assigns one.
92
93
  | `lb-key-value` | Hub | [Landing](./data-binding.md#landing), [Editing a row in one form](./data-binding.md#editing-a-row-in-one-form) |
93
94
  | `lb-row-live` | Hub | [Landing](./data-binding.md#landing) |
94
95
  | `lb-query-row-count` | Hub | [Counting rows](./data-binding.md#counting-rows) |
96
+ | `lb-query-unsorted-count`, `lb-row-unsorted` | Hub | [Rows the user is working in](./data-binding.md#rows-the-user-is-working-in) |
97
+ | `lb-query-order` | Hub | [Order](./data-binding.md#order) |
95
98
  | `lb-group-live`, `lb-group-column`, `lb-group-value` | Hub | [Groups](./data-binding.md#groups) |
96
99
  | `lb-row-created`, `lb-row-changed`, `lb-row-moved`, `lb-row-requested` | Hub | [What happened to a row](./data-binding.md#what-happened-to-a-row) |
97
100
  | `lb-row-leaving`, `lb-group-leaving` | Hub | [What happened to a row](./data-binding.md#what-happened-to-a-row) |
@@ -135,6 +138,7 @@ Loadbare/app owns every value of HTML's `command` attribute beginning with
135
138
  | `--lb-edit` | [Editing a row in one form](./data-binding.md#editing-a-row-in-one-form) |
136
139
  | `--lb-new` | [Editing a row in one form](./data-binding.md#editing-a-row-in-one-form) |
137
140
  | `--lb-release` | [Editing a row in one form](./data-binding.md#editing-a-row-in-one-form) |
141
+ | `--lb-sort` | [Rows the user is working in](./data-binding.md#rows-the-user-is-working-in) |
138
142
 
139
143
  ## Reserved tags
140
144
 
@@ -191,6 +195,8 @@ imports them rather than writing a string.
191
195
  | `ATTR_ROW_LIVE` | `lb-row-live` |
192
196
  | `LIVE_ROW` | `[lb-row-live]`, the selector for a live row |
193
197
  | `ATTR_QUERY_ROW_COUNT` | `lb-query-row-count` |
198
+ | `ATTR_QUERY_UNSORTED_COUNT` | `lb-query-unsorted-count` |
199
+ | `ATTR_QUERY_ORDER` | `lb-query-order` |
194
200
  | `ATTR_GROUP` | `lb-group` |
195
201
  | `ATTR_GROUP_LIVE` | `lb-group-live` |
196
202
  | `ATTR_GROUP_COLUMN` | `lb-group-column` |
@@ -209,6 +215,7 @@ imports them rather than writing a string.
209
215
  | `ATTR_ROW_MOVED` | `lb-row-moved` |
210
216
  | `ATTR_ROW_REQUESTED` | `lb-row-requested` |
211
217
  | `REQUESTED_CREATED`, `REQUESTED_CHANGED`, `REQUESTED_MOVED` | `created`, `changed`, `moved` |
218
+ | `ATTR_ROW_UNSORTED` | `lb-row-unsorted` |
212
219
  | `ATTR_ROW_LEAVING` | `lb-row-leaving` |
213
220
  | `ATTR_GROUP_LEAVING` | `lb-group-leaving` |
214
221
  | `ATTR_REQUEST` | `lb-request` |
@@ -218,8 +225,8 @@ imports them rather than writing a string.
218
225
  | `ATTR_REQUEST_ERROR` | `lb-request-error` |
219
226
  | `ATTR_REQUEST_REFUSED` | `lb-request-refused` |
220
227
  | `LB_REFUSAL_STATUS` | `422` |
221
- | `COMMAND_EDIT`, `COMMAND_NEW`, `COMMAND_RELEASE` | `--lb-edit`, `--lb-new`, `--lb-release` |
222
- | `LB_COMMANDS` | All three commands |
228
+ | `COMMAND_EDIT`, `COMMAND_NEW`, `COMMAND_RELEASE`, `COMMAND_SORT` | `--lb-edit`, `--lb-new`, `--lb-release`, `--lb-sort` |
229
+ | `LB_COMMANDS` | All four commands |
223
230
  | `LB_COMMAND_PREFIX` | `--lb-` |
224
231
  | `ATTR_ROW_EDITING` | `lb-row-editing` |
225
232
  | `ATTR_SELECT` | `lb-select` |
@@ -238,13 +245,14 @@ imports them rather than writing a string.
238
245
  | `URL_COLUMN_PAGE_LABEL` | `lb-page-label` |
239
246
  | `URL_COLUMN_PAGE_UNKNOWN` | `lb-page-unknown` |
240
247
  | `ATTR_URL_LINK` | `lb-url-link` |
248
+ | `ATTR_URL_PARM` | `lb-url-parm` |
241
249
  | `ATTR_URL_PUSH` | `lb-url-push` |
242
250
  | `ATTR_URL_UNKNOWN` | `lb-url-unknown` |
243
251
  | `ATTR_EXP_SLOT` | `lb-exp-slot` |
244
252
  | `ATTR_EXP_TEMPLATE` | `lb-exp-template` |
245
253
  | `ATTR_PAGE` | `lb-page` |
246
254
  | `ATTR_PAGE_TITLE` | `lb-page-title` |
247
- | `DEVELOPER_ATTRIBUTES` | The sixteen attributes a developer writes |
255
+ | `DEVELOPER_ATTRIBUTES` | The seventeen attributes a developer writes |
248
256
  | `HUB_TAG_NAME` | `lb-hub` |
249
257
  | `LB_ENDPOINT` | `/lb` |
250
258
  | `LB_REQUEST_TIMEOUT_MS` | `10000` |
@@ -382,7 +382,8 @@ one row dropped, one row edited — and leave `refresh` empty. A refreshed
382
382
  A change that seems to need a refresh usually has a patch:
383
383
 
384
384
  - A row whose position changes: the hub places it by the query's
385
- [order](./data-binding.md#order).
385
+ [order](./data-binding.md#order), or leaves it where the user is working
386
+ when the request came from inside its list; a refresh would do the same.
386
387
  - A group that appears or goes: the hub makes a group with its first row
387
388
  and removes it with its last, so no row stands in for an empty one.
388
389
  - A row whose other columns change with the edit: re-read the row and patch
@@ -155,7 +155,9 @@ row, the row template, and optionally a footer, each as a `<template>`:
155
155
  | `<template lb-exp-template="foot">` | The `<tfoot>` |
156
156
  | Any other `<template>` | The row or group template, in the `<tbody>` |
157
157
 
158
- - The hub places the rows by the query's order and builds its groups. The
158
+ - The hub places the rows by the query's order and builds its groups, and
159
+ leaves them where they stand for an edit from inside the table; see
160
+ [Rows the user is working in](./data-binding.md#rows-the-user-is-working-in). The
159
161
  rows land in the one `<tbody>`, so a group here is a heading row with its
160
162
  rows after it.
161
163
  - `lb-order` and `lb-filter` go on the `lb-table` itself, beside
@@ -174,6 +176,13 @@ row, the row template, and optionally a footer, each as a `<template>`:
174
176
  - Text selected in a cell whose `lb-column` the table's `lb-filter` names
175
177
  becomes that column's filter in `lb-choices`: `=` for the whole text,
176
178
  `^=` from its start, `$=` up to its end, `*=` otherwise.
179
+ - The heading of the order's leading column carries a triangle for the
180
+ direction, read from [`lb-query-order`](./data-binding.md#order). A
181
+ heading's column is the `lb-column` in the cell at its position in the row
182
+ template. While rows stand out of order the triangle carries
183
+ `data-unsorted` and a click on its heading re-sorts. With `lb-order`, a
184
+ click on the sorted heading reverses the order and a click on another
185
+ sorts by its column. Not on a grouped table.
177
186
 
178
187
  ## `lb-confirm`
179
188