@optionfactory/ful 4.0.9 → 4.0.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/dist/ful.mjs CHANGED
@@ -2424,7 +2424,7 @@ class Pagination extends ParsedElement {
2424
2424
  <nav data-tpl-aria-label="#l10n:t('navigation')" class="user-select-none">
2425
2425
  <ul class="pagination">
2426
2426
  <li class="page-item ms-auto me-2 pagination-index"> {{ #l10n:t('showing', curr.label, total) }}</li>
2427
- <li class="page-item reload me-2"><a role="button"><i data-tpl-class="config.reloadIcon"></i></a></li>
2427
+ <li class="page-item me-2 reload"><a role="button"><i data-tpl-class="config.reloadIcon"></i></a></li>
2428
2428
  <li class="page-item prev">
2429
2429
  <a data-tpl-class="prev.enabled?'page-link':'page-link disabled'" data-tpl-aria-label="#l10n:t('previous')" role="button" data-tpl-data-page="prev.index">
2430
2430
  <i aria-hidden="true" data-tpl-class="config.prevIcon"></i>
@@ -2511,47 +2511,68 @@ class TableSchemaParser {
2511
2511
  if (!schema) {
2512
2512
  throw new Error(`missing expected <schema> in ${nodeOrFragment}`);
2513
2513
  }
2514
- return Nodes.queryChildrenAll(schema, "column")
2515
- .map(el => {
2516
- return {
2517
- sorter: el.getAttribute("sorter"),
2518
- order: el.getAttribute("order"),
2519
- title: TableSchemaParser.#parseTitle(el, template),
2520
- content: TableSchemaParser.#parseContent(el, template)
2514
+ const headersTr = document.createElement("tr");
2515
+ const rowsTr = document.createElement("tr");
2516
+ rowsTr.setAttribute("data-tpl-each", "rows");
2517
+ for (const attr of schema.getAttributeNames()) {
2518
+ const value = schema.getAttribute(attr);
2519
+ headersTr.setAttribute(attr, value ?? '');
2520
+ rowsTr.setAttribute(attr, value ?? '');
2521
+ }
2522
+ const columns = Nodes.queryChildrenAll(schema, "column");
2523
+ const sort = columns.filter(v => v.hasAttribute('order')).map(v => ({sorter: v.getAttribute("sorter"), order: v.getAttribute("order")}))[0] ?? null;
2524
+ for(var column of columns){
2525
+ const maybeTitleTag = Nodes.queryChildren(column, 'title');
2526
+ const sorter = column.getAttribute("sorter");
2527
+ const order = column.getAttribute("order");
2528
+ const titleNode = maybeTitleTag ?? document.createTextNode(column.getAttribute("title") ?? '');
2529
+ maybeTitleTag?.remove();
2530
+ column.removeAttribute("sorter");
2531
+ column.removeAttribute("order");
2532
+ column.removeAttribute("title");
2533
+ const wrappedTitleNode = (!sorter && !order ) ? titleNode : (() => {
2534
+ const fulSorter = document.createElement("ful-sorter");
2535
+ if(sorter){
2536
+ fulSorter.setAttribute("sorter", sorter);
2521
2537
  }
2522
- });
2523
- }
2524
-
2525
- static #parseTitle(el, template) {
2526
- const maybeTitleTag = Nodes.queryChildren(el, 'title');
2527
- if (maybeTitleTag) {
2528
- maybeTitleTag.remove();
2538
+ if(order){
2539
+ fulSorter.setAttribute("order", order);
2540
+ }
2541
+ fulSorter.append(titleNode);
2542
+ return fulSorter;
2543
+ })();
2544
+ const th = document.createElement("th");
2545
+ const td = document.createElement("td");
2546
+ for (const attr of column.getAttributeNames()) {
2547
+ const value = column.getAttribute(attr);
2548
+ th.setAttribute(attr, value ?? '');
2549
+ td.setAttribute(attr, value ?? '');
2550
+ }
2551
+ th.append(wrappedTitleNode);
2552
+ td.append(...column.childNodes);
2553
+ headersTr.append(th);
2554
+ rowsTr.append(td);
2529
2555
  }
2530
- const fragment = maybeTitleTag ? template.withFragment(Fragments.fromChildNodes(maybeTitleTag)).render() : document.createTextNode(el.getAttribute("title") ?? '');
2531
- return {
2532
- classes: el.getAttribute("th-class"),
2533
- fragment
2534
- };
2535
- }
2536
2556
 
2537
- static #parseContent(el, template) {
2538
2557
  return {
2539
- classes: el.getAttribute("td-class"),
2540
- template: template.withFragment(Fragments.fromChildNodes(el))
2558
+ headersTemplate: template.withOverlay({inHeaders: true, inRows: false}).withFragment(Fragments.from(headersTr)),
2559
+ rowsTemplate: template.withOverlay({inHeaders: false, inRows: true}).withFragment(Fragments.from(rowsTr)),
2560
+ sort: sort,
2561
+ length: columns.length
2541
2562
  }
2542
2563
  }
2543
2564
  }
2544
2565
 
2545
- class RemoteTableLoader{
2566
+ class RemoteTableLoader {
2546
2567
  #http;
2547
2568
  #url;
2548
2569
  #method;
2549
- constructor(http, url, method){
2570
+ constructor(http, url, method) {
2550
2571
  this.#http = http;
2551
2572
  this.#url = url;
2552
2573
  this.#method = method;
2553
2574
  }
2554
- async load(pageRequest, sortRequest, filterRequest){
2575
+ async load(pageRequest, sortRequest, filterRequest) {
2555
2576
  const filters = Object.entries(filterRequest).filter(([k, v]) => v);
2556
2577
  return await this.#http.request(this.#method, this.#url)
2557
2578
  .param("page", pageRequest.page)
@@ -2559,12 +2580,12 @@ class RemoteTableLoader{
2559
2580
  .param("sort", sortRequest.order ? `${sortRequest.sorter},${sortRequest.order}` : null)
2560
2581
  .param("filters", filters.length > 0 ? JSON.stringify(Object.fromEntries(filters)) : null)
2561
2582
  .fetchJson();
2562
- }
2583
+ }
2563
2584
  }
2564
2585
 
2565
2586
 
2566
- class TableLoader{
2567
- static create({el, http}){
2587
+ class TableLoader {
2588
+ static create({ el, http }) {
2568
2589
  const url = el.getAttribute("src");
2569
2590
  const method = el.getAttribute("method") ?? 'GET';
2570
2591
  return new RemoteTableLoader(http, url, method);
@@ -2575,18 +2596,18 @@ class Table extends ParsedElement {
2575
2596
  static slots = true;
2576
2597
  static l10n = {
2577
2598
  en: {
2578
- 'notloaded': 'Start searching to see results.',
2599
+ 'initial': 'Start searching to see results.',
2579
2600
  'error': 'Error while loading data:',
2580
2601
  'nodata': 'No elements found.',
2581
2602
  },
2582
2603
  it: {
2583
- 'notloaded': 'Avvia la ricerca per visualizzare i risultati.',
2604
+ 'initial': 'Avvia la ricerca per visualizzare i risultati.',
2584
2605
  'error': 'Errore nel caricamento dei dati:',
2585
2606
  'nodata': 'Nessun elemento trovato.',
2586
2607
  }
2587
2608
  }
2588
- static conf = {
2589
- sortIcon: '',
2609
+ static config = {
2610
+ searchIcon: 'bi bi-search'
2590
2611
  }
2591
2612
  static template = `
2592
2613
  <ful-form data-tpl-if="slots.filters">
@@ -2595,38 +2616,31 @@ class Table extends ParsedElement {
2595
2616
  <div class="table-wrapper">
2596
2617
  <table class="table">
2597
2618
  <caption data-tpl-if="slots.caption">{{{{ slots.caption }}}}</caption>
2598
- <thead>
2599
- <tr>
2600
- <th data-tpl-each="schema" scope="col" data-tpl-class="title.classes">
2601
- {{{{ title.fragment }}}}
2602
- <ful-sorter data-tpl-if="sorter || order" data-tpl-sorter="sorter" data-tpl-order="order"></ful-sorter>
2603
- </th>
2604
- </tr>
2605
- </thead>
2619
+ <thead></thead>
2606
2620
  <tbody></tbody>
2607
- <tbody data-ref="no-autoload">
2621
+ <tbody data-ref="initial">
2608
2622
  <tr>
2609
- <td data-tpl-colspan="schema.length" class="text-center align-middle p-4">
2610
- <i class="bi bi-search" style="font-size: 40px; color: #BDC3CA"></i>
2611
- <p class="mt-3 mb-0" style="color: #BDC3CA">
2612
- {{ #l10n:t('notloaded') }}
2613
- </p>
2623
+ <td data-tpl-colspan="schema.length">
2624
+ <div>
2625
+ <p data-tpl-if="config.searchIcon"><i data-tpl-class="config.searchIcon"></i></p>
2626
+ {{{ #l10n:t('initial') }}}
2627
+ </div>
2614
2628
  </td>
2615
2629
  </tr>
2616
2630
  </tbody>
2617
2631
  <tbody data-ref="loading" hidden>
2618
2632
  <tr>
2619
- <td data-tpl-colspan="schema.length" class="text-center align-middle p-4">
2633
+ <td data-tpl-colspan="schema.length">
2620
2634
  <ful-spinner class="big"></ful-spinner>
2621
2635
  </td>
2622
2636
  </tr>
2623
2637
  </tbody>
2624
2638
  <tbody data-ref="feedback" hidden>
2625
2639
  <tr>
2626
- <td data-tpl-colspan="schema.length" class="text-center align-middle p-4">
2640
+ <td data-tpl-colspan="schema.length">
2627
2641
  <div class="alert alert-danger">
2628
2642
  <p>{{ #l10n:t('error') }}</p>
2629
- <p class="mb-0" data-ref="feedback-error"></p>
2643
+ <div data-ref="feedback-error"></div>
2630
2644
  </div>
2631
2645
  </td>
2632
2646
  </tr>
@@ -2645,11 +2659,7 @@ class Table extends ParsedElement {
2645
2659
  {{ #l10n:t('nodata') }}
2646
2660
  </td>
2647
2661
  </tr>
2648
- <tr data-tpl-each="pageResponse.data" data-tpl-var="row">
2649
- <td data-tpl-each="schema" data-tpl-class="content.classes">
2650
- {{{{ content.template.withOverlay(row).render() }}}}
2651
- </td>
2652
- </tr>
2662
+ {{{{ schema.rowsTemplate.withOverlay({'rows': pageResponse.data}).render() }}}}
2653
2663
  `
2654
2664
  };
2655
2665
  #schema;
@@ -2670,13 +2680,13 @@ class Table extends ParsedElement {
2670
2680
  this.#schema = schema;
2671
2681
  this.#body = table.querySelector(':scope > tbody');
2672
2682
  this.#loading = table.querySelector(":scope > tbody[data-ref=loading]");
2673
- this.#noAutoload = table.querySelector(":scope > tbody[data-ref=no-autoload]");
2683
+ this.#noAutoload = table.querySelector(":scope > tbody[data-ref=initial]");
2674
2684
  this.#feedback = table.querySelector(":scope > tbody[data-ref=feedback]");
2675
2685
  this.#paginator = Nodes.queryChildren(fragment, 'ful-pagination');
2676
2686
  this.#sorters = table.querySelectorAll(':scope > thead ful-sorter') ?? [];
2677
2687
  this.replaceChildren(fragment);
2688
+ schema.headersTemplate.renderTo(this.querySelector('thead'));
2678
2689
  await Rendering.waitForChildren(this);
2679
- const orderFromSchema = schema.find(v => v.order);
2680
2690
 
2681
2691
  const maybeForm = /** @type any */(Nodes.queryChildren(this, 'ful-form'));
2682
2692
  this.#latestRequest = {
@@ -2684,7 +2694,7 @@ class Table extends ParsedElement {
2684
2694
  page: 0,
2685
2695
  size: this.getAttribute("page-size") ? Number(this.getAttribute("page-size")) : 10
2686
2696
  },
2687
- sortRequest: { order: orderFromSchema?.order, sorter: orderFromSchema?.sorter },
2697
+ sortRequest: schema.sort,
2688
2698
  filterRequest: maybeForm?.values ?? {}
2689
2699
  };
2690
2700
  maybeForm?.addEventListener('submit:success', async (evt) => {
@@ -2719,7 +2729,7 @@ class Table extends ParsedElement {
2719
2729
  this.#noAutoload.setAttribute("hidden", "");
2720
2730
  try {
2721
2731
  const loader = Loaders.fromAttributes(this, 'loaders:table');
2722
- const pageResponse =await loader.load(pageRequest, sortRequest, filterRequest);
2732
+ const pageResponse = await loader.load(pageRequest, sortRequest, filterRequest);
2723
2733
  this.#latestRequest = { pageRequest, sortRequest, filterRequest };
2724
2734
  this.#update(pageRequest, sortRequest, filterRequest, pageResponse);
2725
2735
  } catch (/** @type any */error) {