Rename data-table-col to data-table-cell, Add Tree Structure support
This commit is contained in:
parent
1e71ab9f16
commit
081dbac41b
44
dist/frappe-datatable.cjs.css
vendored
44
dist/frappe-datatable.cjs.css
vendored
@ -178,33 +178,33 @@
|
|||||||
background-color: #f5f7fa;
|
background-color: #f5f7fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-header .data-table-col.remove-column {
|
.data-table-header .data-table-cell.remove-column {
|
||||||
background-color: #FD8B8B;
|
background-color: #FD8B8B;
|
||||||
-webkit-transition: 300ms background-color ease-in-out;
|
-webkit-transition: 300ms background-color ease-in-out;
|
||||||
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;
|
background-color: #f5f7fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col {
|
.data-table-cell {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col .content {
|
.data-table-cell .content {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col .content.ellipsis {
|
.data-table-cell .content.ellipsis {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col .edit-cell {
|
.data-table-cell .edit-cell {
|
||||||
display: none;
|
display: none;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
@ -213,31 +213,51 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col.selected .content {
|
.data-table-cell.selected .content {
|
||||||
border: 2px solid rgb(82, 146, 247);
|
border: 2px solid rgb(82, 146, 247);
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col.editing .content {
|
.data-table-cell.editing .content {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col.editing .edit-cell {
|
.data-table-cell.editing .edit-cell {
|
||||||
border: 2px solid rgb(82, 146, 247);
|
border: 2px solid rgb(82, 146, 247);
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col.highlight {
|
.data-table-cell.highlight {
|
||||||
background-color: #f5f7fa;
|
background-color: #f5f7fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col:hover .column-resizer {
|
.data-table-cell:hover .column-resizer {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col:hover .data-table-dropdown-toggle {
|
.data-table-cell:hover .data-table-dropdown-toggle {
|
||||||
display: block;
|
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 {
|
.data-table-row.row-highlight {
|
||||||
background-color: #f5f7fa;
|
background-color: #f5f7fa;
|
||||||
}
|
}
|
||||||
|
|||||||
269
dist/frappe-datatable.cjs.js
vendored
269
dist/frappe-datatable.cjs.js
vendored
@ -847,6 +847,7 @@ class DataManager {
|
|||||||
|
|
||||||
this.prepareColumns();
|
this.prepareColumns();
|
||||||
this.prepareRows();
|
this.prepareRows();
|
||||||
|
this.prepareRowView();
|
||||||
|
|
||||||
this.prepareNumericColumns();
|
this.prepareNumericColumns();
|
||||||
}
|
}
|
||||||
@ -964,6 +965,9 @@ class DataManager {
|
|||||||
const index = this._getNextRowCount();
|
const index = this._getNextRowCount();
|
||||||
|
|
||||||
let row = [];
|
let row = [];
|
||||||
|
let meta = {
|
||||||
|
rowIndex: index
|
||||||
|
};
|
||||||
|
|
||||||
if (Array.isArray(d)) {
|
if (Array.isArray(d)) {
|
||||||
// row is an array
|
// row is an array
|
||||||
@ -990,17 +994,25 @@ class DataManager {
|
|||||||
row.push(d[col.id]);
|
row.push(d[col.id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meta.indent = d.indent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.prepareRow(row, {
|
return this.prepareRow(row, meta);
|
||||||
rowIndex: index
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = {
|
const baseRowCell = {
|
||||||
rowIndex: props.rowIndex
|
rowIndex: meta.rowIndex,
|
||||||
|
indent: meta.indent
|
||||||
};
|
};
|
||||||
|
|
||||||
row = row
|
row = row
|
||||||
@ -1008,7 +1020,7 @@ class DataManager {
|
|||||||
.map(cell => Object.assign({}, baseRowCell, cell));
|
.map(cell => Object.assign({}, baseRowCell, cell));
|
||||||
|
|
||||||
// monkey patched in array object
|
// monkey patched in array object
|
||||||
row.meta = props;
|
row.meta = meta;
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1063,28 +1075,28 @@ class DataManager {
|
|||||||
(this.currentSort.sortOrder === 'asc' && sortOrder === 'desc') ||
|
(this.currentSort.sortOrder === 'asc' && sortOrder === 'desc') ||
|
||||||
(this.currentSort.sortOrder === 'desc' && sortOrder === 'asc')
|
(this.currentSort.sortOrder === 'desc' && sortOrder === 'asc')
|
||||||
) {
|
) {
|
||||||
this.reverseArray(this.rows);
|
this.reverseArray(this.rowViewOrder);
|
||||||
this.currentSort.sortOrder = sortOrder;
|
this.currentSort.sortOrder = sortOrder;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.rows.sort((a, b) => {
|
this.rowViewOrder.sort((a, b) => {
|
||||||
const _aIndex = a[0].rowIndex;
|
const aIndex = a;
|
||||||
const _bIndex = b[0].rowIndex;
|
const bIndex = b;
|
||||||
const _a = a[colIndex].content;
|
const aContent = this.getCell(colIndex, a).content;
|
||||||
const _b = b[colIndex].content;
|
const bContent = this.getCell(colIndex, b).content;
|
||||||
|
|
||||||
if (sortOrder === 'none') {
|
if (sortOrder === 'none') {
|
||||||
return _aIndex - _bIndex;
|
return aIndex - bIndex;
|
||||||
} else if (sortOrder === 'asc') {
|
} else if (sortOrder === 'asc') {
|
||||||
if (_a < _b) return -1;
|
if (aContent < bContent) return -1;
|
||||||
if (_a > _b) return 1;
|
if (aContent > bContent) return 1;
|
||||||
if (_a === _b) return 0;
|
if (aContent === bContent) return 0;
|
||||||
} else if (sortOrder === 'desc') {
|
} else if (sortOrder === 'desc') {
|
||||||
if (_a < _b) return 1;
|
if (aContent < bContent) return 1;
|
||||||
if (_a > _b) return -1;
|
if (aContent > bContent) return -1;
|
||||||
if (_a === _b) return 0;
|
if (aContent === bContent) return 0;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
@ -1093,11 +1105,9 @@ class DataManager {
|
|||||||
// update row index
|
// update row index
|
||||||
const srNoColIndex = this.getColumnIndexById('_rowIndex');
|
const srNoColIndex = this.getColumnIndexById('_rowIndex');
|
||||||
this.rows.forEach((row, index) => {
|
this.rows.forEach((row, index) => {
|
||||||
row.forEach(cell => {
|
const viewIndex = this.rowViewOrder.indexOf(index);
|
||||||
if (cell.colIndex === srNoColIndex) {
|
const cell = row[srNoColIndex];
|
||||||
cell.content = (index + 1) + '';
|
cell.content = (viewIndex + 1) + '';
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1260,6 +1270,11 @@ class DataManager {
|
|||||||
return this.rows.slice(start, end);
|
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) {
|
getColumns(skipStandardColumns) {
|
||||||
let columns = this.columns;
|
let columns = this.columns;
|
||||||
|
|
||||||
@ -1299,13 +1314,33 @@ class DataManager {
|
|||||||
|
|
||||||
getRow(rowIndex) {
|
getRow(rowIndex) {
|
||||||
rowIndex = +rowIndex;
|
rowIndex = +rowIndex;
|
||||||
return this.rows.find(row => row[0].rowIndex === rowIndex);
|
return this.rows[rowIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
getCell(colIndex, rowIndex) {
|
getCell(colIndex, rowIndex) {
|
||||||
rowIndex = +rowIndex;
|
rowIndex = +rowIndex;
|
||||||
colIndex = +colIndex;
|
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() {
|
get() {
|
||||||
@ -1365,11 +1400,11 @@ class ColumnManager {
|
|||||||
|
|
||||||
refreshHeader() {
|
refreshHeader() {
|
||||||
const columns = this.datamanager.getColumns();
|
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 =
|
const refreshHTML =
|
||||||
// first init
|
// first init
|
||||||
!$('.data-table-col', this.header) ||
|
!$('.data-table-cell', this.header) ||
|
||||||
// deleted column
|
// deleted column
|
||||||
columns.length < $cols.length;
|
columns.length < $cols.length;
|
||||||
|
|
||||||
@ -1378,7 +1413,9 @@ class ColumnManager {
|
|||||||
$('thead', this.header).innerHTML = this.getHeaderHTML(columns);
|
$('thead', this.header).innerHTML = this.getHeaderHTML(columns);
|
||||||
|
|
||||||
this.$filterRow = $('.data-table-row[data-is-filter]', this.header);
|
this.$filterRow = $('.data-table-row[data-is-filter]', this.header);
|
||||||
$.style(this.$filterRow, { display: 'none' });
|
if (this.$filterRow) {
|
||||||
|
$.style(this.$filterRow, { display: 'none' });
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// update data-attributes
|
// update data-attributes
|
||||||
$cols.map(($col, i) => {
|
$cols.map(($col, i) => {
|
||||||
@ -1441,7 +1478,7 @@ class ColumnManager {
|
|||||||
const dropdownItems = this.options.headerDropdown;
|
const dropdownItems = this.options.headerDropdown;
|
||||||
|
|
||||||
$.on(this.header, 'click', '.data-table-dropdown-list > div', (e, $item) => {
|
$.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 {
|
const {
|
||||||
index
|
index
|
||||||
} = $.data($item);
|
} = $.data($item);
|
||||||
@ -1463,7 +1500,7 @@ class ColumnManager {
|
|||||||
let isDragging = false;
|
let isDragging = false;
|
||||||
let $resizingCell, startWidth, startX;
|
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');
|
document.body.classList.add('data-table-resize');
|
||||||
const $cell = $handle.parentNode.parentNode;
|
const $cell = $handle.parentNode.parentNode;
|
||||||
$resizingCell = $cell;
|
$resizingCell = $cell;
|
||||||
@ -1520,7 +1557,7 @@ class ColumnManager {
|
|||||||
$.off(document.body, 'mousemove', initialize);
|
$.off(document.body, 'mousemove', initialize);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const ready = $('.data-table-col', this.header);
|
const ready = $('.data-table-cell', this.header);
|
||||||
if (!ready) return;
|
if (!ready) return;
|
||||||
|
|
||||||
const $parent = $('.data-table-row', this.header);
|
const $parent = $('.data-table-row', this.header);
|
||||||
@ -1550,8 +1587,8 @@ class ColumnManager {
|
|||||||
|
|
||||||
bindSortColumn() {
|
bindSortColumn() {
|
||||||
|
|
||||||
$.on(this.header, 'click', '.data-table-col .column-title', (e, span) => {
|
$.on(this.header, 'click', '.data-table-cell .column-title', (e, span) => {
|
||||||
const $cell = span.closest('.data-table-col');
|
const $cell = span.closest('.data-table-cell');
|
||||||
let {
|
let {
|
||||||
colIndex,
|
colIndex,
|
||||||
sortOrder
|
sortOrder
|
||||||
@ -1565,7 +1602,7 @@ class ColumnManager {
|
|||||||
|
|
||||||
// reset sort indicator
|
// reset sort indicator
|
||||||
$('.sort-indicator', this.header).textContent = '';
|
$('.sort-indicator', this.header).textContent = '';
|
||||||
$.each('.data-table-col', this.header).map($cell => {
|
$.each('.data-table-cell', this.header).map($cell => {
|
||||||
$.data($cell, {
|
$.data($cell, {
|
||||||
sortOrder: 'none'
|
sortOrder: 'none'
|
||||||
});
|
});
|
||||||
@ -1666,7 +1703,7 @@ class ColumnManager {
|
|||||||
bindFilter() {
|
bindFilter() {
|
||||||
if (!this.options.enableInlineFilters) return;
|
if (!this.options.enableInlineFilters) return;
|
||||||
const handler = e => {
|
const handler = e => {
|
||||||
const $filterCell = $.closest('.data-table-col', e.target);
|
const $filterCell = $.closest('.data-table-cell', e.target);
|
||||||
const {
|
const {
|
||||||
colIndex
|
colIndex
|
||||||
} = $.data($filterCell);
|
} = $.data($filterCell);
|
||||||
@ -1677,14 +1714,8 @@ class ColumnManager {
|
|||||||
rowsToHide,
|
rowsToHide,
|
||||||
rowsToShow
|
rowsToShow
|
||||||
}) => {
|
}) => {
|
||||||
rowsToHide.map(rowIndex => {
|
this.rowmanager.hideRows(rowsToHide);
|
||||||
const $tr = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
|
this.rowmanager.showRows(rowsToShow);
|
||||||
$tr.classList.add('hide');
|
|
||||||
});
|
|
||||||
rowsToShow.map(rowIndex => {
|
|
||||||
const $tr = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
|
|
||||||
$tr.classList.remove('hide');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
$.on(this.header, 'keydown', '.data-table-filter', debounce$2(handler, 300));
|
$.on(this.header, 'keydown', '.data-table-filter', debounce$2(handler, 300));
|
||||||
@ -1755,7 +1786,7 @@ class ColumnManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getHeaderCell$(colIndex) {
|
getHeaderCell$(colIndex) {
|
||||||
return $(`.data-table-col[data-col-index="${colIndex}"]`, this.header);
|
return $(`.data-table-cell[data-col-index="${colIndex}"]`, this.header);
|
||||||
}
|
}
|
||||||
|
|
||||||
getLastColumnIndex() {
|
getLastColumnIndex() {
|
||||||
@ -1802,6 +1833,7 @@ class CellManager {
|
|||||||
this.bindKeyboardSelection();
|
this.bindKeyboardSelection();
|
||||||
this.bindCopyCellContents();
|
this.bindCopyCellContents();
|
||||||
this.bindMouseEvents();
|
this.bindMouseEvents();
|
||||||
|
this.bindTreeEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
bindFocusCell() {
|
bindFocusCell() {
|
||||||
@ -1811,7 +1843,7 @@ class CellManager {
|
|||||||
bindEditCell() {
|
bindEditCell() {
|
||||||
this.$editingCell = null;
|
this.$editingCell = null;
|
||||||
|
|
||||||
$.on(this.bodyScrollable, 'dblclick', '.data-table-col', (e, cell) => {
|
$.on(this.bodyScrollable, 'dblclick', '.data-table-cell', (e, cell) => {
|
||||||
this.activateEditing(cell);
|
this.activateEditing(cell);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1888,7 +1920,7 @@ class CellManager {
|
|||||||
|
|
||||||
if (this.options.enableInlineFilters) {
|
if (this.options.enableInlineFilters) {
|
||||||
this.keyboard.on('ctrl+f', (e) => {
|
this.keyboard.on('ctrl+f', (e) => {
|
||||||
const $cell = $.closest('.data-table-col', e.target);
|
const $cell = $.closest('.data-table-cell', e.target);
|
||||||
let {
|
let {
|
||||||
colIndex
|
colIndex
|
||||||
} = $.data($cell);
|
} = $.data($cell);
|
||||||
@ -1931,7 +1963,7 @@ class CellManager {
|
|||||||
bindMouseEvents() {
|
bindMouseEvents() {
|
||||||
let mouseDown = null;
|
let mouseDown = null;
|
||||||
|
|
||||||
$.on(this.bodyScrollable, 'mousedown', '.data-table-col', (e) => {
|
$.on(this.bodyScrollable, 'mousedown', '.data-table-cell', (e) => {
|
||||||
mouseDown = true;
|
mouseDown = true;
|
||||||
this.focusCell($(e.delegatedTarget));
|
this.focusCell($(e.delegatedTarget));
|
||||||
});
|
});
|
||||||
@ -1945,7 +1977,39 @@ class CellManager {
|
|||||||
this.selectArea($(e.delegatedTarget));
|
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, {
|
focusCell($cell, {
|
||||||
@ -1995,8 +2059,8 @@ class CellManager {
|
|||||||
rowIndex
|
rowIndex
|
||||||
} = $.data($cell);
|
} = $.data($cell);
|
||||||
const _colIndex = this.datamanager.getColumnIndexById('_rowIndex');
|
const _colIndex = this.datamanager.getColumnIndexById('_rowIndex');
|
||||||
const colHeaderSelector = `.data-table-header .data-table-col[data-col-index="${colIndex}"]`;
|
const colHeaderSelector = `.data-table-header .data-table-cell[data-col-index="${colIndex}"]`;
|
||||||
const rowHeaderSelector = `.data-table-col[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
|
const rowHeaderSelector = `.data-table-cell[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
|
||||||
|
|
||||||
if (this.lastHeaders) {
|
if (this.lastHeaders) {
|
||||||
$.removeStyle(this.lastHeaders, 'backgroundColor');
|
$.removeStyle(this.lastHeaders, 'backgroundColor');
|
||||||
@ -2122,7 +2186,7 @@ class CellManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clearSelection() {
|
clearSelection() {
|
||||||
$.each('.data-table-col.highlight', this.bodyScrollable)
|
$.each('.data-table-cell.highlight', this.bodyScrollable)
|
||||||
.map(cell => cell.classList.remove('highlight'));
|
.map(cell => cell.classList.remove('highlight'));
|
||||||
|
|
||||||
this.$selectionCursor = null;
|
this.$selectionCursor = null;
|
||||||
@ -2394,15 +2458,16 @@ class CellManager {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<td class="data-table-col noselect" ${dataAttr} tabindex="0">
|
<td class="data-table-cell noselect" ${dataAttr} tabindex="0">
|
||||||
${this.getCellContent(cell)}
|
${this.getCellContent(cell)}
|
||||||
</td>
|
</td>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getCellContent(cell) {
|
getCellContent(cell) {
|
||||||
const {
|
const {
|
||||||
isHeader
|
isHeader,
|
||||||
|
isFilter
|
||||||
} = cell;
|
} = cell;
|
||||||
|
|
||||||
const editable = !isHeader && cell.editable !== false;
|
const editable = !isHeader && cell.editable !== false;
|
||||||
@ -2418,21 +2483,35 @@ class CellManager {
|
|||||||
const dropdown = hasDropdown ? `<div class="data-table-dropdown">${getDropdownHTML()}</div>` : '';
|
const dropdown = hasDropdown ? `<div class="data-table-dropdown">${getDropdownHTML()}</div>` : '';
|
||||||
|
|
||||||
let contentHTML;
|
let contentHTML;
|
||||||
if (cell.isHeader || cell.isFilter || !cell.column.format) {
|
if (isHeader || isFilter || !cell.column.format) {
|
||||||
contentHTML = cell.content;
|
contentHTML = cell.content;
|
||||||
} else {
|
} else {
|
||||||
contentHTML = cell.column.format(cell.content, cell);
|
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 `
|
return `
|
||||||
<div class="content ellipsis">
|
<div class="content ellipsis">
|
||||||
${(contentHTML)}
|
${contentHTML}
|
||||||
${sortIndicator}
|
${sortIndicator}
|
||||||
${resizeColumn}
|
${resizeColumn}
|
||||||
${dropdown}
|
${dropdown}
|
||||||
</div>
|
</div>
|
||||||
${editCellHTML}
|
${editCellHTML}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getEditCellHTML() {
|
getEditCellHTML() {
|
||||||
@ -2442,7 +2521,7 @@ class CellManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cellSelector(colIndex, rowIndex) {
|
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
|
// map of checked rows
|
||||||
this.checkMap = [];
|
this.checkMap = [];
|
||||||
|
|
||||||
$.on(this.wrapper, 'click', '.data-table-col[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
|
$.on(this.wrapper, 'click', '.data-table-cell[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
|
||||||
const $cell = $checkbox.closest('.data-table-col');
|
const $cell = $checkbox.closest('.data-table-cell');
|
||||||
const {
|
const {
|
||||||
rowIndex,
|
rowIndex,
|
||||||
isHeader
|
isHeader
|
||||||
@ -2529,7 +2608,7 @@ class RowManager {
|
|||||||
checkRow(rowIndex, toggle) {
|
checkRow(rowIndex, toggle) {
|
||||||
const value = toggle ? 1 : 0;
|
const value = toggle ? 1 : 0;
|
||||||
const selector = rowIndex =>
|
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
|
// update internal map
|
||||||
this.checkMap[rowIndex] = value;
|
this.checkMap[rowIndex] = value;
|
||||||
// set checkbox value explicitly
|
// set checkbox value explicitly
|
||||||
@ -2551,7 +2630,7 @@ class RowManager {
|
|||||||
this.checkMap = [];
|
this.checkMap = [];
|
||||||
}
|
}
|
||||||
// set checkbox value
|
// 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 => {
|
.map(input => {
|
||||||
input.checked = toggle;
|
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) {
|
getRow$(rowIndex) {
|
||||||
return $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
|
return $(this.selector(rowIndex), this.bodyScrollable);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTotalRows() {
|
getTotalRows() {
|
||||||
@ -2663,6 +2766,10 @@ class RowManager {
|
|||||||
const dataAttr = makeDataAttributeString(props);
|
const dataAttr = makeDataAttributeString(props);
|
||||||
return `<input class="data-table-filter input-style" type="text" ${dataAttr} />`;
|
return `<input class="data-table-filter input-style" type="text" ${dataAttr} />`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selector(rowIndex) {
|
||||||
|
return `.data-table-row[data-row-index="${rowIndex}"]`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BodyRenderer {
|
class BodyRenderer {
|
||||||
@ -2686,7 +2793,7 @@ class BodyRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderBodyHTML() {
|
renderBodyHTML() {
|
||||||
const rows = this.datamanager.getRows();
|
const rows = this.datamanager.getRowsForView();
|
||||||
|
|
||||||
this.bodyScrollable.innerHTML = `
|
this.bodyScrollable.innerHTML = `
|
||||||
<table class="data-table-body">
|
<table class="data-table-body">
|
||||||
@ -2699,7 +2806,7 @@ class BodyRenderer {
|
|||||||
|
|
||||||
renderBodyWithClusterize() {
|
renderBodyWithClusterize() {
|
||||||
// first page
|
// first page
|
||||||
const rows = this.datamanager.getRows(0, 20);
|
const rows = this.datamanager.getRowsForView(0, 20);
|
||||||
const initialData = this.getDataForClusterize(rows);
|
const initialData = this.getDataForClusterize(rows);
|
||||||
|
|
||||||
if (!this.clusterize) {
|
if (!this.clusterize) {
|
||||||
@ -2743,7 +2850,7 @@ class BodyRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
appendRemainingData() {
|
appendRemainingData() {
|
||||||
const rows = this.datamanager.getRows(20);
|
const rows = this.datamanager.getRowsForView(20);
|
||||||
const data = this.getDataForClusterize(rows);
|
const data = this.getDataForClusterize(rows);
|
||||||
this.clusterize.append(data);
|
this.clusterize.append(data);
|
||||||
}
|
}
|
||||||
@ -2860,7 +2967,7 @@ class Style {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupMinWidth() {
|
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 width = $.style($('.content', col), 'width');
|
||||||
const {
|
const {
|
||||||
colIndex
|
colIndex
|
||||||
@ -2878,7 +2985,7 @@ class Style {
|
|||||||
if (!$('.data-table-row')) return;
|
if (!$('.data-table-row')) return;
|
||||||
|
|
||||||
// set initial width as naturally calculated by table's first row
|
// 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 {
|
const {
|
||||||
colIndex
|
colIndex
|
||||||
} = $.data($cell);
|
} = $.data($cell);
|
||||||
@ -2927,7 +3034,7 @@ class Style {
|
|||||||
setDefaultCellHeight() {
|
setDefaultCellHeight() {
|
||||||
if (this.__cellHeightSet) return;
|
if (this.__cellHeightSet) return;
|
||||||
const height = this.options.cellHeight ||
|
const height = this.options.cellHeight ||
|
||||||
$.style($('.data-table-col', this.instance.datatableWrapper), 'height');
|
$.style($('.data-table-cell', this.instance.datatableWrapper), 'height');
|
||||||
if (height) {
|
if (height) {
|
||||||
this.setCellHeight(height);
|
this.setCellHeight(height);
|
||||||
this.__cellHeightSet = true;
|
this.__cellHeightSet = true;
|
||||||
@ -2935,10 +3042,10 @@ class Style {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setCellHeight(height) {
|
setCellHeight(height) {
|
||||||
this.setStyle('.data-table-col .content', {
|
this.setStyle('.data-table-cell .content', {
|
||||||
height: height + 'px'
|
height: height + 'px'
|
||||||
});
|
});
|
||||||
this.setStyle('.data-table-col .edit-cell', {
|
this.setStyle('.data-table-cell .edit-cell', {
|
||||||
height: height + 'px'
|
height: height + 'px'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -2987,7 +3094,7 @@ class Style {
|
|||||||
getColumnHeaderElement(colIndex) {
|
getColumnHeaderElement(colIndex) {
|
||||||
colIndex = +colIndex;
|
colIndex = +colIndex;
|
||||||
if (colIndex < 0) return null;
|
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) {
|
getRowIndexColumnWidth(baseWidth) {
|
||||||
|
|||||||
44
dist/frappe-datatable.css
vendored
44
dist/frappe-datatable.css
vendored
@ -178,33 +178,33 @@
|
|||||||
background-color: #f5f7fa;
|
background-color: #f5f7fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-header .data-table-col.remove-column {
|
.data-table-header .data-table-cell.remove-column {
|
||||||
background-color: #FD8B8B;
|
background-color: #FD8B8B;
|
||||||
-webkit-transition: 300ms background-color ease-in-out;
|
-webkit-transition: 300ms background-color ease-in-out;
|
||||||
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;
|
background-color: #f5f7fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col {
|
.data-table-cell {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col .content {
|
.data-table-cell .content {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col .content.ellipsis {
|
.data-table-cell .content.ellipsis {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col .edit-cell {
|
.data-table-cell .edit-cell {
|
||||||
display: none;
|
display: none;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
@ -213,31 +213,51 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col.selected .content {
|
.data-table-cell.selected .content {
|
||||||
border: 2px solid rgb(82, 146, 247);
|
border: 2px solid rgb(82, 146, 247);
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col.editing .content {
|
.data-table-cell.editing .content {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col.editing .edit-cell {
|
.data-table-cell.editing .edit-cell {
|
||||||
border: 2px solid rgb(82, 146, 247);
|
border: 2px solid rgb(82, 146, 247);
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col.highlight {
|
.data-table-cell.highlight {
|
||||||
background-color: #f5f7fa;
|
background-color: #f5f7fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col:hover .column-resizer {
|
.data-table-cell:hover .column-resizer {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col:hover .data-table-dropdown-toggle {
|
.data-table-cell:hover .data-table-dropdown-toggle {
|
||||||
display: block;
|
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 {
|
.data-table-row.row-highlight {
|
||||||
background-color: #f5f7fa;
|
background-color: #f5f7fa;
|
||||||
}
|
}
|
||||||
|
|||||||
269
dist/frappe-datatable.js
vendored
269
dist/frappe-datatable.js
vendored
@ -846,6 +846,7 @@ class DataManager {
|
|||||||
|
|
||||||
this.prepareColumns();
|
this.prepareColumns();
|
||||||
this.prepareRows();
|
this.prepareRows();
|
||||||
|
this.prepareRowView();
|
||||||
|
|
||||||
this.prepareNumericColumns();
|
this.prepareNumericColumns();
|
||||||
}
|
}
|
||||||
@ -963,6 +964,9 @@ class DataManager {
|
|||||||
const index = this._getNextRowCount();
|
const index = this._getNextRowCount();
|
||||||
|
|
||||||
let row = [];
|
let row = [];
|
||||||
|
let meta = {
|
||||||
|
rowIndex: index
|
||||||
|
};
|
||||||
|
|
||||||
if (Array.isArray(d)) {
|
if (Array.isArray(d)) {
|
||||||
// row is an array
|
// row is an array
|
||||||
@ -989,17 +993,25 @@ class DataManager {
|
|||||||
row.push(d[col.id]);
|
row.push(d[col.id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meta.indent = d.indent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.prepareRow(row, {
|
return this.prepareRow(row, meta);
|
||||||
rowIndex: index
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = {
|
const baseRowCell = {
|
||||||
rowIndex: props.rowIndex
|
rowIndex: meta.rowIndex,
|
||||||
|
indent: meta.indent
|
||||||
};
|
};
|
||||||
|
|
||||||
row = row
|
row = row
|
||||||
@ -1007,7 +1019,7 @@ class DataManager {
|
|||||||
.map(cell => Object.assign({}, baseRowCell, cell));
|
.map(cell => Object.assign({}, baseRowCell, cell));
|
||||||
|
|
||||||
// monkey patched in array object
|
// monkey patched in array object
|
||||||
row.meta = props;
|
row.meta = meta;
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1062,28 +1074,28 @@ class DataManager {
|
|||||||
(this.currentSort.sortOrder === 'asc' && sortOrder === 'desc') ||
|
(this.currentSort.sortOrder === 'asc' && sortOrder === 'desc') ||
|
||||||
(this.currentSort.sortOrder === 'desc' && sortOrder === 'asc')
|
(this.currentSort.sortOrder === 'desc' && sortOrder === 'asc')
|
||||||
) {
|
) {
|
||||||
this.reverseArray(this.rows);
|
this.reverseArray(this.rowViewOrder);
|
||||||
this.currentSort.sortOrder = sortOrder;
|
this.currentSort.sortOrder = sortOrder;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.rows.sort((a, b) => {
|
this.rowViewOrder.sort((a, b) => {
|
||||||
const _aIndex = a[0].rowIndex;
|
const aIndex = a;
|
||||||
const _bIndex = b[0].rowIndex;
|
const bIndex = b;
|
||||||
const _a = a[colIndex].content;
|
const aContent = this.getCell(colIndex, a).content;
|
||||||
const _b = b[colIndex].content;
|
const bContent = this.getCell(colIndex, b).content;
|
||||||
|
|
||||||
if (sortOrder === 'none') {
|
if (sortOrder === 'none') {
|
||||||
return _aIndex - _bIndex;
|
return aIndex - bIndex;
|
||||||
} else if (sortOrder === 'asc') {
|
} else if (sortOrder === 'asc') {
|
||||||
if (_a < _b) return -1;
|
if (aContent < bContent) return -1;
|
||||||
if (_a > _b) return 1;
|
if (aContent > bContent) return 1;
|
||||||
if (_a === _b) return 0;
|
if (aContent === bContent) return 0;
|
||||||
} else if (sortOrder === 'desc') {
|
} else if (sortOrder === 'desc') {
|
||||||
if (_a < _b) return 1;
|
if (aContent < bContent) return 1;
|
||||||
if (_a > _b) return -1;
|
if (aContent > bContent) return -1;
|
||||||
if (_a === _b) return 0;
|
if (aContent === bContent) return 0;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
@ -1092,11 +1104,9 @@ class DataManager {
|
|||||||
// update row index
|
// update row index
|
||||||
const srNoColIndex = this.getColumnIndexById('_rowIndex');
|
const srNoColIndex = this.getColumnIndexById('_rowIndex');
|
||||||
this.rows.forEach((row, index) => {
|
this.rows.forEach((row, index) => {
|
||||||
row.forEach(cell => {
|
const viewIndex = this.rowViewOrder.indexOf(index);
|
||||||
if (cell.colIndex === srNoColIndex) {
|
const cell = row[srNoColIndex];
|
||||||
cell.content = (index + 1) + '';
|
cell.content = (viewIndex + 1) + '';
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1259,6 +1269,11 @@ class DataManager {
|
|||||||
return this.rows.slice(start, end);
|
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) {
|
getColumns(skipStandardColumns) {
|
||||||
let columns = this.columns;
|
let columns = this.columns;
|
||||||
|
|
||||||
@ -1298,13 +1313,33 @@ class DataManager {
|
|||||||
|
|
||||||
getRow(rowIndex) {
|
getRow(rowIndex) {
|
||||||
rowIndex = +rowIndex;
|
rowIndex = +rowIndex;
|
||||||
return this.rows.find(row => row[0].rowIndex === rowIndex);
|
return this.rows[rowIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
getCell(colIndex, rowIndex) {
|
getCell(colIndex, rowIndex) {
|
||||||
rowIndex = +rowIndex;
|
rowIndex = +rowIndex;
|
||||||
colIndex = +colIndex;
|
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() {
|
get() {
|
||||||
@ -1364,11 +1399,11 @@ class ColumnManager {
|
|||||||
|
|
||||||
refreshHeader() {
|
refreshHeader() {
|
||||||
const columns = this.datamanager.getColumns();
|
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 =
|
const refreshHTML =
|
||||||
// first init
|
// first init
|
||||||
!$('.data-table-col', this.header) ||
|
!$('.data-table-cell', this.header) ||
|
||||||
// deleted column
|
// deleted column
|
||||||
columns.length < $cols.length;
|
columns.length < $cols.length;
|
||||||
|
|
||||||
@ -1377,7 +1412,9 @@ class ColumnManager {
|
|||||||
$('thead', this.header).innerHTML = this.getHeaderHTML(columns);
|
$('thead', this.header).innerHTML = this.getHeaderHTML(columns);
|
||||||
|
|
||||||
this.$filterRow = $('.data-table-row[data-is-filter]', this.header);
|
this.$filterRow = $('.data-table-row[data-is-filter]', this.header);
|
||||||
$.style(this.$filterRow, { display: 'none' });
|
if (this.$filterRow) {
|
||||||
|
$.style(this.$filterRow, { display: 'none' });
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// update data-attributes
|
// update data-attributes
|
||||||
$cols.map(($col, i) => {
|
$cols.map(($col, i) => {
|
||||||
@ -1440,7 +1477,7 @@ class ColumnManager {
|
|||||||
const dropdownItems = this.options.headerDropdown;
|
const dropdownItems = this.options.headerDropdown;
|
||||||
|
|
||||||
$.on(this.header, 'click', '.data-table-dropdown-list > div', (e, $item) => {
|
$.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 {
|
const {
|
||||||
index
|
index
|
||||||
} = $.data($item);
|
} = $.data($item);
|
||||||
@ -1462,7 +1499,7 @@ class ColumnManager {
|
|||||||
let isDragging = false;
|
let isDragging = false;
|
||||||
let $resizingCell, startWidth, startX;
|
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');
|
document.body.classList.add('data-table-resize');
|
||||||
const $cell = $handle.parentNode.parentNode;
|
const $cell = $handle.parentNode.parentNode;
|
||||||
$resizingCell = $cell;
|
$resizingCell = $cell;
|
||||||
@ -1519,7 +1556,7 @@ class ColumnManager {
|
|||||||
$.off(document.body, 'mousemove', initialize);
|
$.off(document.body, 'mousemove', initialize);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const ready = $('.data-table-col', this.header);
|
const ready = $('.data-table-cell', this.header);
|
||||||
if (!ready) return;
|
if (!ready) return;
|
||||||
|
|
||||||
const $parent = $('.data-table-row', this.header);
|
const $parent = $('.data-table-row', this.header);
|
||||||
@ -1549,8 +1586,8 @@ class ColumnManager {
|
|||||||
|
|
||||||
bindSortColumn() {
|
bindSortColumn() {
|
||||||
|
|
||||||
$.on(this.header, 'click', '.data-table-col .column-title', (e, span) => {
|
$.on(this.header, 'click', '.data-table-cell .column-title', (e, span) => {
|
||||||
const $cell = span.closest('.data-table-col');
|
const $cell = span.closest('.data-table-cell');
|
||||||
let {
|
let {
|
||||||
colIndex,
|
colIndex,
|
||||||
sortOrder
|
sortOrder
|
||||||
@ -1564,7 +1601,7 @@ class ColumnManager {
|
|||||||
|
|
||||||
// reset sort indicator
|
// reset sort indicator
|
||||||
$('.sort-indicator', this.header).textContent = '';
|
$('.sort-indicator', this.header).textContent = '';
|
||||||
$.each('.data-table-col', this.header).map($cell => {
|
$.each('.data-table-cell', this.header).map($cell => {
|
||||||
$.data($cell, {
|
$.data($cell, {
|
||||||
sortOrder: 'none'
|
sortOrder: 'none'
|
||||||
});
|
});
|
||||||
@ -1665,7 +1702,7 @@ class ColumnManager {
|
|||||||
bindFilter() {
|
bindFilter() {
|
||||||
if (!this.options.enableInlineFilters) return;
|
if (!this.options.enableInlineFilters) return;
|
||||||
const handler = e => {
|
const handler = e => {
|
||||||
const $filterCell = $.closest('.data-table-col', e.target);
|
const $filterCell = $.closest('.data-table-cell', e.target);
|
||||||
const {
|
const {
|
||||||
colIndex
|
colIndex
|
||||||
} = $.data($filterCell);
|
} = $.data($filterCell);
|
||||||
@ -1676,14 +1713,8 @@ class ColumnManager {
|
|||||||
rowsToHide,
|
rowsToHide,
|
||||||
rowsToShow
|
rowsToShow
|
||||||
}) => {
|
}) => {
|
||||||
rowsToHide.map(rowIndex => {
|
this.rowmanager.hideRows(rowsToHide);
|
||||||
const $tr = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
|
this.rowmanager.showRows(rowsToShow);
|
||||||
$tr.classList.add('hide');
|
|
||||||
});
|
|
||||||
rowsToShow.map(rowIndex => {
|
|
||||||
const $tr = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
|
|
||||||
$tr.classList.remove('hide');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
$.on(this.header, 'keydown', '.data-table-filter', debounce$2(handler, 300));
|
$.on(this.header, 'keydown', '.data-table-filter', debounce$2(handler, 300));
|
||||||
@ -1754,7 +1785,7 @@ class ColumnManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getHeaderCell$(colIndex) {
|
getHeaderCell$(colIndex) {
|
||||||
return $(`.data-table-col[data-col-index="${colIndex}"]`, this.header);
|
return $(`.data-table-cell[data-col-index="${colIndex}"]`, this.header);
|
||||||
}
|
}
|
||||||
|
|
||||||
getLastColumnIndex() {
|
getLastColumnIndex() {
|
||||||
@ -1801,6 +1832,7 @@ class CellManager {
|
|||||||
this.bindKeyboardSelection();
|
this.bindKeyboardSelection();
|
||||||
this.bindCopyCellContents();
|
this.bindCopyCellContents();
|
||||||
this.bindMouseEvents();
|
this.bindMouseEvents();
|
||||||
|
this.bindTreeEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
bindFocusCell() {
|
bindFocusCell() {
|
||||||
@ -1810,7 +1842,7 @@ class CellManager {
|
|||||||
bindEditCell() {
|
bindEditCell() {
|
||||||
this.$editingCell = null;
|
this.$editingCell = null;
|
||||||
|
|
||||||
$.on(this.bodyScrollable, 'dblclick', '.data-table-col', (e, cell) => {
|
$.on(this.bodyScrollable, 'dblclick', '.data-table-cell', (e, cell) => {
|
||||||
this.activateEditing(cell);
|
this.activateEditing(cell);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1887,7 +1919,7 @@ class CellManager {
|
|||||||
|
|
||||||
if (this.options.enableInlineFilters) {
|
if (this.options.enableInlineFilters) {
|
||||||
this.keyboard.on('ctrl+f', (e) => {
|
this.keyboard.on('ctrl+f', (e) => {
|
||||||
const $cell = $.closest('.data-table-col', e.target);
|
const $cell = $.closest('.data-table-cell', e.target);
|
||||||
let {
|
let {
|
||||||
colIndex
|
colIndex
|
||||||
} = $.data($cell);
|
} = $.data($cell);
|
||||||
@ -1930,7 +1962,7 @@ class CellManager {
|
|||||||
bindMouseEvents() {
|
bindMouseEvents() {
|
||||||
let mouseDown = null;
|
let mouseDown = null;
|
||||||
|
|
||||||
$.on(this.bodyScrollable, 'mousedown', '.data-table-col', (e) => {
|
$.on(this.bodyScrollable, 'mousedown', '.data-table-cell', (e) => {
|
||||||
mouseDown = true;
|
mouseDown = true;
|
||||||
this.focusCell($(e.delegatedTarget));
|
this.focusCell($(e.delegatedTarget));
|
||||||
});
|
});
|
||||||
@ -1944,7 +1976,39 @@ class CellManager {
|
|||||||
this.selectArea($(e.delegatedTarget));
|
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, {
|
focusCell($cell, {
|
||||||
@ -1994,8 +2058,8 @@ class CellManager {
|
|||||||
rowIndex
|
rowIndex
|
||||||
} = $.data($cell);
|
} = $.data($cell);
|
||||||
const _colIndex = this.datamanager.getColumnIndexById('_rowIndex');
|
const _colIndex = this.datamanager.getColumnIndexById('_rowIndex');
|
||||||
const colHeaderSelector = `.data-table-header .data-table-col[data-col-index="${colIndex}"]`;
|
const colHeaderSelector = `.data-table-header .data-table-cell[data-col-index="${colIndex}"]`;
|
||||||
const rowHeaderSelector = `.data-table-col[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
|
const rowHeaderSelector = `.data-table-cell[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
|
||||||
|
|
||||||
if (this.lastHeaders) {
|
if (this.lastHeaders) {
|
||||||
$.removeStyle(this.lastHeaders, 'backgroundColor');
|
$.removeStyle(this.lastHeaders, 'backgroundColor');
|
||||||
@ -2121,7 +2185,7 @@ class CellManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clearSelection() {
|
clearSelection() {
|
||||||
$.each('.data-table-col.highlight', this.bodyScrollable)
|
$.each('.data-table-cell.highlight', this.bodyScrollable)
|
||||||
.map(cell => cell.classList.remove('highlight'));
|
.map(cell => cell.classList.remove('highlight'));
|
||||||
|
|
||||||
this.$selectionCursor = null;
|
this.$selectionCursor = null;
|
||||||
@ -2393,15 +2457,16 @@ class CellManager {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<td class="data-table-col noselect" ${dataAttr} tabindex="0">
|
<td class="data-table-cell noselect" ${dataAttr} tabindex="0">
|
||||||
${this.getCellContent(cell)}
|
${this.getCellContent(cell)}
|
||||||
</td>
|
</td>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getCellContent(cell) {
|
getCellContent(cell) {
|
||||||
const {
|
const {
|
||||||
isHeader
|
isHeader,
|
||||||
|
isFilter
|
||||||
} = cell;
|
} = cell;
|
||||||
|
|
||||||
const editable = !isHeader && cell.editable !== false;
|
const editable = !isHeader && cell.editable !== false;
|
||||||
@ -2417,21 +2482,35 @@ class CellManager {
|
|||||||
const dropdown = hasDropdown ? `<div class="data-table-dropdown">${getDropdownHTML()}</div>` : '';
|
const dropdown = hasDropdown ? `<div class="data-table-dropdown">${getDropdownHTML()}</div>` : '';
|
||||||
|
|
||||||
let contentHTML;
|
let contentHTML;
|
||||||
if (cell.isHeader || cell.isFilter || !cell.column.format) {
|
if (isHeader || isFilter || !cell.column.format) {
|
||||||
contentHTML = cell.content;
|
contentHTML = cell.content;
|
||||||
} else {
|
} else {
|
||||||
contentHTML = cell.column.format(cell.content, cell);
|
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 `
|
return `
|
||||||
<div class="content ellipsis">
|
<div class="content ellipsis">
|
||||||
${(contentHTML)}
|
${contentHTML}
|
||||||
${sortIndicator}
|
${sortIndicator}
|
||||||
${resizeColumn}
|
${resizeColumn}
|
||||||
${dropdown}
|
${dropdown}
|
||||||
</div>
|
</div>
|
||||||
${editCellHTML}
|
${editCellHTML}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getEditCellHTML() {
|
getEditCellHTML() {
|
||||||
@ -2441,7 +2520,7 @@ class CellManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cellSelector(colIndex, rowIndex) {
|
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
|
// map of checked rows
|
||||||
this.checkMap = [];
|
this.checkMap = [];
|
||||||
|
|
||||||
$.on(this.wrapper, 'click', '.data-table-col[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
|
$.on(this.wrapper, 'click', '.data-table-cell[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
|
||||||
const $cell = $checkbox.closest('.data-table-col');
|
const $cell = $checkbox.closest('.data-table-cell');
|
||||||
const {
|
const {
|
||||||
rowIndex,
|
rowIndex,
|
||||||
isHeader
|
isHeader
|
||||||
@ -2528,7 +2607,7 @@ class RowManager {
|
|||||||
checkRow(rowIndex, toggle) {
|
checkRow(rowIndex, toggle) {
|
||||||
const value = toggle ? 1 : 0;
|
const value = toggle ? 1 : 0;
|
||||||
const selector = rowIndex =>
|
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
|
// update internal map
|
||||||
this.checkMap[rowIndex] = value;
|
this.checkMap[rowIndex] = value;
|
||||||
// set checkbox value explicitly
|
// set checkbox value explicitly
|
||||||
@ -2550,7 +2629,7 @@ class RowManager {
|
|||||||
this.checkMap = [];
|
this.checkMap = [];
|
||||||
}
|
}
|
||||||
// set checkbox value
|
// 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 => {
|
.map(input => {
|
||||||
input.checked = toggle;
|
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) {
|
getRow$(rowIndex) {
|
||||||
return $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
|
return $(this.selector(rowIndex), this.bodyScrollable);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTotalRows() {
|
getTotalRows() {
|
||||||
@ -2662,6 +2765,10 @@ class RowManager {
|
|||||||
const dataAttr = makeDataAttributeString(props);
|
const dataAttr = makeDataAttributeString(props);
|
||||||
return `<input class="data-table-filter input-style" type="text" ${dataAttr} />`;
|
return `<input class="data-table-filter input-style" type="text" ${dataAttr} />`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selector(rowIndex) {
|
||||||
|
return `.data-table-row[data-row-index="${rowIndex}"]`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BodyRenderer {
|
class BodyRenderer {
|
||||||
@ -2685,7 +2792,7 @@ class BodyRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderBodyHTML() {
|
renderBodyHTML() {
|
||||||
const rows = this.datamanager.getRows();
|
const rows = this.datamanager.getRowsForView();
|
||||||
|
|
||||||
this.bodyScrollable.innerHTML = `
|
this.bodyScrollable.innerHTML = `
|
||||||
<table class="data-table-body">
|
<table class="data-table-body">
|
||||||
@ -2698,7 +2805,7 @@ class BodyRenderer {
|
|||||||
|
|
||||||
renderBodyWithClusterize() {
|
renderBodyWithClusterize() {
|
||||||
// first page
|
// first page
|
||||||
const rows = this.datamanager.getRows(0, 20);
|
const rows = this.datamanager.getRowsForView(0, 20);
|
||||||
const initialData = this.getDataForClusterize(rows);
|
const initialData = this.getDataForClusterize(rows);
|
||||||
|
|
||||||
if (!this.clusterize) {
|
if (!this.clusterize) {
|
||||||
@ -2742,7 +2849,7 @@ class BodyRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
appendRemainingData() {
|
appendRemainingData() {
|
||||||
const rows = this.datamanager.getRows(20);
|
const rows = this.datamanager.getRowsForView(20);
|
||||||
const data = this.getDataForClusterize(rows);
|
const data = this.getDataForClusterize(rows);
|
||||||
this.clusterize.append(data);
|
this.clusterize.append(data);
|
||||||
}
|
}
|
||||||
@ -2859,7 +2966,7 @@ class Style {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupMinWidth() {
|
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 width = $.style($('.content', col), 'width');
|
||||||
const {
|
const {
|
||||||
colIndex
|
colIndex
|
||||||
@ -2877,7 +2984,7 @@ class Style {
|
|||||||
if (!$('.data-table-row')) return;
|
if (!$('.data-table-row')) return;
|
||||||
|
|
||||||
// set initial width as naturally calculated by table's first row
|
// 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 {
|
const {
|
||||||
colIndex
|
colIndex
|
||||||
} = $.data($cell);
|
} = $.data($cell);
|
||||||
@ -2926,7 +3033,7 @@ class Style {
|
|||||||
setDefaultCellHeight() {
|
setDefaultCellHeight() {
|
||||||
if (this.__cellHeightSet) return;
|
if (this.__cellHeightSet) return;
|
||||||
const height = this.options.cellHeight ||
|
const height = this.options.cellHeight ||
|
||||||
$.style($('.data-table-col', this.instance.datatableWrapper), 'height');
|
$.style($('.data-table-cell', this.instance.datatableWrapper), 'height');
|
||||||
if (height) {
|
if (height) {
|
||||||
this.setCellHeight(height);
|
this.setCellHeight(height);
|
||||||
this.__cellHeightSet = true;
|
this.__cellHeightSet = true;
|
||||||
@ -2934,10 +3041,10 @@ class Style {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setCellHeight(height) {
|
setCellHeight(height) {
|
||||||
this.setStyle('.data-table-col .content', {
|
this.setStyle('.data-table-cell .content', {
|
||||||
height: height + 'px'
|
height: height + 'px'
|
||||||
});
|
});
|
||||||
this.setStyle('.data-table-col .edit-cell', {
|
this.setStyle('.data-table-cell .edit-cell', {
|
||||||
height: height + 'px'
|
height: height + 'px'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -2986,7 +3093,7 @@ class Style {
|
|||||||
getColumnHeaderElement(colIndex) {
|
getColumnHeaderElement(colIndex) {
|
||||||
colIndex = +colIndex;
|
colIndex = +colIndex;
|
||||||
if (colIndex < 0) return null;
|
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) {
|
getRowIndexColumnWidth(baseWidth) {
|
||||||
|
|||||||
@ -178,33 +178,33 @@
|
|||||||
background-color: #f5f7fa;
|
background-color: #f5f7fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-header .data-table-col.remove-column {
|
.data-table-header .data-table-cell.remove-column {
|
||||||
background-color: #FD8B8B;
|
background-color: #FD8B8B;
|
||||||
-webkit-transition: 300ms background-color ease-in-out;
|
-webkit-transition: 300ms background-color ease-in-out;
|
||||||
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;
|
background-color: #f5f7fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col {
|
.data-table-cell {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col .content {
|
.data-table-cell .content {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col .content.ellipsis {
|
.data-table-cell .content.ellipsis {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col .edit-cell {
|
.data-table-cell .edit-cell {
|
||||||
display: none;
|
display: none;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
@ -213,31 +213,51 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col.selected .content {
|
.data-table-cell.selected .content {
|
||||||
border: 2px solid rgb(82, 146, 247);
|
border: 2px solid rgb(82, 146, 247);
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col.editing .content {
|
.data-table-cell.editing .content {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col.editing .edit-cell {
|
.data-table-cell.editing .edit-cell {
|
||||||
border: 2px solid rgb(82, 146, 247);
|
border: 2px solid rgb(82, 146, 247);
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col.highlight {
|
.data-table-cell.highlight {
|
||||||
background-color: #f5f7fa;
|
background-color: #f5f7fa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col:hover .column-resizer {
|
.data-table-cell:hover .column-resizer {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col:hover .data-table-dropdown-toggle {
|
.data-table-cell:hover .data-table-dropdown-toggle {
|
||||||
display: block;
|
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 {
|
.data-table-row.row-highlight {
|
||||||
background-color: #f5f7fa;
|
background-color: #f5f7fa;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -846,6 +846,7 @@ class DataManager {
|
|||||||
|
|
||||||
this.prepareColumns();
|
this.prepareColumns();
|
||||||
this.prepareRows();
|
this.prepareRows();
|
||||||
|
this.prepareRowView();
|
||||||
|
|
||||||
this.prepareNumericColumns();
|
this.prepareNumericColumns();
|
||||||
}
|
}
|
||||||
@ -963,6 +964,9 @@ class DataManager {
|
|||||||
const index = this._getNextRowCount();
|
const index = this._getNextRowCount();
|
||||||
|
|
||||||
let row = [];
|
let row = [];
|
||||||
|
let meta = {
|
||||||
|
rowIndex: index
|
||||||
|
};
|
||||||
|
|
||||||
if (Array.isArray(d)) {
|
if (Array.isArray(d)) {
|
||||||
// row is an array
|
// row is an array
|
||||||
@ -989,17 +993,25 @@ class DataManager {
|
|||||||
row.push(d[col.id]);
|
row.push(d[col.id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meta.indent = d.indent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.prepareRow(row, {
|
return this.prepareRow(row, meta);
|
||||||
rowIndex: index
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = {
|
const baseRowCell = {
|
||||||
rowIndex: props.rowIndex
|
rowIndex: meta.rowIndex,
|
||||||
|
indent: meta.indent
|
||||||
};
|
};
|
||||||
|
|
||||||
row = row
|
row = row
|
||||||
@ -1007,7 +1019,7 @@ class DataManager {
|
|||||||
.map(cell => Object.assign({}, baseRowCell, cell));
|
.map(cell => Object.assign({}, baseRowCell, cell));
|
||||||
|
|
||||||
// monkey patched in array object
|
// monkey patched in array object
|
||||||
row.meta = props;
|
row.meta = meta;
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1062,28 +1074,28 @@ class DataManager {
|
|||||||
(this.currentSort.sortOrder === 'asc' && sortOrder === 'desc') ||
|
(this.currentSort.sortOrder === 'asc' && sortOrder === 'desc') ||
|
||||||
(this.currentSort.sortOrder === 'desc' && sortOrder === 'asc')
|
(this.currentSort.sortOrder === 'desc' && sortOrder === 'asc')
|
||||||
) {
|
) {
|
||||||
this.reverseArray(this.rows);
|
this.reverseArray(this.rowViewOrder);
|
||||||
this.currentSort.sortOrder = sortOrder;
|
this.currentSort.sortOrder = sortOrder;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.rows.sort((a, b) => {
|
this.rowViewOrder.sort((a, b) => {
|
||||||
const _aIndex = a[0].rowIndex;
|
const aIndex = a;
|
||||||
const _bIndex = b[0].rowIndex;
|
const bIndex = b;
|
||||||
const _a = a[colIndex].content;
|
const aContent = this.getCell(colIndex, a).content;
|
||||||
const _b = b[colIndex].content;
|
const bContent = this.getCell(colIndex, b).content;
|
||||||
|
|
||||||
if (sortOrder === 'none') {
|
if (sortOrder === 'none') {
|
||||||
return _aIndex - _bIndex;
|
return aIndex - bIndex;
|
||||||
} else if (sortOrder === 'asc') {
|
} else if (sortOrder === 'asc') {
|
||||||
if (_a < _b) return -1;
|
if (aContent < bContent) return -1;
|
||||||
if (_a > _b) return 1;
|
if (aContent > bContent) return 1;
|
||||||
if (_a === _b) return 0;
|
if (aContent === bContent) return 0;
|
||||||
} else if (sortOrder === 'desc') {
|
} else if (sortOrder === 'desc') {
|
||||||
if (_a < _b) return 1;
|
if (aContent < bContent) return 1;
|
||||||
if (_a > _b) return -1;
|
if (aContent > bContent) return -1;
|
||||||
if (_a === _b) return 0;
|
if (aContent === bContent) return 0;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
@ -1092,11 +1104,9 @@ class DataManager {
|
|||||||
// update row index
|
// update row index
|
||||||
const srNoColIndex = this.getColumnIndexById('_rowIndex');
|
const srNoColIndex = this.getColumnIndexById('_rowIndex');
|
||||||
this.rows.forEach((row, index) => {
|
this.rows.forEach((row, index) => {
|
||||||
row.forEach(cell => {
|
const viewIndex = this.rowViewOrder.indexOf(index);
|
||||||
if (cell.colIndex === srNoColIndex) {
|
const cell = row[srNoColIndex];
|
||||||
cell.content = (index + 1) + '';
|
cell.content = (viewIndex + 1) + '';
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1259,6 +1269,11 @@ class DataManager {
|
|||||||
return this.rows.slice(start, end);
|
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) {
|
getColumns(skipStandardColumns) {
|
||||||
let columns = this.columns;
|
let columns = this.columns;
|
||||||
|
|
||||||
@ -1298,13 +1313,33 @@ class DataManager {
|
|||||||
|
|
||||||
getRow(rowIndex) {
|
getRow(rowIndex) {
|
||||||
rowIndex = +rowIndex;
|
rowIndex = +rowIndex;
|
||||||
return this.rows.find(row => row[0].rowIndex === rowIndex);
|
return this.rows[rowIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
getCell(colIndex, rowIndex) {
|
getCell(colIndex, rowIndex) {
|
||||||
rowIndex = +rowIndex;
|
rowIndex = +rowIndex;
|
||||||
colIndex = +colIndex;
|
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() {
|
get() {
|
||||||
@ -1364,11 +1399,11 @@ class ColumnManager {
|
|||||||
|
|
||||||
refreshHeader() {
|
refreshHeader() {
|
||||||
const columns = this.datamanager.getColumns();
|
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 =
|
const refreshHTML =
|
||||||
// first init
|
// first init
|
||||||
!$('.data-table-col', this.header) ||
|
!$('.data-table-cell', this.header) ||
|
||||||
// deleted column
|
// deleted column
|
||||||
columns.length < $cols.length;
|
columns.length < $cols.length;
|
||||||
|
|
||||||
@ -1377,7 +1412,9 @@ class ColumnManager {
|
|||||||
$('thead', this.header).innerHTML = this.getHeaderHTML(columns);
|
$('thead', this.header).innerHTML = this.getHeaderHTML(columns);
|
||||||
|
|
||||||
this.$filterRow = $('.data-table-row[data-is-filter]', this.header);
|
this.$filterRow = $('.data-table-row[data-is-filter]', this.header);
|
||||||
$.style(this.$filterRow, { display: 'none' });
|
if (this.$filterRow) {
|
||||||
|
$.style(this.$filterRow, { display: 'none' });
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// update data-attributes
|
// update data-attributes
|
||||||
$cols.map(($col, i) => {
|
$cols.map(($col, i) => {
|
||||||
@ -1440,7 +1477,7 @@ class ColumnManager {
|
|||||||
const dropdownItems = this.options.headerDropdown;
|
const dropdownItems = this.options.headerDropdown;
|
||||||
|
|
||||||
$.on(this.header, 'click', '.data-table-dropdown-list > div', (e, $item) => {
|
$.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 {
|
const {
|
||||||
index
|
index
|
||||||
} = $.data($item);
|
} = $.data($item);
|
||||||
@ -1462,7 +1499,7 @@ class ColumnManager {
|
|||||||
let isDragging = false;
|
let isDragging = false;
|
||||||
let $resizingCell, startWidth, startX;
|
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');
|
document.body.classList.add('data-table-resize');
|
||||||
const $cell = $handle.parentNode.parentNode;
|
const $cell = $handle.parentNode.parentNode;
|
||||||
$resizingCell = $cell;
|
$resizingCell = $cell;
|
||||||
@ -1519,7 +1556,7 @@ class ColumnManager {
|
|||||||
$.off(document.body, 'mousemove', initialize);
|
$.off(document.body, 'mousemove', initialize);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const ready = $('.data-table-col', this.header);
|
const ready = $('.data-table-cell', this.header);
|
||||||
if (!ready) return;
|
if (!ready) return;
|
||||||
|
|
||||||
const $parent = $('.data-table-row', this.header);
|
const $parent = $('.data-table-row', this.header);
|
||||||
@ -1549,8 +1586,8 @@ class ColumnManager {
|
|||||||
|
|
||||||
bindSortColumn() {
|
bindSortColumn() {
|
||||||
|
|
||||||
$.on(this.header, 'click', '.data-table-col .column-title', (e, span) => {
|
$.on(this.header, 'click', '.data-table-cell .column-title', (e, span) => {
|
||||||
const $cell = span.closest('.data-table-col');
|
const $cell = span.closest('.data-table-cell');
|
||||||
let {
|
let {
|
||||||
colIndex,
|
colIndex,
|
||||||
sortOrder
|
sortOrder
|
||||||
@ -1564,7 +1601,7 @@ class ColumnManager {
|
|||||||
|
|
||||||
// reset sort indicator
|
// reset sort indicator
|
||||||
$('.sort-indicator', this.header).textContent = '';
|
$('.sort-indicator', this.header).textContent = '';
|
||||||
$.each('.data-table-col', this.header).map($cell => {
|
$.each('.data-table-cell', this.header).map($cell => {
|
||||||
$.data($cell, {
|
$.data($cell, {
|
||||||
sortOrder: 'none'
|
sortOrder: 'none'
|
||||||
});
|
});
|
||||||
@ -1665,7 +1702,7 @@ class ColumnManager {
|
|||||||
bindFilter() {
|
bindFilter() {
|
||||||
if (!this.options.enableInlineFilters) return;
|
if (!this.options.enableInlineFilters) return;
|
||||||
const handler = e => {
|
const handler = e => {
|
||||||
const $filterCell = $.closest('.data-table-col', e.target);
|
const $filterCell = $.closest('.data-table-cell', e.target);
|
||||||
const {
|
const {
|
||||||
colIndex
|
colIndex
|
||||||
} = $.data($filterCell);
|
} = $.data($filterCell);
|
||||||
@ -1676,14 +1713,8 @@ class ColumnManager {
|
|||||||
rowsToHide,
|
rowsToHide,
|
||||||
rowsToShow
|
rowsToShow
|
||||||
}) => {
|
}) => {
|
||||||
rowsToHide.map(rowIndex => {
|
this.rowmanager.hideRows(rowsToHide);
|
||||||
const $tr = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
|
this.rowmanager.showRows(rowsToShow);
|
||||||
$tr.classList.add('hide');
|
|
||||||
});
|
|
||||||
rowsToShow.map(rowIndex => {
|
|
||||||
const $tr = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
|
|
||||||
$tr.classList.remove('hide');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
$.on(this.header, 'keydown', '.data-table-filter', debounce$2(handler, 300));
|
$.on(this.header, 'keydown', '.data-table-filter', debounce$2(handler, 300));
|
||||||
@ -1754,7 +1785,7 @@ class ColumnManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getHeaderCell$(colIndex) {
|
getHeaderCell$(colIndex) {
|
||||||
return $(`.data-table-col[data-col-index="${colIndex}"]`, this.header);
|
return $(`.data-table-cell[data-col-index="${colIndex}"]`, this.header);
|
||||||
}
|
}
|
||||||
|
|
||||||
getLastColumnIndex() {
|
getLastColumnIndex() {
|
||||||
@ -1801,6 +1832,7 @@ class CellManager {
|
|||||||
this.bindKeyboardSelection();
|
this.bindKeyboardSelection();
|
||||||
this.bindCopyCellContents();
|
this.bindCopyCellContents();
|
||||||
this.bindMouseEvents();
|
this.bindMouseEvents();
|
||||||
|
this.bindTreeEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
bindFocusCell() {
|
bindFocusCell() {
|
||||||
@ -1810,7 +1842,7 @@ class CellManager {
|
|||||||
bindEditCell() {
|
bindEditCell() {
|
||||||
this.$editingCell = null;
|
this.$editingCell = null;
|
||||||
|
|
||||||
$.on(this.bodyScrollable, 'dblclick', '.data-table-col', (e, cell) => {
|
$.on(this.bodyScrollable, 'dblclick', '.data-table-cell', (e, cell) => {
|
||||||
this.activateEditing(cell);
|
this.activateEditing(cell);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1887,7 +1919,7 @@ class CellManager {
|
|||||||
|
|
||||||
if (this.options.enableInlineFilters) {
|
if (this.options.enableInlineFilters) {
|
||||||
this.keyboard.on('ctrl+f', (e) => {
|
this.keyboard.on('ctrl+f', (e) => {
|
||||||
const $cell = $.closest('.data-table-col', e.target);
|
const $cell = $.closest('.data-table-cell', e.target);
|
||||||
let {
|
let {
|
||||||
colIndex
|
colIndex
|
||||||
} = $.data($cell);
|
} = $.data($cell);
|
||||||
@ -1930,7 +1962,7 @@ class CellManager {
|
|||||||
bindMouseEvents() {
|
bindMouseEvents() {
|
||||||
let mouseDown = null;
|
let mouseDown = null;
|
||||||
|
|
||||||
$.on(this.bodyScrollable, 'mousedown', '.data-table-col', (e) => {
|
$.on(this.bodyScrollable, 'mousedown', '.data-table-cell', (e) => {
|
||||||
mouseDown = true;
|
mouseDown = true;
|
||||||
this.focusCell($(e.delegatedTarget));
|
this.focusCell($(e.delegatedTarget));
|
||||||
});
|
});
|
||||||
@ -1944,7 +1976,39 @@ class CellManager {
|
|||||||
this.selectArea($(e.delegatedTarget));
|
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, {
|
focusCell($cell, {
|
||||||
@ -1994,8 +2058,8 @@ class CellManager {
|
|||||||
rowIndex
|
rowIndex
|
||||||
} = $.data($cell);
|
} = $.data($cell);
|
||||||
const _colIndex = this.datamanager.getColumnIndexById('_rowIndex');
|
const _colIndex = this.datamanager.getColumnIndexById('_rowIndex');
|
||||||
const colHeaderSelector = `.data-table-header .data-table-col[data-col-index="${colIndex}"]`;
|
const colHeaderSelector = `.data-table-header .data-table-cell[data-col-index="${colIndex}"]`;
|
||||||
const rowHeaderSelector = `.data-table-col[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
|
const rowHeaderSelector = `.data-table-cell[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
|
||||||
|
|
||||||
if (this.lastHeaders) {
|
if (this.lastHeaders) {
|
||||||
$.removeStyle(this.lastHeaders, 'backgroundColor');
|
$.removeStyle(this.lastHeaders, 'backgroundColor');
|
||||||
@ -2121,7 +2185,7 @@ class CellManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clearSelection() {
|
clearSelection() {
|
||||||
$.each('.data-table-col.highlight', this.bodyScrollable)
|
$.each('.data-table-cell.highlight', this.bodyScrollable)
|
||||||
.map(cell => cell.classList.remove('highlight'));
|
.map(cell => cell.classList.remove('highlight'));
|
||||||
|
|
||||||
this.$selectionCursor = null;
|
this.$selectionCursor = null;
|
||||||
@ -2393,15 +2457,16 @@ class CellManager {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<td class="data-table-col noselect" ${dataAttr} tabindex="0">
|
<td class="data-table-cell noselect" ${dataAttr} tabindex="0">
|
||||||
${this.getCellContent(cell)}
|
${this.getCellContent(cell)}
|
||||||
</td>
|
</td>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getCellContent(cell) {
|
getCellContent(cell) {
|
||||||
const {
|
const {
|
||||||
isHeader
|
isHeader,
|
||||||
|
isFilter
|
||||||
} = cell;
|
} = cell;
|
||||||
|
|
||||||
const editable = !isHeader && cell.editable !== false;
|
const editable = !isHeader && cell.editable !== false;
|
||||||
@ -2417,21 +2482,35 @@ class CellManager {
|
|||||||
const dropdown = hasDropdown ? `<div class="data-table-dropdown">${getDropdownHTML()}</div>` : '';
|
const dropdown = hasDropdown ? `<div class="data-table-dropdown">${getDropdownHTML()}</div>` : '';
|
||||||
|
|
||||||
let contentHTML;
|
let contentHTML;
|
||||||
if (cell.isHeader || cell.isFilter || !cell.column.format) {
|
if (isHeader || isFilter || !cell.column.format) {
|
||||||
contentHTML = cell.content;
|
contentHTML = cell.content;
|
||||||
} else {
|
} else {
|
||||||
contentHTML = cell.column.format(cell.content, cell);
|
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 `
|
return `
|
||||||
<div class="content ellipsis">
|
<div class="content ellipsis">
|
||||||
${(contentHTML)}
|
${contentHTML}
|
||||||
${sortIndicator}
|
${sortIndicator}
|
||||||
${resizeColumn}
|
${resizeColumn}
|
||||||
${dropdown}
|
${dropdown}
|
||||||
</div>
|
</div>
|
||||||
${editCellHTML}
|
${editCellHTML}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getEditCellHTML() {
|
getEditCellHTML() {
|
||||||
@ -2441,7 +2520,7 @@ class CellManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cellSelector(colIndex, rowIndex) {
|
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
|
// map of checked rows
|
||||||
this.checkMap = [];
|
this.checkMap = [];
|
||||||
|
|
||||||
$.on(this.wrapper, 'click', '.data-table-col[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
|
$.on(this.wrapper, 'click', '.data-table-cell[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
|
||||||
const $cell = $checkbox.closest('.data-table-col');
|
const $cell = $checkbox.closest('.data-table-cell');
|
||||||
const {
|
const {
|
||||||
rowIndex,
|
rowIndex,
|
||||||
isHeader
|
isHeader
|
||||||
@ -2528,7 +2607,7 @@ class RowManager {
|
|||||||
checkRow(rowIndex, toggle) {
|
checkRow(rowIndex, toggle) {
|
||||||
const value = toggle ? 1 : 0;
|
const value = toggle ? 1 : 0;
|
||||||
const selector = rowIndex =>
|
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
|
// update internal map
|
||||||
this.checkMap[rowIndex] = value;
|
this.checkMap[rowIndex] = value;
|
||||||
// set checkbox value explicitly
|
// set checkbox value explicitly
|
||||||
@ -2550,7 +2629,7 @@ class RowManager {
|
|||||||
this.checkMap = [];
|
this.checkMap = [];
|
||||||
}
|
}
|
||||||
// set checkbox value
|
// 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 => {
|
.map(input => {
|
||||||
input.checked = toggle;
|
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) {
|
getRow$(rowIndex) {
|
||||||
return $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
|
return $(this.selector(rowIndex), this.bodyScrollable);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTotalRows() {
|
getTotalRows() {
|
||||||
@ -2662,6 +2765,10 @@ class RowManager {
|
|||||||
const dataAttr = makeDataAttributeString(props);
|
const dataAttr = makeDataAttributeString(props);
|
||||||
return `<input class="data-table-filter input-style" type="text" ${dataAttr} />`;
|
return `<input class="data-table-filter input-style" type="text" ${dataAttr} />`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selector(rowIndex) {
|
||||||
|
return `.data-table-row[data-row-index="${rowIndex}"]`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BodyRenderer {
|
class BodyRenderer {
|
||||||
@ -2685,7 +2792,7 @@ class BodyRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderBodyHTML() {
|
renderBodyHTML() {
|
||||||
const rows = this.datamanager.getRows();
|
const rows = this.datamanager.getRowsForView();
|
||||||
|
|
||||||
this.bodyScrollable.innerHTML = `
|
this.bodyScrollable.innerHTML = `
|
||||||
<table class="data-table-body">
|
<table class="data-table-body">
|
||||||
@ -2698,7 +2805,7 @@ class BodyRenderer {
|
|||||||
|
|
||||||
renderBodyWithClusterize() {
|
renderBodyWithClusterize() {
|
||||||
// first page
|
// first page
|
||||||
const rows = this.datamanager.getRows(0, 20);
|
const rows = this.datamanager.getRowsForView(0, 20);
|
||||||
const initialData = this.getDataForClusterize(rows);
|
const initialData = this.getDataForClusterize(rows);
|
||||||
|
|
||||||
if (!this.clusterize) {
|
if (!this.clusterize) {
|
||||||
@ -2742,7 +2849,7 @@ class BodyRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
appendRemainingData() {
|
appendRemainingData() {
|
||||||
const rows = this.datamanager.getRows(20);
|
const rows = this.datamanager.getRowsForView(20);
|
||||||
const data = this.getDataForClusterize(rows);
|
const data = this.getDataForClusterize(rows);
|
||||||
this.clusterize.append(data);
|
this.clusterize.append(data);
|
||||||
}
|
}
|
||||||
@ -2859,7 +2966,7 @@ class Style {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupMinWidth() {
|
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 width = $.style($('.content', col), 'width');
|
||||||
const {
|
const {
|
||||||
colIndex
|
colIndex
|
||||||
@ -2877,7 +2984,7 @@ class Style {
|
|||||||
if (!$('.data-table-row')) return;
|
if (!$('.data-table-row')) return;
|
||||||
|
|
||||||
// set initial width as naturally calculated by table's first row
|
// 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 {
|
const {
|
||||||
colIndex
|
colIndex
|
||||||
} = $.data($cell);
|
} = $.data($cell);
|
||||||
@ -2926,7 +3033,7 @@ class Style {
|
|||||||
setDefaultCellHeight() {
|
setDefaultCellHeight() {
|
||||||
if (this.__cellHeightSet) return;
|
if (this.__cellHeightSet) return;
|
||||||
const height = this.options.cellHeight ||
|
const height = this.options.cellHeight ||
|
||||||
$.style($('.data-table-col', this.instance.datatableWrapper), 'height');
|
$.style($('.data-table-cell', this.instance.datatableWrapper), 'height');
|
||||||
if (height) {
|
if (height) {
|
||||||
this.setCellHeight(height);
|
this.setCellHeight(height);
|
||||||
this.__cellHeightSet = true;
|
this.__cellHeightSet = true;
|
||||||
@ -2934,10 +3041,10 @@ class Style {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setCellHeight(height) {
|
setCellHeight(height) {
|
||||||
this.setStyle('.data-table-col .content', {
|
this.setStyle('.data-table-cell .content', {
|
||||||
height: height + 'px'
|
height: height + 'px'
|
||||||
});
|
});
|
||||||
this.setStyle('.data-table-col .edit-cell', {
|
this.setStyle('.data-table-cell .edit-cell', {
|
||||||
height: height + 'px'
|
height: height + 'px'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -2986,7 +3093,7 @@ class Style {
|
|||||||
getColumnHeaderElement(colIndex) {
|
getColumnHeaderElement(colIndex) {
|
||||||
colIndex = +colIndex;
|
colIndex = +colIndex;
|
||||||
if (colIndex < 0) return null;
|
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) {
|
getRowIndexColumnWidth(baseWidth) {
|
||||||
|
|||||||
@ -12,7 +12,8 @@ let datatable1 = new DataTable('.datatable-1', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let datatable2 = new DataTable('.datatable-2', Object.assign(getTreeData(), {
|
let datatable2 = new DataTable('.datatable-2', Object.assign(getTreeData(), {
|
||||||
enableInlineFilters: true
|
enableInlineFilters: true,
|
||||||
|
addCheckboxColumn: true
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function getSampleData(multiplier) {
|
function getSampleData(multiplier) {
|
||||||
|
|||||||
@ -54,7 +54,7 @@
|
|||||||
|
|
||||||
if (largeData) {
|
if (largeData) {
|
||||||
for (let i = 0; i < 10; i++) {
|
for (let i = 0; i < 10; i++) {
|
||||||
data = data.concat(data.rows);
|
data = data.concat(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,6 +29,7 @@ export default class CellManager {
|
|||||||
this.bindKeyboardSelection();
|
this.bindKeyboardSelection();
|
||||||
this.bindCopyCellContents();
|
this.bindCopyCellContents();
|
||||||
this.bindMouseEvents();
|
this.bindMouseEvents();
|
||||||
|
this.bindTreeEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
bindFocusCell() {
|
bindFocusCell() {
|
||||||
@ -38,7 +39,7 @@ export default class CellManager {
|
|||||||
bindEditCell() {
|
bindEditCell() {
|
||||||
this.$editingCell = null;
|
this.$editingCell = null;
|
||||||
|
|
||||||
$.on(this.bodyScrollable, 'dblclick', '.data-table-col', (e, cell) => {
|
$.on(this.bodyScrollable, 'dblclick', '.data-table-cell', (e, cell) => {
|
||||||
this.activateEditing(cell);
|
this.activateEditing(cell);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -115,7 +116,7 @@ export default class CellManager {
|
|||||||
|
|
||||||
if (this.options.enableInlineFilters) {
|
if (this.options.enableInlineFilters) {
|
||||||
this.keyboard.on('ctrl+f', (e) => {
|
this.keyboard.on('ctrl+f', (e) => {
|
||||||
const $cell = $.closest('.data-table-col', e.target);
|
const $cell = $.closest('.data-table-cell', e.target);
|
||||||
let {
|
let {
|
||||||
colIndex
|
colIndex
|
||||||
} = $.data($cell);
|
} = $.data($cell);
|
||||||
@ -158,7 +159,7 @@ export default class CellManager {
|
|||||||
bindMouseEvents() {
|
bindMouseEvents() {
|
||||||
let mouseDown = null;
|
let mouseDown = null;
|
||||||
|
|
||||||
$.on(this.bodyScrollable, 'mousedown', '.data-table-col', (e) => {
|
$.on(this.bodyScrollable, 'mousedown', '.data-table-cell', (e) => {
|
||||||
mouseDown = true;
|
mouseDown = true;
|
||||||
this.focusCell($(e.delegatedTarget));
|
this.focusCell($(e.delegatedTarget));
|
||||||
});
|
});
|
||||||
@ -172,7 +173,39 @@ export default class CellManager {
|
|||||||
this.selectArea($(e.delegatedTarget));
|
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, {
|
focusCell($cell, {
|
||||||
@ -222,8 +255,8 @@ export default class CellManager {
|
|||||||
rowIndex
|
rowIndex
|
||||||
} = $.data($cell);
|
} = $.data($cell);
|
||||||
const _colIndex = this.datamanager.getColumnIndexById('_rowIndex');
|
const _colIndex = this.datamanager.getColumnIndexById('_rowIndex');
|
||||||
const colHeaderSelector = `.data-table-header .data-table-col[data-col-index="${colIndex}"]`;
|
const colHeaderSelector = `.data-table-header .data-table-cell[data-col-index="${colIndex}"]`;
|
||||||
const rowHeaderSelector = `.data-table-col[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
|
const rowHeaderSelector = `.data-table-cell[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
|
||||||
|
|
||||||
if (this.lastHeaders) {
|
if (this.lastHeaders) {
|
||||||
$.removeStyle(this.lastHeaders, 'backgroundColor');
|
$.removeStyle(this.lastHeaders, 'backgroundColor');
|
||||||
@ -349,7 +382,7 @@ export default class CellManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clearSelection() {
|
clearSelection() {
|
||||||
$.each('.data-table-col.highlight', this.bodyScrollable)
|
$.each('.data-table-cell.highlight', this.bodyScrollable)
|
||||||
.map(cell => cell.classList.remove('highlight'));
|
.map(cell => cell.classList.remove('highlight'));
|
||||||
|
|
||||||
this.$selectionCursor = null;
|
this.$selectionCursor = null;
|
||||||
@ -621,15 +654,16 @@ export default class CellManager {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<td class="data-table-col noselect" ${dataAttr} tabindex="0">
|
<td class="data-table-cell noselect" ${dataAttr} tabindex="0">
|
||||||
${this.getCellContent(cell)}
|
${this.getCellContent(cell)}
|
||||||
</td>
|
</td>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getCellContent(cell) {
|
getCellContent(cell) {
|
||||||
const {
|
const {
|
||||||
isHeader
|
isHeader,
|
||||||
|
isFilter
|
||||||
} = cell;
|
} = cell;
|
||||||
|
|
||||||
const editable = !isHeader && cell.editable !== false;
|
const editable = !isHeader && cell.editable !== false;
|
||||||
@ -645,21 +679,35 @@ export default class CellManager {
|
|||||||
const dropdown = hasDropdown ? `<div class="data-table-dropdown">${getDropdownHTML()}</div>` : '';
|
const dropdown = hasDropdown ? `<div class="data-table-dropdown">${getDropdownHTML()}</div>` : '';
|
||||||
|
|
||||||
let contentHTML;
|
let contentHTML;
|
||||||
if (cell.isHeader || cell.isFilter || !cell.column.format) {
|
if (isHeader || isFilter || !cell.column.format) {
|
||||||
contentHTML = cell.content;
|
contentHTML = cell.content;
|
||||||
} else {
|
} else {
|
||||||
contentHTML = cell.column.format(cell.content, cell);
|
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 `
|
return `
|
||||||
<div class="content ellipsis">
|
<div class="content ellipsis">
|
||||||
${(contentHTML)}
|
${contentHTML}
|
||||||
${sortIndicator}
|
${sortIndicator}
|
||||||
${resizeColumn}
|
${resizeColumn}
|
||||||
${dropdown}
|
${dropdown}
|
||||||
</div>
|
</div>
|
||||||
${editCellHTML}
|
${editCellHTML}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getEditCellHTML() {
|
getEditCellHTML() {
|
||||||
@ -669,6 +717,6 @@ export default class CellManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cellSelector(colIndex, rowIndex) {
|
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}"]`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,11 +32,11 @@ export default class ColumnManager {
|
|||||||
|
|
||||||
refreshHeader() {
|
refreshHeader() {
|
||||||
const columns = this.datamanager.getColumns();
|
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 =
|
const refreshHTML =
|
||||||
// first init
|
// first init
|
||||||
!$('.data-table-col', this.header) ||
|
!$('.data-table-cell', this.header) ||
|
||||||
// deleted column
|
// deleted column
|
||||||
columns.length < $cols.length;
|
columns.length < $cols.length;
|
||||||
|
|
||||||
@ -45,7 +45,9 @@ export default class ColumnManager {
|
|||||||
$('thead', this.header).innerHTML = this.getHeaderHTML(columns);
|
$('thead', this.header).innerHTML = this.getHeaderHTML(columns);
|
||||||
|
|
||||||
this.$filterRow = $('.data-table-row[data-is-filter]', this.header);
|
this.$filterRow = $('.data-table-row[data-is-filter]', this.header);
|
||||||
$.style(this.$filterRow, { display: 'none' });
|
if (this.$filterRow) {
|
||||||
|
$.style(this.$filterRow, { display: 'none' });
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// update data-attributes
|
// update data-attributes
|
||||||
$cols.map(($col, i) => {
|
$cols.map(($col, i) => {
|
||||||
@ -108,7 +110,7 @@ export default class ColumnManager {
|
|||||||
const dropdownItems = this.options.headerDropdown;
|
const dropdownItems = this.options.headerDropdown;
|
||||||
|
|
||||||
$.on(this.header, 'click', '.data-table-dropdown-list > div', (e, $item) => {
|
$.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 {
|
const {
|
||||||
index
|
index
|
||||||
} = $.data($item);
|
} = $.data($item);
|
||||||
@ -130,7 +132,7 @@ export default class ColumnManager {
|
|||||||
let isDragging = false;
|
let isDragging = false;
|
||||||
let $resizingCell, startWidth, startX;
|
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');
|
document.body.classList.add('data-table-resize');
|
||||||
const $cell = $handle.parentNode.parentNode;
|
const $cell = $handle.parentNode.parentNode;
|
||||||
$resizingCell = $cell;
|
$resizingCell = $cell;
|
||||||
@ -187,7 +189,7 @@ export default class ColumnManager {
|
|||||||
$.off(document.body, 'mousemove', initialize);
|
$.off(document.body, 'mousemove', initialize);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const ready = $('.data-table-col', this.header);
|
const ready = $('.data-table-cell', this.header);
|
||||||
if (!ready) return;
|
if (!ready) return;
|
||||||
|
|
||||||
const $parent = $('.data-table-row', this.header);
|
const $parent = $('.data-table-row', this.header);
|
||||||
@ -217,8 +219,8 @@ export default class ColumnManager {
|
|||||||
|
|
||||||
bindSortColumn() {
|
bindSortColumn() {
|
||||||
|
|
||||||
$.on(this.header, 'click', '.data-table-col .column-title', (e, span) => {
|
$.on(this.header, 'click', '.data-table-cell .column-title', (e, span) => {
|
||||||
const $cell = span.closest('.data-table-col');
|
const $cell = span.closest('.data-table-cell');
|
||||||
let {
|
let {
|
||||||
colIndex,
|
colIndex,
|
||||||
sortOrder
|
sortOrder
|
||||||
@ -232,7 +234,7 @@ export default class ColumnManager {
|
|||||||
|
|
||||||
// reset sort indicator
|
// reset sort indicator
|
||||||
$('.sort-indicator', this.header).textContent = '';
|
$('.sort-indicator', this.header).textContent = '';
|
||||||
$.each('.data-table-col', this.header).map($cell => {
|
$.each('.data-table-cell', this.header).map($cell => {
|
||||||
$.data($cell, {
|
$.data($cell, {
|
||||||
sortOrder: 'none'
|
sortOrder: 'none'
|
||||||
});
|
});
|
||||||
@ -333,7 +335,7 @@ export default class ColumnManager {
|
|||||||
bindFilter() {
|
bindFilter() {
|
||||||
if (!this.options.enableInlineFilters) return;
|
if (!this.options.enableInlineFilters) return;
|
||||||
const handler = e => {
|
const handler = e => {
|
||||||
const $filterCell = $.closest('.data-table-col', e.target);
|
const $filterCell = $.closest('.data-table-cell', e.target);
|
||||||
const {
|
const {
|
||||||
colIndex
|
colIndex
|
||||||
} = $.data($filterCell);
|
} = $.data($filterCell);
|
||||||
@ -344,14 +346,8 @@ export default class ColumnManager {
|
|||||||
rowsToHide,
|
rowsToHide,
|
||||||
rowsToShow
|
rowsToShow
|
||||||
}) => {
|
}) => {
|
||||||
rowsToHide.map(rowIndex => {
|
this.rowmanager.hideRows(rowsToHide);
|
||||||
const $tr = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
|
this.rowmanager.showRows(rowsToShow);
|
||||||
$tr.classList.add('hide');
|
|
||||||
});
|
|
||||||
rowsToShow.map(rowIndex => {
|
|
||||||
const $tr = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
|
|
||||||
$tr.classList.remove('hide');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
$.on(this.header, 'keydown', '.data-table-filter', debounce(handler, 300));
|
$.on(this.header, 'keydown', '.data-table-filter', debounce(handler, 300));
|
||||||
@ -422,7 +418,7 @@ export default class ColumnManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getHeaderCell$(colIndex) {
|
getHeaderCell$(colIndex) {
|
||||||
return $(`.data-table-col[data-col-index="${colIndex}"]`, this.header);
|
return $(`.data-table-cell[data-col-index="${colIndex}"]`, this.header);
|
||||||
}
|
}
|
||||||
|
|
||||||
getLastColumnIndex() {
|
getLastColumnIndex() {
|
||||||
|
|||||||
@ -501,6 +501,26 @@ export default class DataManager {
|
|||||||
return this.getRow(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() {
|
get() {
|
||||||
return {
|
return {
|
||||||
columns: this.columns,
|
columns: this.columns,
|
||||||
|
|||||||
@ -54,3 +54,5 @@ export default class Keyboard {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export let keyCode = KEYCODES;
|
||||||
|
|||||||
@ -33,8 +33,8 @@ export default class RowManager {
|
|||||||
// map of checked rows
|
// map of checked rows
|
||||||
this.checkMap = [];
|
this.checkMap = [];
|
||||||
|
|
||||||
$.on(this.wrapper, 'click', '.data-table-col[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
|
$.on(this.wrapper, 'click', '.data-table-cell[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
|
||||||
const $cell = $checkbox.closest('.data-table-col');
|
const $cell = $checkbox.closest('.data-table-cell');
|
||||||
const {
|
const {
|
||||||
rowIndex,
|
rowIndex,
|
||||||
isHeader
|
isHeader
|
||||||
@ -87,7 +87,7 @@ export default class RowManager {
|
|||||||
checkRow(rowIndex, toggle) {
|
checkRow(rowIndex, toggle) {
|
||||||
const value = toggle ? 1 : 0;
|
const value = toggle ? 1 : 0;
|
||||||
const selector = rowIndex =>
|
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
|
// update internal map
|
||||||
this.checkMap[rowIndex] = value;
|
this.checkMap[rowIndex] = value;
|
||||||
// set checkbox value explicitly
|
// set checkbox value explicitly
|
||||||
@ -109,7 +109,7 @@ export default class RowManager {
|
|||||||
this.checkMap = [];
|
this.checkMap = [];
|
||||||
}
|
}
|
||||||
// set checkbox value
|
// 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 => {
|
.map(input => {
|
||||||
input.checked = toggle;
|
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) {
|
getRow$(rowIndex) {
|
||||||
return $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
|
return $(this.selector(rowIndex), this.bodyScrollable);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTotalRows() {
|
getTotalRows() {
|
||||||
@ -221,4 +245,8 @@ export default class RowManager {
|
|||||||
const dataAttr = makeDataAttributeString(props);
|
const dataAttr = makeDataAttributeString(props);
|
||||||
return `<input class="data-table-filter input-style" type="text" ${dataAttr} />`;
|
return `<input class="data-table-filter input-style" type="text" ${dataAttr} />`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selector(rowIndex) {
|
||||||
|
return `.data-table-row[data-row-index="${rowIndex}"]`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -173,17 +173,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col.remove-column {
|
.data-table-cell.remove-column {
|
||||||
background-color: var(--light-red);
|
background-color: var(--light-red);
|
||||||
transition: 300ms background-color ease-in-out;
|
transition: 300ms background-color ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col.sortable-chosen {
|
.data-table-cell.sortable-chosen {
|
||||||
background-color: var(--light-bg);
|
background-color: var(--light-bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-col {
|
.data-table-cell {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
@ -231,6 +231,28 @@
|
|||||||
&:hover .data-table-dropdown-toggle {
|
&:hover .data-table-dropdown-toggle {
|
||||||
display: block;
|
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 {
|
.data-table-row {
|
||||||
|
|||||||
12
src/style.js
12
src/style.js
@ -104,7 +104,7 @@ export default class Style {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupMinWidth() {
|
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 width = $.style($('.content', col), 'width');
|
||||||
const {
|
const {
|
||||||
colIndex
|
colIndex
|
||||||
@ -122,7 +122,7 @@ export default class Style {
|
|||||||
if (!$('.data-table-row')) return;
|
if (!$('.data-table-row')) return;
|
||||||
|
|
||||||
// set initial width as naturally calculated by table's first row
|
// 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 {
|
const {
|
||||||
colIndex
|
colIndex
|
||||||
} = $.data($cell);
|
} = $.data($cell);
|
||||||
@ -171,7 +171,7 @@ export default class Style {
|
|||||||
setDefaultCellHeight() {
|
setDefaultCellHeight() {
|
||||||
if (this.__cellHeightSet) return;
|
if (this.__cellHeightSet) return;
|
||||||
const height = this.options.cellHeight ||
|
const height = this.options.cellHeight ||
|
||||||
$.style($('.data-table-col', this.instance.datatableWrapper), 'height');
|
$.style($('.data-table-cell', this.instance.datatableWrapper), 'height');
|
||||||
if (height) {
|
if (height) {
|
||||||
this.setCellHeight(height);
|
this.setCellHeight(height);
|
||||||
this.__cellHeightSet = true;
|
this.__cellHeightSet = true;
|
||||||
@ -179,10 +179,10 @@ export default class Style {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setCellHeight(height) {
|
setCellHeight(height) {
|
||||||
this.setStyle('.data-table-col .content', {
|
this.setStyle('.data-table-cell .content', {
|
||||||
height: height + 'px'
|
height: height + 'px'
|
||||||
});
|
});
|
||||||
this.setStyle('.data-table-col .edit-cell', {
|
this.setStyle('.data-table-cell .edit-cell', {
|
||||||
height: height + 'px'
|
height: height + 'px'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -231,7 +231,7 @@ export default class Style {
|
|||||||
getColumnHeaderElement(colIndex) {
|
getColumnHeaderElement(colIndex) {
|
||||||
colIndex = +colIndex;
|
colIndex = +colIndex;
|
||||||
if (colIndex < 0) return null;
|
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) {
|
getRowIndexColumnWidth(baseWidth) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user