UNPKG

@smui/data-table

Version:

Svelte Material UI - Data Table

310 lines 13.5 kB
/** * @license * Copyright 2019 Google Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ import { MDCComponent } from '@smui/base/component'; import { MDCCheckbox } from '@smui/checkbox/component'; import { closest } from '@smui/dom/ponyfill'; import { MDCLinearProgress } from '@smui/linear-progress/component'; import { cssClasses, dataAttributes, events, messages, selectors, SortValue, } from './constants'; import { MDCDataTableFoundation } from './foundation'; /** MDC Data Table */ export class MDCDataTable extends MDCComponent { static attachTo(root) { return new MDCDataTable(root); } initialize(checkboxFactory = (el) => new MDCCheckbox(el)) { this.checkboxFactory = checkboxFactory; } initialSyncWithDOM() { this.headerRow = this.root.querySelector(`.${cssClasses.HEADER_ROW}`); this.handleHeaderRowCheckboxChange = () => { this.foundation.handleHeaderRowCheckboxChange(); }; this.headerRow.addEventListener('change', this.handleHeaderRowCheckboxChange); this.headerRowClickListener = (event) => { this.handleHeaderRowClick(event); }; this.headerRow.addEventListener('click', this.headerRowClickListener); this.content = this.root.querySelector(`.${cssClasses.CONTENT}`); this.handleContentClick = (event) => { const dataRowEl = closest(event.target, selectors.ROW); if (!dataRowEl) return; this.foundation.handleRowClick({ rowId: this.getRowIdByRowElement(dataRowEl), row: dataRowEl, altKey: event.altKey, ctrlKey: event.ctrlKey, metaKey: event.metaKey, shiftKey: event.shiftKey, }); }; this.content.addEventListener('click', this.handleContentClick); this.handleRowCheckboxChange = (event) => { this.foundation.handleRowCheckboxChange(event); }; this.content.addEventListener('change', this.handleRowCheckboxChange); this.layout(); } /** * Re-initializes header row checkbox and row checkboxes when selectable rows * are added or removed from table. */ layout() { this.foundation.layout(); } /** * @return Returns array of header row cell elements. */ getHeaderCells() { return Array.from(this.root.querySelectorAll(selectors.HEADER_CELL)); } /** * @return Returns array of row elements. */ getRows() { return this.foundation.getRows(); } /** * @return Returns array of selected row ids. */ getSelectedRowIds() { return this.foundation.getSelectedRowIds(); } /** * Sets selected row ids. Overwrites previously selected rows. * @param rowIds Array of row ids that needs to be selected. */ setSelectedRowIds(rowIds) { this.foundation.setSelectedRowIds(rowIds); } /** * Shows progress indicator when data table is in loading state. */ showProgress() { this.getLinearProgress().open(); this.foundation.showProgress(); } /** * Hides progress indicator after data table is finished loading. */ hideProgress() { this.foundation.hideProgress(); this.getLinearProgress().close(); } destroy() { if (this.handleHeaderRowCheckboxChange) { this.headerRow.removeEventListener('change', this.handleHeaderRowCheckboxChange); } if (this.headerRowClickListener) { this.headerRow.removeEventListener('click', this.headerRowClickListener); } if (this.handleRowCheckboxChange) { this.content.removeEventListener('change', this.handleRowCheckboxChange); } if (this.headerRowCheckbox) { this.headerRowCheckbox.destroy(); } if (this.rowCheckboxList) { for (const checkbox of this.rowCheckboxList) { checkbox.destroy(); } } if (this.handleContentClick) { this.content.removeEventListener('click', this.handleContentClick); } } getDefaultFoundation() { // DO NOT INLINE this variable. For backward compatibility, foundations take // a Partial<MDCFooAdapter>. To ensure we don't accidentally omit any // methods, we need a separate, strongly typed adapter variable. // tslint:disable:object-literal-sort-keys Methods should be in the same order as the adapter interface. const adapter = { addClass: (className) => { this.root.classList.add(className); }, removeClass: (className) => { this.root.classList.remove(className); }, getHeaderCellElements: () => this.getHeaderCells(), getHeaderCellCount: () => this.getHeaderCells().length, getAttributeByHeaderCellIndex: (index, attribute) => { return this.getHeaderCells()[index].getAttribute(attribute); }, setAttributeByHeaderCellIndex: (index, attribute, value) => { this.safeSetAttribute(this.getHeaderCells()[index], attribute, value); }, setClassNameByHeaderCellIndex: (index, className) => { this.getHeaderCells()[index].classList.add(className); }, removeClassNameByHeaderCellIndex: (index, className) => { this.getHeaderCells()[index].classList.remove(className); }, notifySortAction: (data) => { this.emit(events.SORTED, data, /** shouldBubble */ true); }, getTableContainerHeight: () => { const tableContainer = this.root.querySelector(`.${cssClasses.TABLE_CONTAINER}`); if (!tableContainer) { throw new Error('MDCDataTable: Table container element not found.'); } return tableContainer.getBoundingClientRect().height; }, getTableHeaderHeight: () => { const tableHeader = this.root.querySelector(selectors.HEADER_ROW); if (!tableHeader) { throw new Error('MDCDataTable: Table header element not found.'); } return tableHeader.getBoundingClientRect().height; }, setProgressIndicatorStyles: (styles) => { const progressIndicator = this.root.querySelector(selectors.PROGRESS_INDICATOR); if (!progressIndicator) { throw new Error('MDCDataTable: Progress indicator element not found.'); } progressIndicator.style.setProperty('height', styles.height); progressIndicator.style.setProperty('top', styles.top); }, addClassAtRowIndex: (rowIndex, className) => { this.getRows()[rowIndex].classList.add(className); }, getRowCount: () => this.getRows().length, getRowElements: () => Array.from(this.root.querySelectorAll(selectors.ROW)), getRowIdAtIndex: (rowIndex) => this.getRows()[rowIndex].getAttribute(dataAttributes.ROW_ID), getRowIndexByChildElement: (el) => { return this.getRows().indexOf(closest(el, selectors.ROW)); }, getSelectedRowCount: () => this.root.querySelectorAll(selectors.ROW_SELECTED).length, isCheckboxAtRowIndexChecked: (rowIndex) => this.rowCheckboxList[rowIndex].checked, isHeaderRowCheckboxChecked: () => this.headerRowCheckbox.checked, isRowsSelectable: () => !!this.root.querySelector(selectors.ROW_CHECKBOX) || !!this.root.querySelector(selectors.HEADER_ROW_CHECKBOX), notifyRowSelectionChanged: (data) => { this.emit(events.ROW_SELECTION_CHANGED, { row: this.getRowByIndex(data.rowIndex), rowId: this.getRowIdByIndex(data.rowIndex), rowIndex: data.rowIndex, selected: data.selected, }, /** shouldBubble */ true); }, notifySelectedAll: () => { this.emit(events.SELECTED_ALL, {}, /** shouldBubble */ true); }, notifyUnselectedAll: () => { this.emit(events.UNSELECTED_ALL, {}, /** shouldBubble */ true); }, notifyRowClick: (data) => { this.emit(events.ROW_CLICK, data, /** shouldBubble */ true); }, registerHeaderRowCheckbox: () => { if (this.headerRowCheckbox) { this.headerRowCheckbox.destroy(); } const checkboxEl = this.root.querySelector(selectors.HEADER_ROW_CHECKBOX); this.headerRowCheckbox = this.checkboxFactory(checkboxEl); }, registerRowCheckboxes: () => { if (this.rowCheckboxList) { this.rowCheckboxList.forEach((checkbox) => { checkbox.destroy(); }); } this.rowCheckboxList = []; this.getRows().forEach((rowEl) => { const checkbox = this.checkboxFactory(rowEl.querySelector(selectors.ROW_CHECKBOX)); this.rowCheckboxList.push(checkbox); }); }, removeClassAtRowIndex: (rowIndex, className) => { this.getRows()[rowIndex].classList.remove(className); }, setAttributeAtRowIndex: (rowIndex, attr, value) => { this.safeSetAttribute(this.getRows()[rowIndex], attr, value); }, setHeaderRowCheckboxChecked: (checked) => { this.headerRowCheckbox.checked = checked; }, setHeaderRowCheckboxIndeterminate: (indeterminate) => { this.headerRowCheckbox.indeterminate = indeterminate; }, setRowCheckboxCheckedAtIndex: (rowIndex, checked) => { this.rowCheckboxList[rowIndex].checked = checked; }, setSortStatusLabelByHeaderCellIndex: (columnIndex, sortValue) => { const headerCell = this.getHeaderCells()[columnIndex]; const sortStatusLabel = headerCell.querySelector(selectors.SORT_STATUS_LABEL); if (!sortStatusLabel) return; sortStatusLabel.textContent = this.getSortStatusMessageBySortValue(sortValue); }, }; return new MDCDataTableFoundation(adapter); } getRowByIndex(index) { return this.getRows()[index]; } getRowIdByIndex(index) { return this.getRowByIndex(index).getAttribute(dataAttributes.ROW_ID); } handleHeaderRowClick(event) { const headerCell = closest(event.target, selectors.HEADER_CELL_WITH_SORT); if (!headerCell) { return; } const columnId = headerCell.getAttribute(dataAttributes.COLUMN_ID); const columnIndex = this.getHeaderCells().indexOf(headerCell); if (columnIndex === -1) { return; } this.foundation.handleSortAction({ columnId, columnIndex, headerCell }); } getSortStatusMessageBySortValue(sortValue) { switch (sortValue) { case SortValue.ASCENDING: return messages.SORTED_IN_ASCENDING; case SortValue.DESCENDING: return messages.SORTED_IN_DESCENDING; default: return ''; } } getLinearProgressElement() { const el = this.root.querySelector(`.${cssClasses.LINEAR_PROGRESS}`); if (!el) { throw new Error('MDCDataTable: linear progress element is not found.'); } return el; } getLinearProgress() { if (!this.linearProgress) { const el = this.getLinearProgressElement(); this.linearProgress = new MDCLinearProgress(el); } return this.linearProgress; } getRowIdByRowElement(rowElement) { return rowElement.getAttribute(dataAttributes.ROW_ID); } } //# sourceMappingURL=component.js.map