import '@material/mwc-linear-progress'; import '@material/mwc-list/mwc-list-item'; import '../../WebComponents/Select'; import {type Cash} from 'cash-dom/dist/cash'; import { type Children, type Vnode } from 'mithril'; import Component from '../Component.jsx'; import Mdi from '../Mdi.jsx'; import TableColumn from './TableColumn.jsx'; import TableFooter from './TableFooter.jsx'; import TableRow from './TableRow.jsx'; export default class DataTable extends Component { rows: Cash[]; columns: Children[]; footer: Children[]; rowsPerPage = { options: [10, 25, 50, 75, 100], default: 10 } onbeforeupdate(vnode) { super.onbeforeupdate(vnode); const children = (vnode.children: Children[]).flat(); this.rows = this.tableRows(children); this.columns = this.filterElements(children, TableColumn); this.footer = this.filterElements(children, TableFooter); const rowsPerPage = this.attrs.get('rows-per-page'); if (rowsPerPage) { this.rowsPerPage.options = rowsPerPage.split(',') .map((value: string) => Number.parseInt(value, 10)); } let defaultRowsPerPage = this.attrs.get('default-rows-per-page'); if (Number.isInteger(defaultRowsPerPage)) { defaultRowsPerPage = Number.parseInt(defaultRowsPerPage, 10); if (!this.rowsPerPage.options.includes(defaultRowsPerPage)) { [this.rowsPerPage.default] = this.rowsPerPage.options; } } } view(vnode) { return
{this.attrs.has('checkable') && } {this.columns} {this.rows} {this.footer}
{this.attrs.has('paginated') &&
{__('Righe per pagina')}
{this.rowsPerPage.options.map( rowsPerPage => ( {rowsPerPage} ) )}
{__('1-:chunk di :total', { chunk: 10, total: 100 })}
}
; } tableRows(children: Children[]): Children[] { let rows = this.filterElements(children, TableRow); if (this.attrs.has('checkable')) { rows = rows.map((row: Vnode) => ( {row.children} )); } return rows; } filterElements(elements: Children[], tag: Component | string): Children[] { const filtered = []; for (const element: Vnode of elements) { if (element.tag === tag) { filtered.push(element); } } return filtered; } oncreate(vnode) { super.oncreate(vnode); $(this.element) .find('thead th[sortable], thead th[sortable] mwc-icon-button-toggle') .on('click', this.onColumnClicked.bind(this)); } showProgress() { $(this.element) .addClass('mdc-data-table--in-progress') .find('.mdc-data-table__progress-indicator mwc-linear-progress') .get(0) .open(); } hideProgress() { $(this.element) .removeClass('mdc-data-table--in-progress') .find('.mdc-data-table__progress-indicator mwc-linear-progress') .get(0) .open(); } onColumnClicked(event: Event) { this.showProgress(); const column: Cash = $(event.target) .closest('th'); const ascendingClass = 'mdc-data-table__header-cell--sorted'; const descendingClass = 'mdc-data-table__header-cell--sorted-descending'; // If it's already sorted change direction if (column.hasClass(ascendingClass)) { column.toggleClass(descendingClass); } // Clean previously sorted info and arrows const columns = $(this.element) .find('thead th'); columns.removeClass(ascendingClass); columns.find('mwc-icon-button-toggle') .hide(); // Add ony one header to sort column.addClass(ascendingClass); // Check if need descending sorting const isDescending = column.hasClass(descendingClass); // Do sorting this.sortTable(column.index() + 1, isDescending, column.attr('type') === 'numeric'); } sortTable(columnIndex: number, isDescending: boolean, isNumeric: boolean) { const sorted = [...$(this.element) .find(`tr td:nth-child(${columnIndex})`)].sort((a: HTMLElement, b: HTMLElement) => { let aValue = a.textContent; let bValue = b.textContent; if (isNumeric) { aValue = Number.parseFloat(aValue); bValue = Number.parseFloat(bValue); } if (!isDescending) { const temporary = aValue; aValue = bValue; bValue = temporary; } if (typeof aValue === 'string') { return aValue.localeCompare(bValue); } return aValue < bValue ? -1 : (aValue > bValue ? 1 : 0); }); for (const cell of sorted) { const row = $(cell) .parent(); row.appendTo(row.parent()); } } }