.mdc-data-table + .mdc-data-table {
margin-top: 16px;
}
:root {
--mdc-data-table-light-theme-bg-color: #fff;
--mdc-data-table-dark-theme-bg-color: #303030;
--mdc-data-table-light-theme-border-color: #e0e0e0;
--mdc-data-table-dark-theme-border-color: #4f4f4f;
--mdc-data-table-light-theme-row-hover: #eee;
--mdc-data-table-dark-theme-row-hover: #414141;
--mdc-data-table-light-theme-row-selected: #f5f5f5;
--mdc-data-table-dark-theme-row-selected: #3a3a3a;
}
.mdc-data-table {
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),
0 1px 5px 0 rgba(0, 0, 0, 0.12);
color: rgba(0, 0, 0, 0.87) !important;
color: var(
--mdc-theme-text-primary-on-background,
rgba(0, 0, 0, 0.87)
) !important;
-webkit-box-orient: vertical;
-ms-flex-flow: column nowrap;
flex-flow: column nowrap;
}
.mdc-data-table,
.mdc-data-table__header {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-direction: normal;
}
.mdc-data-table__header {
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
height: 64px;
-webkit-box-orient: horizontal;
-ms-flex-flow: row nowrap;
flex-flow: row nowrap;
padding: 0 14px 0 24px;
-webkit-box-flex: 0;
-ms-flex: none;
flex: none;
}
.mdc-data-table__header-title {
font-weight: 400;
font-size: 20px;
display: inline-block;
margin: 0;
}
.mdc-data-table__header-actions {
color: rgba(0, 0, 0, 0.54) !important;
color: var(
--mdc-theme-text-secondary-on-background,
rgba(0, 0, 0, 0.54)
) !important;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-orient: horizontal;
-webkit-box-direction: reverse;
-ms-flex-flow: row-reverse nowrap;
flex-flow: row-reverse nowrap;
}
.mdc-data-table__header-actions :nth-last-child(n + 2) {
margin-left: 24px;
}
.mdc-data-table__content {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
.mdc-data-table__content tr:first-child,
.mdc-data-table__content tr:nth-last-child(n + 2) {
border-bottom: 1px solid #e0e0e0;
}
.mdc-data-table__content tr.mdc-data-table--selected {
background-color: #f5f5f5;
}
.mdc-data-table__content td,
.mdc-data-table__content th {
text-align: left;
padding: 12px 24px;
vertical-align: middle;
}
.mdc-data-table__content td.mdc-data-table--numeric,
.mdc-data-table__content th.mdc-data-table--numeric {
text-align: right;
}
.mdc-data-table__content th {
font-size: 13px;
line-height: 17px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
color: rgba(0, 0, 0, 0.54) !important;
color: var(
--mdc-theme-text-secondary-on-background,
rgba(0, 0, 0, 0.54)
) !important;
}
.mdc-data-table__content th.mdc-data-table--sortable {
cursor: pointer;
}
.mdc-data-table__content th.mdc-data-table--sortable.mdc-data-table--sort-asc,
.mdc-data-table__content th.mdc-data-table--sortable.mdc-data-table--sort-desc {
color: rgba(0, 0, 0, 0.87) !important;
color: var(
--mdc-theme-text-primary-on-background,
rgba(0, 0, 0, 0.87)
) !important;
}
.mdc-data-table__content
th.mdc-data-table--sortable.mdc-data-table--sort-asc:before,
.mdc-data-table__content
th.mdc-data-table--sortable.mdc-data-table--sort-desc:before {
font-family: Material Icons;
font-size: 16px;
vertical-align: text-bottom;
line-height: 16px;
margin-right: 8px;
}
.mdc-data-table__content
th.mdc-data-table--sortable.mdc-data-table--sort-asc:before {
content: "arrow_downward";
}
.mdc-data-table__content
th.mdc-data-table--sortable.mdc-data-table--sort-desc:before {
content: "arrow_upward";
}
.mdc-data-table__content td {
font-size: 14px;
}
.mdc-data-table__content tbody tr:hover {
background-color: #eee;
}
.mdc-data-table__footer {
color: rgba(0, 0, 0, 0.54) !important;
color: var(
--mdc-theme-text-secondary-on-background,
rgba(0, 0, 0, 0.54)
) !important;
border-top: 1px solid #e0e0e0;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-align: center;
height: 56px;
-ms-flex-flow: row nowrap;
flex-flow: row nowrap;
padding: 0 14px 0 0;
-webkit-box-flex: 0;
-ms-flex: none;
flex: none;
font-size: 13px;
}
.mdc-data-table__footer,
.mdc-data-table__footer .mdc-data-table__per-page {
-webkit-box-align: center;
align-items: center;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-box-pack: end;
-ms-flex-pack: end;
justify-content: flex-end;
}
.mdc-data-table__footer .mdc-data-table__per-page {
display: -webkit-inline-box;
display: -ms-inline-flexbox;
display: inline-flex;
-ms-flex-flow: row nowrap;
flex-flow: row nowrap;
-ms-flex-align: center;
width: 64px;
background-repeat: no-repeat;
background-position: right 7px center;
text-align: right;
cursor: pointer;
}
.mdc-data-table__footer .mdc-data-table__per-page:after {
font-family: Material Icons;
font-size: 20px;
content: "arrow_drop_down";
margin: 0 2px;
}
.mdc-data-table__footer .mdc-data-table__results {
margin-left: 32px;
}
.mdc-data-table__footer .mdc-data-table__prev {
margin-left: 32px;
cursor: pointer;
}
.mdc-data-table__footer .mdc-data-table__next {
margin-left: 24px;
cursor: pointer;
}
.mdc-data-table [dir="rtl"] td,
.mdc-data-table [dir="rtl"] th,
.mdc-data-table[dir="rtl"] td,
.mdc-data-table[dir="rtl"] th,
.mdc-data-table__content[dir="rtl"] td,
.mdc-data-table__content[dir="rtl"] th {
text-align: right;
}
.mdc-data-table [dir="rtl"] td.mdc-data-table--numeric,
.mdc-data-table [dir="rtl"] th.mdc-data-table--numeric,
.mdc-data-table[dir="rtl"] td.mdc-data-table--numeric,
.mdc-data-table[dir="rtl"] th.mdc-data-table--numeric,
.mdc-data-table__content[dir="rtl"] td.mdc-data-table--numeric,
.mdc-data-table__content[dir="rtl"] th.mdc-data-table--numeric {
text-align: left;
}
.mdc-data-table
[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-asc:before,
.mdc-data-table
[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-desc:before,
.mdc-data-table[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-asc:before,
.mdc-data-table[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-desc:before,
.mdc-data-table__content[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-asc:before,
.mdc-data-table__content[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-desc:before {
display: none;
}
.mdc-data-table
[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-asc:after,
.mdc-data-table
[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-desc:after,
.mdc-data-table[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-asc:after,
.mdc-data-table[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-desc:after,
.mdc-data-table__content[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-asc:after,
.mdc-data-table__content[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-desc:after {
font-family: Material Icons;
font-size: 16px;
vertical-align: text-bottom;
line-height: 16px;
margin-left: 8px;
}
.mdc-data-table
[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-asc:after,
.mdc-data-table[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-asc:after,
.mdc-data-table__content[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-asc:after {
content: "arrow_downward";
}
.mdc-data-table
[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-desc:after,
.mdc-data-table[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-desc:after,
.mdc-data-table__content[dir="rtl"]
.mdc-data-table--sortable.mdc-data-table--sort-desc:after {
content: "arrow_upward";
}
.mdc-data-table--dark,
.mdc-theme--dark .mdc-data-table {
color: #fff !important;
color: var(--mdc-theme-text-primary-on-dark, #fff) !important;
background-color: #303030;
}
.mdc-data-table--dark .mdc-data-table__header-actions,
.mdc-theme--dark .mdc-data-table .mdc-data-table__header-actions {
color: hsla(0, 0%, 100%, 0.7) !important;
color: var(
--mdc-theme-text-secondary-on-dark,
hsla(0, 0%, 100%, 0.7)
) !important;
}
.mdc-data-table--dark .mdc-data-table__content tr:first-child,
.mdc-data-table--dark .mdc-data-table__content tr:nth-last-child(n + 2),
.mdc-theme--dark .mdc-data-table .mdc-data-table__content tr:first-child,
.mdc-theme--dark
.mdc-data-table
.mdc-data-table__content
tr:nth-last-child(n + 2) {
border-bottom-color: #4f4f4f;
}
.mdc-data-table--dark .mdc-data-table__content tr.mdc-data-table--selected,
.mdc-theme--dark
.mdc-data-table
.mdc-data-table__content
tr.mdc-data-table--selected {
background-color: #3a3a3a;
}
.mdc-data-table--dark .mdc-data-table__content th,
.mdc-theme--dark .mdc-data-table .mdc-data-table__content th {
color: hsla(0, 0%, 100%, 0.7) !important;
color: var(
--mdc-theme-text-secondary-on-dark,
hsla(0, 0%, 100%, 0.7)
) !important;
}
.mdc-data-table--dark .mdc-data-table__content th.mdc-data-table--sort-asc,
.mdc-data-table--dark .mdc-data-table__content th.mdc-data-table--sort-desc,
.mdc-theme--dark
.mdc-data-table
.mdc-data-table__content
th.mdc-data-table--sort-asc,
.mdc-theme--dark
.mdc-data-table
.mdc-data-table__content
th.mdc-data-table--sort-desc {
color: #fff !important;
color: var(--mdc-theme-text-primary-on-dark, #fff) !important;
}
.mdc-data-table--dark .mdc-data-table__content tbody tr:hover,
.mdc-theme--dark .mdc-data-table .mdc-data-table__content tbody tr:hover {
background-color: #414141;
}
.mdc-data-table--dark .mdc-data-table__footer,
.mdc-theme--dark .mdc-data-table .mdc-data-table__footer {
color: hsla(0, 0%, 100%, 0.7) !important;
color: var(
--mdc-theme-text-secondary-on-dark,
hsla(0, 0%, 100%, 0.7)
) !important;
border-top-color: #4f4f4f;
}
const {
MDCComponent
} = mdc.base;
const DATATABLE_COLUMNS_SELECTOR = `.mdc-data-table__content thead`,
DATATABLE_DATA_SELECTOR = `.mdc-data-table__content tbody`,
DATATABLE_SORTABLE_SELECTOR = `.mdc-data-table--sortable`,
DATATABLE_COLUMNS_NUMERIC = `mdc-data-table--numeric`,
DATATABLE_COLUMNS_SORTABLE = `mdc-data-table--sortable`,
DATATABLE_COLUMNS_SORT_ASC = `mdc-data-table--sort-asc`,
DATATABLE_COLUMNS_SORT_DESC = `mdc-data-table--sort-desc`;
class MDCDataTable extends MDCComponent {
static attachTo(root) {
return new MDCDataTable(root);
}
get columns() {
return this.foundation_.columns;
}
set columns(columns) {
if (Array.isArray(columns)) {
this.foundation_.setColumns(columns);
} else {
throw new Error(`Expected an array`);
}
}
get data() {
return this.foundation_.data;
}
set data(data) {
if (Array.isArray(data)) {
this.foundation_.setData(data);
} else {
throw new Error(`Expected an array`);
}
}
getDefaultFoundation() {
const getHeaderRow = () => {
let thead = this.root_.querySelector(DATATABLE_COLUMNS_SELECTOR),
row = thead.querySelector(`tr`);
if (!row) {
row = document.createElement(`tr`);
row.setAttribute(`role`, `rowheader`);
thead.appendChild(row);
}
return row;
},
getHeaderColumns = () => {
return getHeaderRow().querySelectorAll(`th`);
},
emptyHeaderColumns = () => {
getHeaderRow().remove();
},
getData = () => {
return this.root_.querySelector(DATATABLE_DATA_SELECTOR);
},
getDataRows = () => {
return getData().querySelectorAll(`tr`);
},
emptyData = () => {
Array.prototype.map.call(getDataRows(), row => {
row.remove();
});
};
return new MDCDataTableFoundation({
registerSortClickHandler: (handler) => this.root_.addEventListener(`click`, handler),
deregisterSortClickHandler: (handler) => this.root_.removeEventListener(`click`, handler),
// Reads the columns list
readColumns: () => {
var cols = getHeaderColumns();
return Array.prototype.map.call(cols, col => {
return {
text: col.textContent,
description: col.getAttribute(`aria-label`),
numeric: col.classList.contains(DATATABLE_COLUMNS_NUMERIC),
sortable: col.classList.contains(DATATABLE_COLUMNS_SORTABLE),
sort: col.classList.contains(DATATABLE_COLUMNS_SORT_ASC) ? 1 : col.classList.contains(DATATABLE_COLUMNS_SORT_DESC) ? -1 : 0
};
});
},
// Edit the columns
setColumns: (cols) => {
emptyHeaderColumns();
let row = getHeaderRow();
cols.forEach(col => {
let column = document.createElement(`th`);
column.setAttribute(`role`, `columnheader`)
// Add text
column.textContent = col.text;
column.setAttribute(`aria-label`, col.description);
// Numeric
if (col.numeric) {
column.classList.add(DATATABLE_COLUMNS_NUMERIC);
}
// Sort
if (col.sortable) {
let ariaSort = `none`;
column.classList.add(DATATABLE_COLUMNS_SORTABLE);
if (col.sort === `asc` || col.sort === 1) {
ariaSort = `ascending`;
column.classList.add(DATATABLE_COLUMNS_SORT_ASC);
} else if (col.sort === `desc` || col.sort === -1) {
ariaSort = `descending`;
column.classList.add(DATATABLE_COLUMNS_SORT_DESC);
}
column.setAttribute(`aria-sort`, ariaSort);
}
// Add to cols
row.appendChild(column);
});
},
// Read data
readData: () => {
var rows = getDataRows();
return Array.prototype.map.call(rows, row => {
let cells = row.querySelectorAll(`td`);
return Array.prototype.map.call(cells, cell => cell.textContent);
});
},
// Edit the data
setData: (data) => {
emptyData();
let element = getData();
// Sorting data
let column = this.columns.find(el => el.sort);
if (column) {
let index = this.columns.indexOf(column);
if (column.sortable) {
let f = (params => {
if (params.sort === `desc` || params.sort === -1) {
return params.numeric ? (a, b) => b[index] - a[index] : (a, b) => b[index].localeCompare(a[index]);
} else {
return params.numeric ? (a, b) => a[index] - b[index] : (a, b) => a[index].localeCompare(b[index]);
}
})(column);
data.sort(f);
}
}
// For each data
data.forEach(d => {
// Create a new row
let row = document.createElement(`tr`);
row.setAttribute(`role`, `row`);
// For each values
d.forEach((val, i) => {
// Create a new cell
let cell = document.createElement(`td`);
cell.setAttribute(`role`, `gridcell`);
// Add numeric if needed
if (this.columns[i].numeric) {
cell.classList.add(DATATABLE_COLUMNS_NUMERIC);
}
// Add content
if (val instanceof Element) {
cell.appendChild(val);
} else {
cell.textContent = val;
}
row.appendChild(cell);
});
// Add to cols
element.appendChild(row);
});
},
// Redraw data table after edit
redraw: () => {
this.foundation_.adapter_.setColumns(this.columns);
this.foundation_.adapter_.setData(this.data);
}
});
}
}
mdc.autoInit.register(`MDCDataTable`, MDCDataTable);
const {
MDCFoundation
} = mdc.base;
class MDCDataTableFoundation extends MDCFoundation {
static get defaultAdapter() {
return {
registerSortClickHandler: ( /* handler: EventListener */ ) => {},
deregisterSortClickHandler: ( /* handler: EventListener */ ) => {},
readColumns: () => {},
setColumns: () => {},
readData: () => {},
setData: () => {},
redraw: () => {}
};
}
constructor(adapter) {
super(Object.assign(MDCDataTableFoundation.defaultAdapter, adapter));
// Attributes
this.columns = [];
this.data = [];
// Methods
// On sort
this.sortClickHandler_ = (e) => {
let target = e.target.closest(DATATABLE_SORTABLE_SELECTOR);
if (target) {
let index = Array.prototype.indexOf.call(target.parentElement.children, target);
this.columns.forEach((col, i) => {
if (i !== index) {
col.sort = 0;
} else {
if (col.sort === `asc` || col.sort === 1) {
col.sort = `desc`;
} else {
col.sort = `asc`;
}
}
});
this.adapter_.redraw();
}
};
}
init() {
// Read columns
this.columns = this.adapter_.readColumns();
// Read data
this.data = this.adapter_.readData();
// Click
this.adapter_.registerSortClickHandler(this.sortClickHandler_);
}
destroy() {
// Click
this.adapter_.deregisterSortClickHandler(this.sortClickHandler_);
}
setColumns(cols) {
this.adapter_.setColumns(cols);
}
setData(data) {
this.adapter_.setData(data);
}
}
var tables = document.querySelectorAll('.mdc-data-table')
Array.prototype.forEach.call(tables, (table) => new MDCDataTable(table));