Rename data-table-col to data-table-cell, Add Tree Structure support

This commit is contained in:
Faris Ansari 2018-03-01 23:52:21 +05:30
parent 1e71ab9f16
commit 081dbac41b
15 changed files with 834 additions and 336 deletions

View File

@ -178,33 +178,33 @@
background-color: #f5f7fa;
}
.data-table-header .data-table-col.remove-column {
.data-table-header .data-table-cell.remove-column {
background-color: #FD8B8B;
-webkit-transition: 300ms background-color ease-in-out;
transition: 300ms background-color ease-in-out;
}
.data-table-header .data-table-col.sortable-chosen {
.data-table-header .data-table-cell.sortable-chosen {
background-color: #f5f7fa;
}
.data-table-col {
.data-table-cell {
position: relative;
}
.data-table-col .content {
.data-table-cell .content {
padding: 8px;
padding: 0.5rem;
border: 2px solid transparent;
}
.data-table-col .content.ellipsis {
.data-table-cell .content.ellipsis {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.data-table-col .edit-cell {
.data-table-cell .edit-cell {
display: none;
padding: 8px;
padding: 0.5rem;
@ -213,31 +213,51 @@
height: 100%;
}
.data-table-col.selected .content {
.data-table-cell.selected .content {
border: 2px solid rgb(82, 146, 247);
}
.data-table-col.editing .content {
.data-table-cell.editing .content {
display: none;
}
.data-table-col.editing .edit-cell {
.data-table-cell.editing .edit-cell {
border: 2px solid rgb(82, 146, 247);
display: block;
}
.data-table-col.highlight {
.data-table-cell.highlight {
background-color: #f5f7fa;
}
.data-table-col:hover .column-resizer {
.data-table-cell:hover .column-resizer {
display: inline-block;
}
.data-table-col:hover .data-table-dropdown-toggle {
.data-table-cell:hover .data-table-dropdown-toggle {
display: block;
}
.data-table-cell .tree-node {
display: inline-block;
position: relative;
}
.data-table-cell .toggle {
display: inline-block;
position: absolute;
padding: 0 4px;
cursor: pointer;
}
.data-table-cell .toggle:before {
content: '▼';
}
.data-table-cell.tree-close .toggle:before {
content: '►';
}
.data-table-row.row-highlight {
background-color: #f5f7fa;
}

View File

@ -847,6 +847,7 @@ class DataManager {
this.prepareColumns();
this.prepareRows();
this.prepareRowView();
this.prepareNumericColumns();
}
@ -964,6 +965,9 @@ class DataManager {
const index = this._getNextRowCount();
let row = [];
let meta = {
rowIndex: index
};
if (Array.isArray(d)) {
// row is an array
@ -990,17 +994,25 @@ class DataManager {
row.push(d[col.id]);
}
}
meta.indent = d.indent;
}
return this.prepareRow(row, {
rowIndex: index
});
return this.prepareRow(row, meta);
});
}
prepareRow(row, props) {
prepareRowView() {
// This is order in which rows will be rendered in the table.
// When sorting happens, only this.rowViewOrder will change
// and not the original this.rows
this.rowViewOrder = this.rows.map(row => row.meta.rowIndex);
}
prepareRow(row, meta) {
const baseRowCell = {
rowIndex: props.rowIndex
rowIndex: meta.rowIndex,
indent: meta.indent
};
row = row
@ -1008,7 +1020,7 @@ class DataManager {
.map(cell => Object.assign({}, baseRowCell, cell));
// monkey patched in array object
row.meta = props;
row.meta = meta;
return row;
}
@ -1063,28 +1075,28 @@ class DataManager {
(this.currentSort.sortOrder === 'asc' && sortOrder === 'desc') ||
(this.currentSort.sortOrder === 'desc' && sortOrder === 'asc')
) {
this.reverseArray(this.rows);
this.reverseArray(this.rowViewOrder);
this.currentSort.sortOrder = sortOrder;
return;
}
}
this.rows.sort((a, b) => {
const _aIndex = a[0].rowIndex;
const _bIndex = b[0].rowIndex;
const _a = a[colIndex].content;
const _b = b[colIndex].content;
this.rowViewOrder.sort((a, b) => {
const aIndex = a;
const bIndex = b;
const aContent = this.getCell(colIndex, a).content;
const bContent = this.getCell(colIndex, b).content;
if (sortOrder === 'none') {
return _aIndex - _bIndex;
return aIndex - bIndex;
} else if (sortOrder === 'asc') {
if (_a < _b) return -1;
if (_a > _b) return 1;
if (_a === _b) return 0;
if (aContent < bContent) return -1;
if (aContent > bContent) return 1;
if (aContent === bContent) return 0;
} else if (sortOrder === 'desc') {
if (_a < _b) return 1;
if (_a > _b) return -1;
if (_a === _b) return 0;
if (aContent < bContent) return 1;
if (aContent > bContent) return -1;
if (aContent === bContent) return 0;
}
return 0;
});
@ -1093,11 +1105,9 @@ class DataManager {
// update row index
const srNoColIndex = this.getColumnIndexById('_rowIndex');
this.rows.forEach((row, index) => {
row.forEach(cell => {
if (cell.colIndex === srNoColIndex) {
cell.content = (index + 1) + '';
}
});
const viewIndex = this.rowViewOrder.indexOf(index);
const cell = row[srNoColIndex];
cell.content = (viewIndex + 1) + '';
});
}
}
@ -1260,6 +1270,11 @@ class DataManager {
return this.rows.slice(start, end);
}
getRowsForView(start, end) {
const rows = this.rowViewOrder.map(i => this.rows[i]);
return rows.slice(start, end);
}
getColumns(skipStandardColumns) {
let columns = this.columns;
@ -1299,13 +1314,33 @@ class DataManager {
getRow(rowIndex) {
rowIndex = +rowIndex;
return this.rows.find(row => row[0].rowIndex === rowIndex);
return this.rows[rowIndex];
}
getCell(colIndex, rowIndex) {
rowIndex = +rowIndex;
colIndex = +colIndex;
return this.rows.find(row => row[0].rowIndex === rowIndex)[colIndex];
return this.getRow(rowIndex)[colIndex];
}
getChildrenIndices(parentRowIndex) {
parentRowIndex = +parentRowIndex;
const parentIndent = this.getRow(parentRowIndex).meta.indent;
const out = [];
let i = parentRowIndex + 1;
let nextRow = this.getRow(i);
let nextIndent = nextRow ? (nextRow.meta.indent || 0) : -1;
while (nextIndent > parentIndent) {
out.push(i);
i++;
nextRow = this.getRow(i);
nextIndent = nextRow ? (nextRow.meta.indent || 0) : -1;
}
return out;
}
get() {
@ -1365,11 +1400,11 @@ class ColumnManager {
refreshHeader() {
const columns = this.datamanager.getColumns();
const $cols = $.each('.data-table-col[data-is-header]', this.header);
const $cols = $.each('.data-table-cell[data-is-header]', this.header);
const refreshHTML =
// first init
!$('.data-table-col', this.header) ||
!$('.data-table-cell', this.header) ||
// deleted column
columns.length < $cols.length;
@ -1378,7 +1413,9 @@ class ColumnManager {
$('thead', this.header).innerHTML = this.getHeaderHTML(columns);
this.$filterRow = $('.data-table-row[data-is-filter]', this.header);
$.style(this.$filterRow, { display: 'none' });
if (this.$filterRow) {
$.style(this.$filterRow, { display: 'none' });
}
} else {
// update data-attributes
$cols.map(($col, i) => {
@ -1441,7 +1478,7 @@ class ColumnManager {
const dropdownItems = this.options.headerDropdown;
$.on(this.header, 'click', '.data-table-dropdown-list > div', (e, $item) => {
const $col = $.closest('.data-table-col', $item);
const $col = $.closest('.data-table-cell', $item);
const {
index
} = $.data($item);
@ -1463,7 +1500,7 @@ class ColumnManager {
let isDragging = false;
let $resizingCell, startWidth, startX;
$.on(this.header, 'mousedown', '.data-table-col .column-resizer', (e, $handle) => {
$.on(this.header, 'mousedown', '.data-table-cell .column-resizer', (e, $handle) => {
document.body.classList.add('data-table-resize');
const $cell = $handle.parentNode.parentNode;
$resizingCell = $cell;
@ -1520,7 +1557,7 @@ class ColumnManager {
$.off(document.body, 'mousemove', initialize);
return;
}
const ready = $('.data-table-col', this.header);
const ready = $('.data-table-cell', this.header);
if (!ready) return;
const $parent = $('.data-table-row', this.header);
@ -1550,8 +1587,8 @@ class ColumnManager {
bindSortColumn() {
$.on(this.header, 'click', '.data-table-col .column-title', (e, span) => {
const $cell = span.closest('.data-table-col');
$.on(this.header, 'click', '.data-table-cell .column-title', (e, span) => {
const $cell = span.closest('.data-table-cell');
let {
colIndex,
sortOrder
@ -1565,7 +1602,7 @@ class ColumnManager {
// reset sort indicator
$('.sort-indicator', this.header).textContent = '';
$.each('.data-table-col', this.header).map($cell => {
$.each('.data-table-cell', this.header).map($cell => {
$.data($cell, {
sortOrder: 'none'
});
@ -1666,7 +1703,7 @@ class ColumnManager {
bindFilter() {
if (!this.options.enableInlineFilters) return;
const handler = e => {
const $filterCell = $.closest('.data-table-col', e.target);
const $filterCell = $.closest('.data-table-cell', e.target);
const {
colIndex
} = $.data($filterCell);
@ -1677,14 +1714,8 @@ class ColumnManager {
rowsToHide,
rowsToShow
}) => {
rowsToHide.map(rowIndex => {
const $tr = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
$tr.classList.add('hide');
});
rowsToShow.map(rowIndex => {
const $tr = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
$tr.classList.remove('hide');
});
this.rowmanager.hideRows(rowsToHide);
this.rowmanager.showRows(rowsToShow);
});
};
$.on(this.header, 'keydown', '.data-table-filter', debounce$2(handler, 300));
@ -1755,7 +1786,7 @@ class ColumnManager {
}
getHeaderCell$(colIndex) {
return $(`.data-table-col[data-col-index="${colIndex}"]`, this.header);
return $(`.data-table-cell[data-col-index="${colIndex}"]`, this.header);
}
getLastColumnIndex() {
@ -1802,6 +1833,7 @@ class CellManager {
this.bindKeyboardSelection();
this.bindCopyCellContents();
this.bindMouseEvents();
this.bindTreeEvents();
}
bindFocusCell() {
@ -1811,7 +1843,7 @@ class CellManager {
bindEditCell() {
this.$editingCell = null;
$.on(this.bodyScrollable, 'dblclick', '.data-table-col', (e, cell) => {
$.on(this.bodyScrollable, 'dblclick', '.data-table-cell', (e, cell) => {
this.activateEditing(cell);
});
@ -1888,7 +1920,7 @@ class CellManager {
if (this.options.enableInlineFilters) {
this.keyboard.on('ctrl+f', (e) => {
const $cell = $.closest('.data-table-col', e.target);
const $cell = $.closest('.data-table-cell', e.target);
let {
colIndex
} = $.data($cell);
@ -1931,7 +1963,7 @@ class CellManager {
bindMouseEvents() {
let mouseDown = null;
$.on(this.bodyScrollable, 'mousedown', '.data-table-col', (e) => {
$.on(this.bodyScrollable, 'mousedown', '.data-table-cell', (e) => {
mouseDown = true;
this.focusCell($(e.delegatedTarget));
});
@ -1945,7 +1977,39 @@ class CellManager {
this.selectArea($(e.delegatedTarget));
};
$.on(this.bodyScrollable, 'mousemove', '.data-table-col', throttle$1(selectArea, 50));
$.on(this.bodyScrollable, 'mousemove', '.data-table-cell', throttle$1(selectArea, 50));
}
bindTreeEvents() {
$.on(this.bodyScrollable, 'click', '.toggle', (e, $toggle) => {
const $cell = $.closest('.data-table-cell', $toggle);
const { rowIndex } = $.data($cell);
if ($cell.classList.contains('tree-close')) {
this.rowmanager.openTreeNode(rowIndex);
$cell.classList.remove('tree-close');
} else {
this.rowmanager.closeTreeNode(rowIndex);
$cell.classList.add('tree-close');
}
});
// this.keyboard.on('left, right', (e) => {
// const firstColumnIndex = this.datamanager.getColumnIndexById('_rowIndex') + 1;
// if (e.target.matches('.data-table-cell')) {
// const $cell = e.target;
// const { colIndex, rowIndex } = $.data($cell);
// if (+colIndex === firstColumnIndex) {
// if (keyCode[e.keyCode] === 'left') {
// this.rowmanager.closeTreeNode(rowIndex);
// }
// if (keyCode[e.keyCode] === 'right') {
// this.rowmanager.openTreeNode(rowIndex);
// }
// return false;
// }
// }
// });
}
focusCell($cell, {
@ -1995,8 +2059,8 @@ class CellManager {
rowIndex
} = $.data($cell);
const _colIndex = this.datamanager.getColumnIndexById('_rowIndex');
const colHeaderSelector = `.data-table-header .data-table-col[data-col-index="${colIndex}"]`;
const rowHeaderSelector = `.data-table-col[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
const colHeaderSelector = `.data-table-header .data-table-cell[data-col-index="${colIndex}"]`;
const rowHeaderSelector = `.data-table-cell[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
if (this.lastHeaders) {
$.removeStyle(this.lastHeaders, 'backgroundColor');
@ -2122,7 +2186,7 @@ class CellManager {
}
clearSelection() {
$.each('.data-table-col.highlight', this.bodyScrollable)
$.each('.data-table-cell.highlight', this.bodyScrollable)
.map(cell => cell.classList.remove('highlight'));
this.$selectionCursor = null;
@ -2394,15 +2458,16 @@ class CellManager {
});
return `
<td class="data-table-col noselect" ${dataAttr} tabindex="0">
${this.getCellContent(cell)}
</td>
`;
<td class="data-table-cell noselect" ${dataAttr} tabindex="0">
${this.getCellContent(cell)}
</td>
`;
}
getCellContent(cell) {
const {
isHeader
isHeader,
isFilter
} = cell;
const editable = !isHeader && cell.editable !== false;
@ -2418,21 +2483,35 @@ class CellManager {
const dropdown = hasDropdown ? `<div class="data-table-dropdown">${getDropdownHTML()}</div>` : '';
let contentHTML;
if (cell.isHeader || cell.isFilter || !cell.column.format) {
if (isHeader || isFilter || !cell.column.format) {
contentHTML = cell.content;
} else {
contentHTML = cell.column.format(cell.content, cell);
}
if (!(isHeader || isFilter) && cell.indent !== undefined) {
const nextRow = this.datamanager.getRow(cell.rowIndex + 1);
const addToggle = nextRow && nextRow.meta.indent > cell.indent;
// Add toggle and indent in the first column
const firstColumnIndex = this.datamanager.getColumnIndexById('_rowIndex') + 1;
if (firstColumnIndex === cell.colIndex) {
const padding = ((cell.indent || 0) + 1) * 1.5;
const toggleHTML = addToggle ? `<span class="toggle" style="left: ${padding - 1.5}rem"></span>` : '';
contentHTML = `<span class="tree-node" style="padding-left: ${padding}rem">
${toggleHTML}${contentHTML}</span>`;
}
}
return `
<div class="content ellipsis">
${(contentHTML)}
${sortIndicator}
${resizeColumn}
${dropdown}
</div>
${editCellHTML}
`;
<div class="content ellipsis">
${contentHTML}
${sortIndicator}
${resizeColumn}
${dropdown}
</div>
${editCellHTML}
`;
}
getEditCellHTML() {
@ -2442,7 +2521,7 @@ class CellManager {
}
cellSelector(colIndex, rowIndex) {
return `.data-table-col[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`;
return `.data-table-cell[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`;
}
}
@ -2475,8 +2554,8 @@ class RowManager {
// map of checked rows
this.checkMap = [];
$.on(this.wrapper, 'click', '.data-table-col[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
const $cell = $checkbox.closest('.data-table-col');
$.on(this.wrapper, 'click', '.data-table-cell[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
const $cell = $checkbox.closest('.data-table-cell');
const {
rowIndex,
isHeader
@ -2529,7 +2608,7 @@ class RowManager {
checkRow(rowIndex, toggle) {
const value = toggle ? 1 : 0;
const selector = rowIndex =>
`.data-table-col[data-row-index="${rowIndex}"][data-col-index="0"] [type="checkbox"]`;
`.data-table-cell[data-row-index="${rowIndex}"][data-col-index="0"] [type="checkbox"]`;
// update internal map
this.checkMap[rowIndex] = value;
// set checkbox value explicitly
@ -2551,7 +2630,7 @@ class RowManager {
this.checkMap = [];
}
// set checkbox value
$.each('.data-table-col[data-col-index="0"] [type="checkbox"]', this.bodyScrollable)
$.each('.data-table-cell[data-col-index="0"] [type="checkbox"]', this.bodyScrollable)
.map(input => {
input.checked = toggle;
});
@ -2596,8 +2675,32 @@ class RowManager {
}
}
hideRows(rowIndices) {
rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex);
$tr.classList.add('hide');
});
}
showRows(rowIndices) {
rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex);
$tr.classList.remove('hide');
});
}
openTreeNode(rowIndex) {
const rowsToShow = this.datamanager.getChildrenIndices(rowIndex);
this.showRows(rowsToShow);
}
closeTreeNode(rowIndex) {
const rowsToHide = this.datamanager.getChildrenIndices(rowIndex);
this.hideRows(rowsToHide);
}
getRow$(rowIndex) {
return $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
return $(this.selector(rowIndex), this.bodyScrollable);
}
getTotalRows() {
@ -2663,6 +2766,10 @@ class RowManager {
const dataAttr = makeDataAttributeString(props);
return `<input class="data-table-filter input-style" type="text" ${dataAttr} />`;
}
selector(rowIndex) {
return `.data-table-row[data-row-index="${rowIndex}"]`;
}
}
class BodyRenderer {
@ -2686,7 +2793,7 @@ class BodyRenderer {
}
renderBodyHTML() {
const rows = this.datamanager.getRows();
const rows = this.datamanager.getRowsForView();
this.bodyScrollable.innerHTML = `
<table class="data-table-body">
@ -2699,7 +2806,7 @@ class BodyRenderer {
renderBodyWithClusterize() {
// first page
const rows = this.datamanager.getRows(0, 20);
const rows = this.datamanager.getRowsForView(0, 20);
const initialData = this.getDataForClusterize(rows);
if (!this.clusterize) {
@ -2743,7 +2850,7 @@ class BodyRenderer {
}
appendRemainingData() {
const rows = this.datamanager.getRows(20);
const rows = this.datamanager.getRowsForView(20);
const data = this.getDataForClusterize(rows);
this.clusterize.append(data);
}
@ -2860,7 +2967,7 @@ class Style {
}
setupMinWidth() {
$.each('.data-table-col[data-is-header]', this.header).map(col => {
$.each('.data-table-cell[data-is-header]', this.header).map(col => {
const width = $.style($('.content', col), 'width');
const {
colIndex
@ -2878,7 +2985,7 @@ class Style {
if (!$('.data-table-row')) return;
// set initial width as naturally calculated by table's first row
$.each('.data-table-row[data-row-index="0"] .data-table-col', this.bodyScrollable).map($cell => {
$.each('.data-table-row[data-row-index="0"] .data-table-cell', this.bodyScrollable).map($cell => {
const {
colIndex
} = $.data($cell);
@ -2927,7 +3034,7 @@ class Style {
setDefaultCellHeight() {
if (this.__cellHeightSet) return;
const height = this.options.cellHeight ||
$.style($('.data-table-col', this.instance.datatableWrapper), 'height');
$.style($('.data-table-cell', this.instance.datatableWrapper), 'height');
if (height) {
this.setCellHeight(height);
this.__cellHeightSet = true;
@ -2935,10 +3042,10 @@ class Style {
}
setCellHeight(height) {
this.setStyle('.data-table-col .content', {
this.setStyle('.data-table-cell .content', {
height: height + 'px'
});
this.setStyle('.data-table-col .edit-cell', {
this.setStyle('.data-table-cell .edit-cell', {
height: height + 'px'
});
}
@ -2987,7 +3094,7 @@ class Style {
getColumnHeaderElement(colIndex) {
colIndex = +colIndex;
if (colIndex < 0) return null;
return $(`.data-table-col[data-col-index="${colIndex}"]`, this.header);
return $(`.data-table-cell[data-col-index="${colIndex}"]`, this.header);
}
getRowIndexColumnWidth(baseWidth) {

View File

@ -178,33 +178,33 @@
background-color: #f5f7fa;
}
.data-table-header .data-table-col.remove-column {
.data-table-header .data-table-cell.remove-column {
background-color: #FD8B8B;
-webkit-transition: 300ms background-color ease-in-out;
transition: 300ms background-color ease-in-out;
}
.data-table-header .data-table-col.sortable-chosen {
.data-table-header .data-table-cell.sortable-chosen {
background-color: #f5f7fa;
}
.data-table-col {
.data-table-cell {
position: relative;
}
.data-table-col .content {
.data-table-cell .content {
padding: 8px;
padding: 0.5rem;
border: 2px solid transparent;
}
.data-table-col .content.ellipsis {
.data-table-cell .content.ellipsis {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.data-table-col .edit-cell {
.data-table-cell .edit-cell {
display: none;
padding: 8px;
padding: 0.5rem;
@ -213,31 +213,51 @@
height: 100%;
}
.data-table-col.selected .content {
.data-table-cell.selected .content {
border: 2px solid rgb(82, 146, 247);
}
.data-table-col.editing .content {
.data-table-cell.editing .content {
display: none;
}
.data-table-col.editing .edit-cell {
.data-table-cell.editing .edit-cell {
border: 2px solid rgb(82, 146, 247);
display: block;
}
.data-table-col.highlight {
.data-table-cell.highlight {
background-color: #f5f7fa;
}
.data-table-col:hover .column-resizer {
.data-table-cell:hover .column-resizer {
display: inline-block;
}
.data-table-col:hover .data-table-dropdown-toggle {
.data-table-cell:hover .data-table-dropdown-toggle {
display: block;
}
.data-table-cell .tree-node {
display: inline-block;
position: relative;
}
.data-table-cell .toggle {
display: inline-block;
position: absolute;
padding: 0 4px;
cursor: pointer;
}
.data-table-cell .toggle:before {
content: '▼';
}
.data-table-cell.tree-close .toggle:before {
content: '►';
}
.data-table-row.row-highlight {
background-color: #f5f7fa;
}

View File

@ -846,6 +846,7 @@ class DataManager {
this.prepareColumns();
this.prepareRows();
this.prepareRowView();
this.prepareNumericColumns();
}
@ -963,6 +964,9 @@ class DataManager {
const index = this._getNextRowCount();
let row = [];
let meta = {
rowIndex: index
};
if (Array.isArray(d)) {
// row is an array
@ -989,17 +993,25 @@ class DataManager {
row.push(d[col.id]);
}
}
meta.indent = d.indent;
}
return this.prepareRow(row, {
rowIndex: index
});
return this.prepareRow(row, meta);
});
}
prepareRow(row, props) {
prepareRowView() {
// This is order in which rows will be rendered in the table.
// When sorting happens, only this.rowViewOrder will change
// and not the original this.rows
this.rowViewOrder = this.rows.map(row => row.meta.rowIndex);
}
prepareRow(row, meta) {
const baseRowCell = {
rowIndex: props.rowIndex
rowIndex: meta.rowIndex,
indent: meta.indent
};
row = row
@ -1007,7 +1019,7 @@ class DataManager {
.map(cell => Object.assign({}, baseRowCell, cell));
// monkey patched in array object
row.meta = props;
row.meta = meta;
return row;
}
@ -1062,28 +1074,28 @@ class DataManager {
(this.currentSort.sortOrder === 'asc' && sortOrder === 'desc') ||
(this.currentSort.sortOrder === 'desc' && sortOrder === 'asc')
) {
this.reverseArray(this.rows);
this.reverseArray(this.rowViewOrder);
this.currentSort.sortOrder = sortOrder;
return;
}
}
this.rows.sort((a, b) => {
const _aIndex = a[0].rowIndex;
const _bIndex = b[0].rowIndex;
const _a = a[colIndex].content;
const _b = b[colIndex].content;
this.rowViewOrder.sort((a, b) => {
const aIndex = a;
const bIndex = b;
const aContent = this.getCell(colIndex, a).content;
const bContent = this.getCell(colIndex, b).content;
if (sortOrder === 'none') {
return _aIndex - _bIndex;
return aIndex - bIndex;
} else if (sortOrder === 'asc') {
if (_a < _b) return -1;
if (_a > _b) return 1;
if (_a === _b) return 0;
if (aContent < bContent) return -1;
if (aContent > bContent) return 1;
if (aContent === bContent) return 0;
} else if (sortOrder === 'desc') {
if (_a < _b) return 1;
if (_a > _b) return -1;
if (_a === _b) return 0;
if (aContent < bContent) return 1;
if (aContent > bContent) return -1;
if (aContent === bContent) return 0;
}
return 0;
});
@ -1092,11 +1104,9 @@ class DataManager {
// update row index
const srNoColIndex = this.getColumnIndexById('_rowIndex');
this.rows.forEach((row, index) => {
row.forEach(cell => {
if (cell.colIndex === srNoColIndex) {
cell.content = (index + 1) + '';
}
});
const viewIndex = this.rowViewOrder.indexOf(index);
const cell = row[srNoColIndex];
cell.content = (viewIndex + 1) + '';
});
}
}
@ -1259,6 +1269,11 @@ class DataManager {
return this.rows.slice(start, end);
}
getRowsForView(start, end) {
const rows = this.rowViewOrder.map(i => this.rows[i]);
return rows.slice(start, end);
}
getColumns(skipStandardColumns) {
let columns = this.columns;
@ -1298,13 +1313,33 @@ class DataManager {
getRow(rowIndex) {
rowIndex = +rowIndex;
return this.rows.find(row => row[0].rowIndex === rowIndex);
return this.rows[rowIndex];
}
getCell(colIndex, rowIndex) {
rowIndex = +rowIndex;
colIndex = +colIndex;
return this.rows.find(row => row[0].rowIndex === rowIndex)[colIndex];
return this.getRow(rowIndex)[colIndex];
}
getChildrenIndices(parentRowIndex) {
parentRowIndex = +parentRowIndex;
const parentIndent = this.getRow(parentRowIndex).meta.indent;
const out = [];
let i = parentRowIndex + 1;
let nextRow = this.getRow(i);
let nextIndent = nextRow ? (nextRow.meta.indent || 0) : -1;
while (nextIndent > parentIndent) {
out.push(i);
i++;
nextRow = this.getRow(i);
nextIndent = nextRow ? (nextRow.meta.indent || 0) : -1;
}
return out;
}
get() {
@ -1364,11 +1399,11 @@ class ColumnManager {
refreshHeader() {
const columns = this.datamanager.getColumns();
const $cols = $.each('.data-table-col[data-is-header]', this.header);
const $cols = $.each('.data-table-cell[data-is-header]', this.header);
const refreshHTML =
// first init
!$('.data-table-col', this.header) ||
!$('.data-table-cell', this.header) ||
// deleted column
columns.length < $cols.length;
@ -1377,7 +1412,9 @@ class ColumnManager {
$('thead', this.header).innerHTML = this.getHeaderHTML(columns);
this.$filterRow = $('.data-table-row[data-is-filter]', this.header);
$.style(this.$filterRow, { display: 'none' });
if (this.$filterRow) {
$.style(this.$filterRow, { display: 'none' });
}
} else {
// update data-attributes
$cols.map(($col, i) => {
@ -1440,7 +1477,7 @@ class ColumnManager {
const dropdownItems = this.options.headerDropdown;
$.on(this.header, 'click', '.data-table-dropdown-list > div', (e, $item) => {
const $col = $.closest('.data-table-col', $item);
const $col = $.closest('.data-table-cell', $item);
const {
index
} = $.data($item);
@ -1462,7 +1499,7 @@ class ColumnManager {
let isDragging = false;
let $resizingCell, startWidth, startX;
$.on(this.header, 'mousedown', '.data-table-col .column-resizer', (e, $handle) => {
$.on(this.header, 'mousedown', '.data-table-cell .column-resizer', (e, $handle) => {
document.body.classList.add('data-table-resize');
const $cell = $handle.parentNode.parentNode;
$resizingCell = $cell;
@ -1519,7 +1556,7 @@ class ColumnManager {
$.off(document.body, 'mousemove', initialize);
return;
}
const ready = $('.data-table-col', this.header);
const ready = $('.data-table-cell', this.header);
if (!ready) return;
const $parent = $('.data-table-row', this.header);
@ -1549,8 +1586,8 @@ class ColumnManager {
bindSortColumn() {
$.on(this.header, 'click', '.data-table-col .column-title', (e, span) => {
const $cell = span.closest('.data-table-col');
$.on(this.header, 'click', '.data-table-cell .column-title', (e, span) => {
const $cell = span.closest('.data-table-cell');
let {
colIndex,
sortOrder
@ -1564,7 +1601,7 @@ class ColumnManager {
// reset sort indicator
$('.sort-indicator', this.header).textContent = '';
$.each('.data-table-col', this.header).map($cell => {
$.each('.data-table-cell', this.header).map($cell => {
$.data($cell, {
sortOrder: 'none'
});
@ -1665,7 +1702,7 @@ class ColumnManager {
bindFilter() {
if (!this.options.enableInlineFilters) return;
const handler = e => {
const $filterCell = $.closest('.data-table-col', e.target);
const $filterCell = $.closest('.data-table-cell', e.target);
const {
colIndex
} = $.data($filterCell);
@ -1676,14 +1713,8 @@ class ColumnManager {
rowsToHide,
rowsToShow
}) => {
rowsToHide.map(rowIndex => {
const $tr = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
$tr.classList.add('hide');
});
rowsToShow.map(rowIndex => {
const $tr = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
$tr.classList.remove('hide');
});
this.rowmanager.hideRows(rowsToHide);
this.rowmanager.showRows(rowsToShow);
});
};
$.on(this.header, 'keydown', '.data-table-filter', debounce$2(handler, 300));
@ -1754,7 +1785,7 @@ class ColumnManager {
}
getHeaderCell$(colIndex) {
return $(`.data-table-col[data-col-index="${colIndex}"]`, this.header);
return $(`.data-table-cell[data-col-index="${colIndex}"]`, this.header);
}
getLastColumnIndex() {
@ -1801,6 +1832,7 @@ class CellManager {
this.bindKeyboardSelection();
this.bindCopyCellContents();
this.bindMouseEvents();
this.bindTreeEvents();
}
bindFocusCell() {
@ -1810,7 +1842,7 @@ class CellManager {
bindEditCell() {
this.$editingCell = null;
$.on(this.bodyScrollable, 'dblclick', '.data-table-col', (e, cell) => {
$.on(this.bodyScrollable, 'dblclick', '.data-table-cell', (e, cell) => {
this.activateEditing(cell);
});
@ -1887,7 +1919,7 @@ class CellManager {
if (this.options.enableInlineFilters) {
this.keyboard.on('ctrl+f', (e) => {
const $cell = $.closest('.data-table-col', e.target);
const $cell = $.closest('.data-table-cell', e.target);
let {
colIndex
} = $.data($cell);
@ -1930,7 +1962,7 @@ class CellManager {
bindMouseEvents() {
let mouseDown = null;
$.on(this.bodyScrollable, 'mousedown', '.data-table-col', (e) => {
$.on(this.bodyScrollable, 'mousedown', '.data-table-cell', (e) => {
mouseDown = true;
this.focusCell($(e.delegatedTarget));
});
@ -1944,7 +1976,39 @@ class CellManager {
this.selectArea($(e.delegatedTarget));
};
$.on(this.bodyScrollable, 'mousemove', '.data-table-col', throttle$1(selectArea, 50));
$.on(this.bodyScrollable, 'mousemove', '.data-table-cell', throttle$1(selectArea, 50));
}
bindTreeEvents() {
$.on(this.bodyScrollable, 'click', '.toggle', (e, $toggle) => {
const $cell = $.closest('.data-table-cell', $toggle);
const { rowIndex } = $.data($cell);
if ($cell.classList.contains('tree-close')) {
this.rowmanager.openTreeNode(rowIndex);
$cell.classList.remove('tree-close');
} else {
this.rowmanager.closeTreeNode(rowIndex);
$cell.classList.add('tree-close');
}
});
// this.keyboard.on('left, right', (e) => {
// const firstColumnIndex = this.datamanager.getColumnIndexById('_rowIndex') + 1;
// if (e.target.matches('.data-table-cell')) {
// const $cell = e.target;
// const { colIndex, rowIndex } = $.data($cell);
// if (+colIndex === firstColumnIndex) {
// if (keyCode[e.keyCode] === 'left') {
// this.rowmanager.closeTreeNode(rowIndex);
// }
// if (keyCode[e.keyCode] === 'right') {
// this.rowmanager.openTreeNode(rowIndex);
// }
// return false;
// }
// }
// });
}
focusCell($cell, {
@ -1994,8 +2058,8 @@ class CellManager {
rowIndex
} = $.data($cell);
const _colIndex = this.datamanager.getColumnIndexById('_rowIndex');
const colHeaderSelector = `.data-table-header .data-table-col[data-col-index="${colIndex}"]`;
const rowHeaderSelector = `.data-table-col[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
const colHeaderSelector = `.data-table-header .data-table-cell[data-col-index="${colIndex}"]`;
const rowHeaderSelector = `.data-table-cell[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
if (this.lastHeaders) {
$.removeStyle(this.lastHeaders, 'backgroundColor');
@ -2121,7 +2185,7 @@ class CellManager {
}
clearSelection() {
$.each('.data-table-col.highlight', this.bodyScrollable)
$.each('.data-table-cell.highlight', this.bodyScrollable)
.map(cell => cell.classList.remove('highlight'));
this.$selectionCursor = null;
@ -2393,15 +2457,16 @@ class CellManager {
});
return `
<td class="data-table-col noselect" ${dataAttr} tabindex="0">
${this.getCellContent(cell)}
</td>
`;
<td class="data-table-cell noselect" ${dataAttr} tabindex="0">
${this.getCellContent(cell)}
</td>
`;
}
getCellContent(cell) {
const {
isHeader
isHeader,
isFilter
} = cell;
const editable = !isHeader && cell.editable !== false;
@ -2417,21 +2482,35 @@ class CellManager {
const dropdown = hasDropdown ? `<div class="data-table-dropdown">${getDropdownHTML()}</div>` : '';
let contentHTML;
if (cell.isHeader || cell.isFilter || !cell.column.format) {
if (isHeader || isFilter || !cell.column.format) {
contentHTML = cell.content;
} else {
contentHTML = cell.column.format(cell.content, cell);
}
if (!(isHeader || isFilter) && cell.indent !== undefined) {
const nextRow = this.datamanager.getRow(cell.rowIndex + 1);
const addToggle = nextRow && nextRow.meta.indent > cell.indent;
// Add toggle and indent in the first column
const firstColumnIndex = this.datamanager.getColumnIndexById('_rowIndex') + 1;
if (firstColumnIndex === cell.colIndex) {
const padding = ((cell.indent || 0) + 1) * 1.5;
const toggleHTML = addToggle ? `<span class="toggle" style="left: ${padding - 1.5}rem"></span>` : '';
contentHTML = `<span class="tree-node" style="padding-left: ${padding}rem">
${toggleHTML}${contentHTML}</span>`;
}
}
return `
<div class="content ellipsis">
${(contentHTML)}
${sortIndicator}
${resizeColumn}
${dropdown}
</div>
${editCellHTML}
`;
<div class="content ellipsis">
${contentHTML}
${sortIndicator}
${resizeColumn}
${dropdown}
</div>
${editCellHTML}
`;
}
getEditCellHTML() {
@ -2441,7 +2520,7 @@ class CellManager {
}
cellSelector(colIndex, rowIndex) {
return `.data-table-col[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`;
return `.data-table-cell[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`;
}
}
@ -2474,8 +2553,8 @@ class RowManager {
// map of checked rows
this.checkMap = [];
$.on(this.wrapper, 'click', '.data-table-col[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
const $cell = $checkbox.closest('.data-table-col');
$.on(this.wrapper, 'click', '.data-table-cell[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
const $cell = $checkbox.closest('.data-table-cell');
const {
rowIndex,
isHeader
@ -2528,7 +2607,7 @@ class RowManager {
checkRow(rowIndex, toggle) {
const value = toggle ? 1 : 0;
const selector = rowIndex =>
`.data-table-col[data-row-index="${rowIndex}"][data-col-index="0"] [type="checkbox"]`;
`.data-table-cell[data-row-index="${rowIndex}"][data-col-index="0"] [type="checkbox"]`;
// update internal map
this.checkMap[rowIndex] = value;
// set checkbox value explicitly
@ -2550,7 +2629,7 @@ class RowManager {
this.checkMap = [];
}
// set checkbox value
$.each('.data-table-col[data-col-index="0"] [type="checkbox"]', this.bodyScrollable)
$.each('.data-table-cell[data-col-index="0"] [type="checkbox"]', this.bodyScrollable)
.map(input => {
input.checked = toggle;
});
@ -2595,8 +2674,32 @@ class RowManager {
}
}
hideRows(rowIndices) {
rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex);
$tr.classList.add('hide');
});
}
showRows(rowIndices) {
rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex);
$tr.classList.remove('hide');
});
}
openTreeNode(rowIndex) {
const rowsToShow = this.datamanager.getChildrenIndices(rowIndex);
this.showRows(rowsToShow);
}
closeTreeNode(rowIndex) {
const rowsToHide = this.datamanager.getChildrenIndices(rowIndex);
this.hideRows(rowsToHide);
}
getRow$(rowIndex) {
return $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
return $(this.selector(rowIndex), this.bodyScrollable);
}
getTotalRows() {
@ -2662,6 +2765,10 @@ class RowManager {
const dataAttr = makeDataAttributeString(props);
return `<input class="data-table-filter input-style" type="text" ${dataAttr} />`;
}
selector(rowIndex) {
return `.data-table-row[data-row-index="${rowIndex}"]`;
}
}
class BodyRenderer {
@ -2685,7 +2792,7 @@ class BodyRenderer {
}
renderBodyHTML() {
const rows = this.datamanager.getRows();
const rows = this.datamanager.getRowsForView();
this.bodyScrollable.innerHTML = `
<table class="data-table-body">
@ -2698,7 +2805,7 @@ class BodyRenderer {
renderBodyWithClusterize() {
// first page
const rows = this.datamanager.getRows(0, 20);
const rows = this.datamanager.getRowsForView(0, 20);
const initialData = this.getDataForClusterize(rows);
if (!this.clusterize) {
@ -2742,7 +2849,7 @@ class BodyRenderer {
}
appendRemainingData() {
const rows = this.datamanager.getRows(20);
const rows = this.datamanager.getRowsForView(20);
const data = this.getDataForClusterize(rows);
this.clusterize.append(data);
}
@ -2859,7 +2966,7 @@ class Style {
}
setupMinWidth() {
$.each('.data-table-col[data-is-header]', this.header).map(col => {
$.each('.data-table-cell[data-is-header]', this.header).map(col => {
const width = $.style($('.content', col), 'width');
const {
colIndex
@ -2877,7 +2984,7 @@ class Style {
if (!$('.data-table-row')) return;
// set initial width as naturally calculated by table's first row
$.each('.data-table-row[data-row-index="0"] .data-table-col', this.bodyScrollable).map($cell => {
$.each('.data-table-row[data-row-index="0"] .data-table-cell', this.bodyScrollable).map($cell => {
const {
colIndex
} = $.data($cell);
@ -2926,7 +3033,7 @@ class Style {
setDefaultCellHeight() {
if (this.__cellHeightSet) return;
const height = this.options.cellHeight ||
$.style($('.data-table-col', this.instance.datatableWrapper), 'height');
$.style($('.data-table-cell', this.instance.datatableWrapper), 'height');
if (height) {
this.setCellHeight(height);
this.__cellHeightSet = true;
@ -2934,10 +3041,10 @@ class Style {
}
setCellHeight(height) {
this.setStyle('.data-table-col .content', {
this.setStyle('.data-table-cell .content', {
height: height + 'px'
});
this.setStyle('.data-table-col .edit-cell', {
this.setStyle('.data-table-cell .edit-cell', {
height: height + 'px'
});
}
@ -2986,7 +3093,7 @@ class Style {
getColumnHeaderElement(colIndex) {
colIndex = +colIndex;
if (colIndex < 0) return null;
return $(`.data-table-col[data-col-index="${colIndex}"]`, this.header);
return $(`.data-table-cell[data-col-index="${colIndex}"]`, this.header);
}
getRowIndexColumnWidth(baseWidth) {

View File

@ -178,33 +178,33 @@
background-color: #f5f7fa;
}
.data-table-header .data-table-col.remove-column {
.data-table-header .data-table-cell.remove-column {
background-color: #FD8B8B;
-webkit-transition: 300ms background-color ease-in-out;
transition: 300ms background-color ease-in-out;
}
.data-table-header .data-table-col.sortable-chosen {
.data-table-header .data-table-cell.sortable-chosen {
background-color: #f5f7fa;
}
.data-table-col {
.data-table-cell {
position: relative;
}
.data-table-col .content {
.data-table-cell .content {
padding: 8px;
padding: 0.5rem;
border: 2px solid transparent;
}
.data-table-col .content.ellipsis {
.data-table-cell .content.ellipsis {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.data-table-col .edit-cell {
.data-table-cell .edit-cell {
display: none;
padding: 8px;
padding: 0.5rem;
@ -213,31 +213,51 @@
height: 100%;
}
.data-table-col.selected .content {
.data-table-cell.selected .content {
border: 2px solid rgb(82, 146, 247);
}
.data-table-col.editing .content {
.data-table-cell.editing .content {
display: none;
}
.data-table-col.editing .edit-cell {
.data-table-cell.editing .edit-cell {
border: 2px solid rgb(82, 146, 247);
display: block;
}
.data-table-col.highlight {
.data-table-cell.highlight {
background-color: #f5f7fa;
}
.data-table-col:hover .column-resizer {
.data-table-cell:hover .column-resizer {
display: inline-block;
}
.data-table-col:hover .data-table-dropdown-toggle {
.data-table-cell:hover .data-table-dropdown-toggle {
display: block;
}
.data-table-cell .tree-node {
display: inline-block;
position: relative;
}
.data-table-cell .toggle {
display: inline-block;
position: absolute;
padding: 0 4px;
cursor: pointer;
}
.data-table-cell .toggle:before {
content: '▼';
}
.data-table-cell.tree-close .toggle:before {
content: '►';
}
.data-table-row.row-highlight {
background-color: #f5f7fa;
}

View File

@ -846,6 +846,7 @@ class DataManager {
this.prepareColumns();
this.prepareRows();
this.prepareRowView();
this.prepareNumericColumns();
}
@ -963,6 +964,9 @@ class DataManager {
const index = this._getNextRowCount();
let row = [];
let meta = {
rowIndex: index
};
if (Array.isArray(d)) {
// row is an array
@ -989,17 +993,25 @@ class DataManager {
row.push(d[col.id]);
}
}
meta.indent = d.indent;
}
return this.prepareRow(row, {
rowIndex: index
});
return this.prepareRow(row, meta);
});
}
prepareRow(row, props) {
prepareRowView() {
// This is order in which rows will be rendered in the table.
// When sorting happens, only this.rowViewOrder will change
// and not the original this.rows
this.rowViewOrder = this.rows.map(row => row.meta.rowIndex);
}
prepareRow(row, meta) {
const baseRowCell = {
rowIndex: props.rowIndex
rowIndex: meta.rowIndex,
indent: meta.indent
};
row = row
@ -1007,7 +1019,7 @@ class DataManager {
.map(cell => Object.assign({}, baseRowCell, cell));
// monkey patched in array object
row.meta = props;
row.meta = meta;
return row;
}
@ -1062,28 +1074,28 @@ class DataManager {
(this.currentSort.sortOrder === 'asc' && sortOrder === 'desc') ||
(this.currentSort.sortOrder === 'desc' && sortOrder === 'asc')
) {
this.reverseArray(this.rows);
this.reverseArray(this.rowViewOrder);
this.currentSort.sortOrder = sortOrder;
return;
}
}
this.rows.sort((a, b) => {
const _aIndex = a[0].rowIndex;
const _bIndex = b[0].rowIndex;
const _a = a[colIndex].content;
const _b = b[colIndex].content;
this.rowViewOrder.sort((a, b) => {
const aIndex = a;
const bIndex = b;
const aContent = this.getCell(colIndex, a).content;
const bContent = this.getCell(colIndex, b).content;
if (sortOrder === 'none') {
return _aIndex - _bIndex;
return aIndex - bIndex;
} else if (sortOrder === 'asc') {
if (_a < _b) return -1;
if (_a > _b) return 1;
if (_a === _b) return 0;
if (aContent < bContent) return -1;
if (aContent > bContent) return 1;
if (aContent === bContent) return 0;
} else if (sortOrder === 'desc') {
if (_a < _b) return 1;
if (_a > _b) return -1;
if (_a === _b) return 0;
if (aContent < bContent) return 1;
if (aContent > bContent) return -1;
if (aContent === bContent) return 0;
}
return 0;
});
@ -1092,11 +1104,9 @@ class DataManager {
// update row index
const srNoColIndex = this.getColumnIndexById('_rowIndex');
this.rows.forEach((row, index) => {
row.forEach(cell => {
if (cell.colIndex === srNoColIndex) {
cell.content = (index + 1) + '';
}
});
const viewIndex = this.rowViewOrder.indexOf(index);
const cell = row[srNoColIndex];
cell.content = (viewIndex + 1) + '';
});
}
}
@ -1259,6 +1269,11 @@ class DataManager {
return this.rows.slice(start, end);
}
getRowsForView(start, end) {
const rows = this.rowViewOrder.map(i => this.rows[i]);
return rows.slice(start, end);
}
getColumns(skipStandardColumns) {
let columns = this.columns;
@ -1298,13 +1313,33 @@ class DataManager {
getRow(rowIndex) {
rowIndex = +rowIndex;
return this.rows.find(row => row[0].rowIndex === rowIndex);
return this.rows[rowIndex];
}
getCell(colIndex, rowIndex) {
rowIndex = +rowIndex;
colIndex = +colIndex;
return this.rows.find(row => row[0].rowIndex === rowIndex)[colIndex];
return this.getRow(rowIndex)[colIndex];
}
getChildrenIndices(parentRowIndex) {
parentRowIndex = +parentRowIndex;
const parentIndent = this.getRow(parentRowIndex).meta.indent;
const out = [];
let i = parentRowIndex + 1;
let nextRow = this.getRow(i);
let nextIndent = nextRow ? (nextRow.meta.indent || 0) : -1;
while (nextIndent > parentIndent) {
out.push(i);
i++;
nextRow = this.getRow(i);
nextIndent = nextRow ? (nextRow.meta.indent || 0) : -1;
}
return out;
}
get() {
@ -1364,11 +1399,11 @@ class ColumnManager {
refreshHeader() {
const columns = this.datamanager.getColumns();
const $cols = $.each('.data-table-col[data-is-header]', this.header);
const $cols = $.each('.data-table-cell[data-is-header]', this.header);
const refreshHTML =
// first init
!$('.data-table-col', this.header) ||
!$('.data-table-cell', this.header) ||
// deleted column
columns.length < $cols.length;
@ -1377,7 +1412,9 @@ class ColumnManager {
$('thead', this.header).innerHTML = this.getHeaderHTML(columns);
this.$filterRow = $('.data-table-row[data-is-filter]', this.header);
$.style(this.$filterRow, { display: 'none' });
if (this.$filterRow) {
$.style(this.$filterRow, { display: 'none' });
}
} else {
// update data-attributes
$cols.map(($col, i) => {
@ -1440,7 +1477,7 @@ class ColumnManager {
const dropdownItems = this.options.headerDropdown;
$.on(this.header, 'click', '.data-table-dropdown-list > div', (e, $item) => {
const $col = $.closest('.data-table-col', $item);
const $col = $.closest('.data-table-cell', $item);
const {
index
} = $.data($item);
@ -1462,7 +1499,7 @@ class ColumnManager {
let isDragging = false;
let $resizingCell, startWidth, startX;
$.on(this.header, 'mousedown', '.data-table-col .column-resizer', (e, $handle) => {
$.on(this.header, 'mousedown', '.data-table-cell .column-resizer', (e, $handle) => {
document.body.classList.add('data-table-resize');
const $cell = $handle.parentNode.parentNode;
$resizingCell = $cell;
@ -1519,7 +1556,7 @@ class ColumnManager {
$.off(document.body, 'mousemove', initialize);
return;
}
const ready = $('.data-table-col', this.header);
const ready = $('.data-table-cell', this.header);
if (!ready) return;
const $parent = $('.data-table-row', this.header);
@ -1549,8 +1586,8 @@ class ColumnManager {
bindSortColumn() {
$.on(this.header, 'click', '.data-table-col .column-title', (e, span) => {
const $cell = span.closest('.data-table-col');
$.on(this.header, 'click', '.data-table-cell .column-title', (e, span) => {
const $cell = span.closest('.data-table-cell');
let {
colIndex,
sortOrder
@ -1564,7 +1601,7 @@ class ColumnManager {
// reset sort indicator
$('.sort-indicator', this.header).textContent = '';
$.each('.data-table-col', this.header).map($cell => {
$.each('.data-table-cell', this.header).map($cell => {
$.data($cell, {
sortOrder: 'none'
});
@ -1665,7 +1702,7 @@ class ColumnManager {
bindFilter() {
if (!this.options.enableInlineFilters) return;
const handler = e => {
const $filterCell = $.closest('.data-table-col', e.target);
const $filterCell = $.closest('.data-table-cell', e.target);
const {
colIndex
} = $.data($filterCell);
@ -1676,14 +1713,8 @@ class ColumnManager {
rowsToHide,
rowsToShow
}) => {
rowsToHide.map(rowIndex => {
const $tr = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
$tr.classList.add('hide');
});
rowsToShow.map(rowIndex => {
const $tr = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
$tr.classList.remove('hide');
});
this.rowmanager.hideRows(rowsToHide);
this.rowmanager.showRows(rowsToShow);
});
};
$.on(this.header, 'keydown', '.data-table-filter', debounce$2(handler, 300));
@ -1754,7 +1785,7 @@ class ColumnManager {
}
getHeaderCell$(colIndex) {
return $(`.data-table-col[data-col-index="${colIndex}"]`, this.header);
return $(`.data-table-cell[data-col-index="${colIndex}"]`, this.header);
}
getLastColumnIndex() {
@ -1801,6 +1832,7 @@ class CellManager {
this.bindKeyboardSelection();
this.bindCopyCellContents();
this.bindMouseEvents();
this.bindTreeEvents();
}
bindFocusCell() {
@ -1810,7 +1842,7 @@ class CellManager {
bindEditCell() {
this.$editingCell = null;
$.on(this.bodyScrollable, 'dblclick', '.data-table-col', (e, cell) => {
$.on(this.bodyScrollable, 'dblclick', '.data-table-cell', (e, cell) => {
this.activateEditing(cell);
});
@ -1887,7 +1919,7 @@ class CellManager {
if (this.options.enableInlineFilters) {
this.keyboard.on('ctrl+f', (e) => {
const $cell = $.closest('.data-table-col', e.target);
const $cell = $.closest('.data-table-cell', e.target);
let {
colIndex
} = $.data($cell);
@ -1930,7 +1962,7 @@ class CellManager {
bindMouseEvents() {
let mouseDown = null;
$.on(this.bodyScrollable, 'mousedown', '.data-table-col', (e) => {
$.on(this.bodyScrollable, 'mousedown', '.data-table-cell', (e) => {
mouseDown = true;
this.focusCell($(e.delegatedTarget));
});
@ -1944,7 +1976,39 @@ class CellManager {
this.selectArea($(e.delegatedTarget));
};
$.on(this.bodyScrollable, 'mousemove', '.data-table-col', throttle$1(selectArea, 50));
$.on(this.bodyScrollable, 'mousemove', '.data-table-cell', throttle$1(selectArea, 50));
}
bindTreeEvents() {
$.on(this.bodyScrollable, 'click', '.toggle', (e, $toggle) => {
const $cell = $.closest('.data-table-cell', $toggle);
const { rowIndex } = $.data($cell);
if ($cell.classList.contains('tree-close')) {
this.rowmanager.openTreeNode(rowIndex);
$cell.classList.remove('tree-close');
} else {
this.rowmanager.closeTreeNode(rowIndex);
$cell.classList.add('tree-close');
}
});
// this.keyboard.on('left, right', (e) => {
// const firstColumnIndex = this.datamanager.getColumnIndexById('_rowIndex') + 1;
// if (e.target.matches('.data-table-cell')) {
// const $cell = e.target;
// const { colIndex, rowIndex } = $.data($cell);
// if (+colIndex === firstColumnIndex) {
// if (keyCode[e.keyCode] === 'left') {
// this.rowmanager.closeTreeNode(rowIndex);
// }
// if (keyCode[e.keyCode] === 'right') {
// this.rowmanager.openTreeNode(rowIndex);
// }
// return false;
// }
// }
// });
}
focusCell($cell, {
@ -1994,8 +2058,8 @@ class CellManager {
rowIndex
} = $.data($cell);
const _colIndex = this.datamanager.getColumnIndexById('_rowIndex');
const colHeaderSelector = `.data-table-header .data-table-col[data-col-index="${colIndex}"]`;
const rowHeaderSelector = `.data-table-col[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
const colHeaderSelector = `.data-table-header .data-table-cell[data-col-index="${colIndex}"]`;
const rowHeaderSelector = `.data-table-cell[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
if (this.lastHeaders) {
$.removeStyle(this.lastHeaders, 'backgroundColor');
@ -2121,7 +2185,7 @@ class CellManager {
}
clearSelection() {
$.each('.data-table-col.highlight', this.bodyScrollable)
$.each('.data-table-cell.highlight', this.bodyScrollable)
.map(cell => cell.classList.remove('highlight'));
this.$selectionCursor = null;
@ -2393,15 +2457,16 @@ class CellManager {
});
return `
<td class="data-table-col noselect" ${dataAttr} tabindex="0">
${this.getCellContent(cell)}
</td>
`;
<td class="data-table-cell noselect" ${dataAttr} tabindex="0">
${this.getCellContent(cell)}
</td>
`;
}
getCellContent(cell) {
const {
isHeader
isHeader,
isFilter
} = cell;
const editable = !isHeader && cell.editable !== false;
@ -2417,21 +2482,35 @@ class CellManager {
const dropdown = hasDropdown ? `<div class="data-table-dropdown">${getDropdownHTML()}</div>` : '';
let contentHTML;
if (cell.isHeader || cell.isFilter || !cell.column.format) {
if (isHeader || isFilter || !cell.column.format) {
contentHTML = cell.content;
} else {
contentHTML = cell.column.format(cell.content, cell);
}
if (!(isHeader || isFilter) && cell.indent !== undefined) {
const nextRow = this.datamanager.getRow(cell.rowIndex + 1);
const addToggle = nextRow && nextRow.meta.indent > cell.indent;
// Add toggle and indent in the first column
const firstColumnIndex = this.datamanager.getColumnIndexById('_rowIndex') + 1;
if (firstColumnIndex === cell.colIndex) {
const padding = ((cell.indent || 0) + 1) * 1.5;
const toggleHTML = addToggle ? `<span class="toggle" style="left: ${padding - 1.5}rem"></span>` : '';
contentHTML = `<span class="tree-node" style="padding-left: ${padding}rem">
${toggleHTML}${contentHTML}</span>`;
}
}
return `
<div class="content ellipsis">
${(contentHTML)}
${sortIndicator}
${resizeColumn}
${dropdown}
</div>
${editCellHTML}
`;
<div class="content ellipsis">
${contentHTML}
${sortIndicator}
${resizeColumn}
${dropdown}
</div>
${editCellHTML}
`;
}
getEditCellHTML() {
@ -2441,7 +2520,7 @@ class CellManager {
}
cellSelector(colIndex, rowIndex) {
return `.data-table-col[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`;
return `.data-table-cell[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`;
}
}
@ -2474,8 +2553,8 @@ class RowManager {
// map of checked rows
this.checkMap = [];
$.on(this.wrapper, 'click', '.data-table-col[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
const $cell = $checkbox.closest('.data-table-col');
$.on(this.wrapper, 'click', '.data-table-cell[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
const $cell = $checkbox.closest('.data-table-cell');
const {
rowIndex,
isHeader
@ -2528,7 +2607,7 @@ class RowManager {
checkRow(rowIndex, toggle) {
const value = toggle ? 1 : 0;
const selector = rowIndex =>
`.data-table-col[data-row-index="${rowIndex}"][data-col-index="0"] [type="checkbox"]`;
`.data-table-cell[data-row-index="${rowIndex}"][data-col-index="0"] [type="checkbox"]`;
// update internal map
this.checkMap[rowIndex] = value;
// set checkbox value explicitly
@ -2550,7 +2629,7 @@ class RowManager {
this.checkMap = [];
}
// set checkbox value
$.each('.data-table-col[data-col-index="0"] [type="checkbox"]', this.bodyScrollable)
$.each('.data-table-cell[data-col-index="0"] [type="checkbox"]', this.bodyScrollable)
.map(input => {
input.checked = toggle;
});
@ -2595,8 +2674,32 @@ class RowManager {
}
}
hideRows(rowIndices) {
rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex);
$tr.classList.add('hide');
});
}
showRows(rowIndices) {
rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex);
$tr.classList.remove('hide');
});
}
openTreeNode(rowIndex) {
const rowsToShow = this.datamanager.getChildrenIndices(rowIndex);
this.showRows(rowsToShow);
}
closeTreeNode(rowIndex) {
const rowsToHide = this.datamanager.getChildrenIndices(rowIndex);
this.hideRows(rowsToHide);
}
getRow$(rowIndex) {
return $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
return $(this.selector(rowIndex), this.bodyScrollable);
}
getTotalRows() {
@ -2662,6 +2765,10 @@ class RowManager {
const dataAttr = makeDataAttributeString(props);
return `<input class="data-table-filter input-style" type="text" ${dataAttr} />`;
}
selector(rowIndex) {
return `.data-table-row[data-row-index="${rowIndex}"]`;
}
}
class BodyRenderer {
@ -2685,7 +2792,7 @@ class BodyRenderer {
}
renderBodyHTML() {
const rows = this.datamanager.getRows();
const rows = this.datamanager.getRowsForView();
this.bodyScrollable.innerHTML = `
<table class="data-table-body">
@ -2698,7 +2805,7 @@ class BodyRenderer {
renderBodyWithClusterize() {
// first page
const rows = this.datamanager.getRows(0, 20);
const rows = this.datamanager.getRowsForView(0, 20);
const initialData = this.getDataForClusterize(rows);
if (!this.clusterize) {
@ -2742,7 +2849,7 @@ class BodyRenderer {
}
appendRemainingData() {
const rows = this.datamanager.getRows(20);
const rows = this.datamanager.getRowsForView(20);
const data = this.getDataForClusterize(rows);
this.clusterize.append(data);
}
@ -2859,7 +2966,7 @@ class Style {
}
setupMinWidth() {
$.each('.data-table-col[data-is-header]', this.header).map(col => {
$.each('.data-table-cell[data-is-header]', this.header).map(col => {
const width = $.style($('.content', col), 'width');
const {
colIndex
@ -2877,7 +2984,7 @@ class Style {
if (!$('.data-table-row')) return;
// set initial width as naturally calculated by table's first row
$.each('.data-table-row[data-row-index="0"] .data-table-col', this.bodyScrollable).map($cell => {
$.each('.data-table-row[data-row-index="0"] .data-table-cell', this.bodyScrollable).map($cell => {
const {
colIndex
} = $.data($cell);
@ -2926,7 +3033,7 @@ class Style {
setDefaultCellHeight() {
if (this.__cellHeightSet) return;
const height = this.options.cellHeight ||
$.style($('.data-table-col', this.instance.datatableWrapper), 'height');
$.style($('.data-table-cell', this.instance.datatableWrapper), 'height');
if (height) {
this.setCellHeight(height);
this.__cellHeightSet = true;
@ -2934,10 +3041,10 @@ class Style {
}
setCellHeight(height) {
this.setStyle('.data-table-col .content', {
this.setStyle('.data-table-cell .content', {
height: height + 'px'
});
this.setStyle('.data-table-col .edit-cell', {
this.setStyle('.data-table-cell .edit-cell', {
height: height + 'px'
});
}
@ -2986,7 +3093,7 @@ class Style {
getColumnHeaderElement(colIndex) {
colIndex = +colIndex;
if (colIndex < 0) return null;
return $(`.data-table-col[data-col-index="${colIndex}"]`, this.header);
return $(`.data-table-cell[data-col-index="${colIndex}"]`, this.header);
}
getRowIndexColumnWidth(baseWidth) {

View File

@ -12,7 +12,8 @@ let datatable1 = new DataTable('.datatable-1', {
});
let datatable2 = new DataTable('.datatable-2', Object.assign(getTreeData(), {
enableInlineFilters: true
enableInlineFilters: true,
addCheckboxColumn: true
}));
function getSampleData(multiplier) {

View File

@ -54,7 +54,7 @@
if (largeData) {
for (let i = 0; i < 10; i++) {
data = data.concat(data.rows);
data = data.concat(data);
}
}
}

View File

@ -29,6 +29,7 @@ export default class CellManager {
this.bindKeyboardSelection();
this.bindCopyCellContents();
this.bindMouseEvents();
this.bindTreeEvents();
}
bindFocusCell() {
@ -38,7 +39,7 @@ export default class CellManager {
bindEditCell() {
this.$editingCell = null;
$.on(this.bodyScrollable, 'dblclick', '.data-table-col', (e, cell) => {
$.on(this.bodyScrollable, 'dblclick', '.data-table-cell', (e, cell) => {
this.activateEditing(cell);
});
@ -115,7 +116,7 @@ export default class CellManager {
if (this.options.enableInlineFilters) {
this.keyboard.on('ctrl+f', (e) => {
const $cell = $.closest('.data-table-col', e.target);
const $cell = $.closest('.data-table-cell', e.target);
let {
colIndex
} = $.data($cell);
@ -158,7 +159,7 @@ export default class CellManager {
bindMouseEvents() {
let mouseDown = null;
$.on(this.bodyScrollable, 'mousedown', '.data-table-col', (e) => {
$.on(this.bodyScrollable, 'mousedown', '.data-table-cell', (e) => {
mouseDown = true;
this.focusCell($(e.delegatedTarget));
});
@ -172,7 +173,39 @@ export default class CellManager {
this.selectArea($(e.delegatedTarget));
};
$.on(this.bodyScrollable, 'mousemove', '.data-table-col', throttle(selectArea, 50));
$.on(this.bodyScrollable, 'mousemove', '.data-table-cell', throttle(selectArea, 50));
}
bindTreeEvents() {
$.on(this.bodyScrollable, 'click', '.toggle', (e, $toggle) => {
const $cell = $.closest('.data-table-cell', $toggle);
const { rowIndex } = $.data($cell);
if ($cell.classList.contains('tree-close')) {
this.rowmanager.openTreeNode(rowIndex);
$cell.classList.remove('tree-close');
} else {
this.rowmanager.closeTreeNode(rowIndex);
$cell.classList.add('tree-close');
}
});
// this.keyboard.on('left, right', (e) => {
// const firstColumnIndex = this.datamanager.getColumnIndexById('_rowIndex') + 1;
// if (e.target.matches('.data-table-cell')) {
// const $cell = e.target;
// const { colIndex, rowIndex } = $.data($cell);
// if (+colIndex === firstColumnIndex) {
// if (keyCode[e.keyCode] === 'left') {
// this.rowmanager.closeTreeNode(rowIndex);
// }
// if (keyCode[e.keyCode] === 'right') {
// this.rowmanager.openTreeNode(rowIndex);
// }
// return false;
// }
// }
// });
}
focusCell($cell, {
@ -222,8 +255,8 @@ export default class CellManager {
rowIndex
} = $.data($cell);
const _colIndex = this.datamanager.getColumnIndexById('_rowIndex');
const colHeaderSelector = `.data-table-header .data-table-col[data-col-index="${colIndex}"]`;
const rowHeaderSelector = `.data-table-col[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
const colHeaderSelector = `.data-table-header .data-table-cell[data-col-index="${colIndex}"]`;
const rowHeaderSelector = `.data-table-cell[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
if (this.lastHeaders) {
$.removeStyle(this.lastHeaders, 'backgroundColor');
@ -349,7 +382,7 @@ export default class CellManager {
}
clearSelection() {
$.each('.data-table-col.highlight', this.bodyScrollable)
$.each('.data-table-cell.highlight', this.bodyScrollable)
.map(cell => cell.classList.remove('highlight'));
this.$selectionCursor = null;
@ -621,15 +654,16 @@ export default class CellManager {
});
return `
<td class="data-table-col noselect" ${dataAttr} tabindex="0">
${this.getCellContent(cell)}
</td>
`;
<td class="data-table-cell noselect" ${dataAttr} tabindex="0">
${this.getCellContent(cell)}
</td>
`;
}
getCellContent(cell) {
const {
isHeader
isHeader,
isFilter
} = cell;
const editable = !isHeader && cell.editable !== false;
@ -645,21 +679,35 @@ export default class CellManager {
const dropdown = hasDropdown ? `<div class="data-table-dropdown">${getDropdownHTML()}</div>` : '';
let contentHTML;
if (cell.isHeader || cell.isFilter || !cell.column.format) {
if (isHeader || isFilter || !cell.column.format) {
contentHTML = cell.content;
} else {
contentHTML = cell.column.format(cell.content, cell);
}
if (!(isHeader || isFilter) && cell.indent !== undefined) {
const nextRow = this.datamanager.getRow(cell.rowIndex + 1);
const addToggle = nextRow && nextRow.meta.indent > cell.indent;
// Add toggle and indent in the first column
const firstColumnIndex = this.datamanager.getColumnIndexById('_rowIndex') + 1;
if (firstColumnIndex === cell.colIndex) {
const padding = ((cell.indent || 0) + 1) * 1.5;
const toggleHTML = addToggle ? `<span class="toggle" style="left: ${padding - 1.5}rem"></span>` : '';
contentHTML = `<span class="tree-node" style="padding-left: ${padding}rem">
${toggleHTML}${contentHTML}</span>`;
}
}
return `
<div class="content ellipsis">
${(contentHTML)}
${sortIndicator}
${resizeColumn}
${dropdown}
</div>
${editCellHTML}
`;
<div class="content ellipsis">
${contentHTML}
${sortIndicator}
${resizeColumn}
${dropdown}
</div>
${editCellHTML}
`;
}
getEditCellHTML() {
@ -669,6 +717,6 @@ export default class CellManager {
}
cellSelector(colIndex, rowIndex) {
return `.data-table-col[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`;
return `.data-table-cell[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`;
}
}

View File

@ -32,11 +32,11 @@ export default class ColumnManager {
refreshHeader() {
const columns = this.datamanager.getColumns();
const $cols = $.each('.data-table-col[data-is-header]', this.header);
const $cols = $.each('.data-table-cell[data-is-header]', this.header);
const refreshHTML =
// first init
!$('.data-table-col', this.header) ||
!$('.data-table-cell', this.header) ||
// deleted column
columns.length < $cols.length;
@ -45,7 +45,9 @@ export default class ColumnManager {
$('thead', this.header).innerHTML = this.getHeaderHTML(columns);
this.$filterRow = $('.data-table-row[data-is-filter]', this.header);
$.style(this.$filterRow, { display: 'none' });
if (this.$filterRow) {
$.style(this.$filterRow, { display: 'none' });
}
} else {
// update data-attributes
$cols.map(($col, i) => {
@ -108,7 +110,7 @@ export default class ColumnManager {
const dropdownItems = this.options.headerDropdown;
$.on(this.header, 'click', '.data-table-dropdown-list > div', (e, $item) => {
const $col = $.closest('.data-table-col', $item);
const $col = $.closest('.data-table-cell', $item);
const {
index
} = $.data($item);
@ -130,7 +132,7 @@ export default class ColumnManager {
let isDragging = false;
let $resizingCell, startWidth, startX;
$.on(this.header, 'mousedown', '.data-table-col .column-resizer', (e, $handle) => {
$.on(this.header, 'mousedown', '.data-table-cell .column-resizer', (e, $handle) => {
document.body.classList.add('data-table-resize');
const $cell = $handle.parentNode.parentNode;
$resizingCell = $cell;
@ -187,7 +189,7 @@ export default class ColumnManager {
$.off(document.body, 'mousemove', initialize);
return;
}
const ready = $('.data-table-col', this.header);
const ready = $('.data-table-cell', this.header);
if (!ready) return;
const $parent = $('.data-table-row', this.header);
@ -217,8 +219,8 @@ export default class ColumnManager {
bindSortColumn() {
$.on(this.header, 'click', '.data-table-col .column-title', (e, span) => {
const $cell = span.closest('.data-table-col');
$.on(this.header, 'click', '.data-table-cell .column-title', (e, span) => {
const $cell = span.closest('.data-table-cell');
let {
colIndex,
sortOrder
@ -232,7 +234,7 @@ export default class ColumnManager {
// reset sort indicator
$('.sort-indicator', this.header).textContent = '';
$.each('.data-table-col', this.header).map($cell => {
$.each('.data-table-cell', this.header).map($cell => {
$.data($cell, {
sortOrder: 'none'
});
@ -333,7 +335,7 @@ export default class ColumnManager {
bindFilter() {
if (!this.options.enableInlineFilters) return;
const handler = e => {
const $filterCell = $.closest('.data-table-col', e.target);
const $filterCell = $.closest('.data-table-cell', e.target);
const {
colIndex
} = $.data($filterCell);
@ -344,14 +346,8 @@ export default class ColumnManager {
rowsToHide,
rowsToShow
}) => {
rowsToHide.map(rowIndex => {
const $tr = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
$tr.classList.add('hide');
});
rowsToShow.map(rowIndex => {
const $tr = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
$tr.classList.remove('hide');
});
this.rowmanager.hideRows(rowsToHide);
this.rowmanager.showRows(rowsToShow);
});
};
$.on(this.header, 'keydown', '.data-table-filter', debounce(handler, 300));
@ -422,7 +418,7 @@ export default class ColumnManager {
}
getHeaderCell$(colIndex) {
return $(`.data-table-col[data-col-index="${colIndex}"]`, this.header);
return $(`.data-table-cell[data-col-index="${colIndex}"]`, this.header);
}
getLastColumnIndex() {

View File

@ -501,6 +501,26 @@ export default class DataManager {
return this.getRow(rowIndex)[colIndex];
}
getChildrenIndices(parentRowIndex) {
parentRowIndex = +parentRowIndex;
const parentIndent = this.getRow(parentRowIndex).meta.indent;
const out = [];
let i = parentRowIndex + 1;
let nextRow = this.getRow(i);
let nextIndent = nextRow ? (nextRow.meta.indent || 0) : -1;
while (nextIndent > parentIndent) {
out.push(i);
i++;
nextRow = this.getRow(i);
nextIndent = nextRow ? (nextRow.meta.indent || 0) : -1;
}
return out;
}
get() {
return {
columns: this.columns,

View File

@ -54,3 +54,5 @@ export default class Keyboard {
});
}
}
export let keyCode = KEYCODES;

View File

@ -33,8 +33,8 @@ export default class RowManager {
// map of checked rows
this.checkMap = [];
$.on(this.wrapper, 'click', '.data-table-col[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
const $cell = $checkbox.closest('.data-table-col');
$.on(this.wrapper, 'click', '.data-table-cell[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
const $cell = $checkbox.closest('.data-table-cell');
const {
rowIndex,
isHeader
@ -87,7 +87,7 @@ export default class RowManager {
checkRow(rowIndex, toggle) {
const value = toggle ? 1 : 0;
const selector = rowIndex =>
`.data-table-col[data-row-index="${rowIndex}"][data-col-index="0"] [type="checkbox"]`;
`.data-table-cell[data-row-index="${rowIndex}"][data-col-index="0"] [type="checkbox"]`;
// update internal map
this.checkMap[rowIndex] = value;
// set checkbox value explicitly
@ -109,7 +109,7 @@ export default class RowManager {
this.checkMap = [];
}
// set checkbox value
$.each('.data-table-col[data-col-index="0"] [type="checkbox"]', this.bodyScrollable)
$.each('.data-table-cell[data-col-index="0"] [type="checkbox"]', this.bodyScrollable)
.map(input => {
input.checked = toggle;
});
@ -154,8 +154,32 @@ export default class RowManager {
}
}
hideRows(rowIndices) {
rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex);
$tr.classList.add('hide');
});
}
showRows(rowIndices) {
rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex);
$tr.classList.remove('hide');
});
}
openTreeNode(rowIndex) {
const rowsToShow = this.datamanager.getChildrenIndices(rowIndex);
this.showRows(rowsToShow);
}
closeTreeNode(rowIndex) {
const rowsToHide = this.datamanager.getChildrenIndices(rowIndex);
this.hideRows(rowsToHide);
}
getRow$(rowIndex) {
return $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
return $(this.selector(rowIndex), this.bodyScrollable);
}
getTotalRows() {
@ -221,4 +245,8 @@ export default class RowManager {
const dataAttr = makeDataAttributeString(props);
return `<input class="data-table-filter input-style" type="text" ${dataAttr} />`;
}
selector(rowIndex) {
return `.data-table-row[data-row-index="${rowIndex}"]`;
}
}

View File

@ -173,17 +173,17 @@
}
}
.data-table-col.remove-column {
.data-table-cell.remove-column {
background-color: var(--light-red);
transition: 300ms background-color ease-in-out;
}
.data-table-col.sortable-chosen {
.data-table-cell.sortable-chosen {
background-color: var(--light-bg);
}
}
.data-table-col {
.data-table-cell {
position: relative;
.content {
@ -231,6 +231,28 @@
&:hover .data-table-dropdown-toggle {
display: block;
}
.tree-node {
display: inline-block;
position: relative;
}
.toggle {
display: inline-block;
position: absolute;
padding: 0 4px;
cursor: pointer;
}
.toggle:before {
content: '▼';
}
}
.data-table-cell.tree-close {
.toggle:before {
content: '►';
}
}
.data-table-row {

View File

@ -104,7 +104,7 @@ export default class Style {
}
setupMinWidth() {
$.each('.data-table-col[data-is-header]', this.header).map(col => {
$.each('.data-table-cell[data-is-header]', this.header).map(col => {
const width = $.style($('.content', col), 'width');
const {
colIndex
@ -122,7 +122,7 @@ export default class Style {
if (!$('.data-table-row')) return;
// set initial width as naturally calculated by table's first row
$.each('.data-table-row[data-row-index="0"] .data-table-col', this.bodyScrollable).map($cell => {
$.each('.data-table-row[data-row-index="0"] .data-table-cell', this.bodyScrollable).map($cell => {
const {
colIndex
} = $.data($cell);
@ -171,7 +171,7 @@ export default class Style {
setDefaultCellHeight() {
if (this.__cellHeightSet) return;
const height = this.options.cellHeight ||
$.style($('.data-table-col', this.instance.datatableWrapper), 'height');
$.style($('.data-table-cell', this.instance.datatableWrapper), 'height');
if (height) {
this.setCellHeight(height);
this.__cellHeightSet = true;
@ -179,10 +179,10 @@ export default class Style {
}
setCellHeight(height) {
this.setStyle('.data-table-col .content', {
this.setStyle('.data-table-cell .content', {
height: height + 'px'
});
this.setStyle('.data-table-col .edit-cell', {
this.setStyle('.data-table-cell .edit-cell', {
height: height + 'px'
});
}
@ -231,7 +231,7 @@ export default class Style {
getColumnHeaderElement(colIndex) {
colIndex = +colIndex;
if (colIndex < 0) return null;
return $(`.data-table-col[data-col-index="${colIndex}"]`, this.header);
return $(`.data-table-cell[data-col-index="${colIndex}"]`, this.header);
}
getRowIndexColumnWidth(baseWidth) {