Tree expand/collapse working

This commit is contained in:
Faris Ansari 2018-03-02 15:42:51 +05:30
parent 081dbac41b
commit 470ab90fef
8 changed files with 460 additions and 239 deletions

View File

@ -825,6 +825,25 @@ function linkProperties(target, source, properties) {
Object.defineProperties(target, props); Object.defineProperties(target, props);
} }
function isSet(val) {
return val !== undefined || val !== null;
}
function notSet(val) {
return !isSet(val);
}
function isNumber(val) {
return !isNaN(val);
}
function ensureArray(val) {
if (!Array.isArray(val)) {
return [val];
}
return val;
}
class DataManager { class DataManager {
constructor(options) { constructor(options) {
this.options = options; this.options = options;
@ -847,6 +866,7 @@ class DataManager {
this.prepareColumns(); this.prepareColumns();
this.prepareRows(); this.prepareRows();
this.prepareTreeRows();
this.prepareRowView(); this.prepareRowView();
this.prepareNumericColumns(); this.prepareNumericColumns();
@ -995,13 +1015,25 @@ class DataManager {
} }
} }
meta.indent = d.indent; meta.indent = d.indent || 0;
} }
return this.prepareRow(row, meta); return this.prepareRow(row, meta);
}); });
} }
prepareTreeRows() {
this.rows.forEach((row, i) => {
if (isNumber(row.meta.indent)) {
// if (i === 36) debugger;
const nextRow = this.getRow(i + 1);
row.meta.isLeaf = !nextRow ||
notSet(nextRow.meta.indent) ||
nextRow.meta.indent <= row.meta.indent;
}
});
}
prepareRowView() { prepareRowView() {
// This is order in which rows will be rendered in the table. // This is order in which rows will be rendered in the table.
// When sorting happens, only this.rowViewOrder will change // When sorting happens, only this.rowViewOrder will change
@ -1323,21 +1355,44 @@ class DataManager {
return this.getRow(rowIndex)[colIndex]; return this.getRow(rowIndex)[colIndex];
} }
getChildrenIndices(parentRowIndex) { getChildren(parentRowIndex) {
parentRowIndex = +parentRowIndex; parentRowIndex = +parentRowIndex;
const parentIndent = this.getRow(parentRowIndex).meta.indent; const parentIndent = this.getRow(parentRowIndex).meta.indent;
const out = []; const out = [];
let i = parentRowIndex + 1; for (let i = parentRowIndex + 1; i < this.rowCount; i++) {
let nextRow = this.getRow(i); const row = this.getRow(i);
let nextIndent = nextRow ? (nextRow.meta.indent || 0) : -1; if (isNaN(row.meta.indent)) continue;
while (nextIndent > parentIndent) { if (row.meta.indent > parentIndent) {
out.push(i); out.push(i);
}
i++; if (row.meta.indent === parentIndent) {
nextRow = this.getRow(i); break;
nextIndent = nextRow ? (nextRow.meta.indent || 0) : -1; }
}
return out;
}
getImmediateChildren(parentRowIndex) {
parentRowIndex = +parentRowIndex;
const parentIndent = this.getRow(parentRowIndex).meta.indent;
const out = [];
const childIndent = parentIndent + 1;
for (let i = parentRowIndex + 1; i < this.rowCount; i++) {
const row = this.getRow(i);
if (isNaN(row.meta.indent) || row.meta.indent > childIndent) continue;
if (row.meta.indent === childIndent) {
out.push(i);
}
if (row.meta.indent === parentIndent) {
break;
}
} }
return out; return out;
@ -1774,15 +1829,7 @@ class ColumnManager {
} }
getFirstColumnIndex() { getFirstColumnIndex() {
if (this.options.addCheckboxColumn && this.options.addSerialNoColumn) { return this.datamanager.getColumnIndexById('_rowIndex') + 1;
return 2;
}
if (this.options.addCheckboxColumn || this.options.addSerialNoColumn) {
return 1;
}
return 0;
} }
getHeaderCell$(colIndex) { getHeaderCell$(colIndex) {
@ -1815,14 +1862,16 @@ var getDropdownHTML = function getDropdownHTML(dropdownButton = 'v') {
class CellManager { class CellManager {
constructor(instance) { constructor(instance) {
this.instance = instance; this.instance = instance;
this.wrapper = this.instance.wrapper; linkProperties(this, this.instance, [
this.options = this.instance.options; 'wrapper',
this.style = this.instance.style; 'options',
this.bodyScrollable = this.instance.bodyScrollable; 'style',
this.columnmanager = this.instance.columnmanager; 'bodyScrollable',
this.rowmanager = this.instance.rowmanager; 'columnmanager',
this.datamanager = this.instance.datamanager; 'rowmanager',
this.keyboard = this.instance.keyboard; 'datamanager',
'keyboard'
]);
this.bindEvents(); this.bindEvents();
} }
@ -1986,30 +2035,11 @@ class CellManager {
const { rowIndex } = $.data($cell); const { rowIndex } = $.data($cell);
if ($cell.classList.contains('tree-close')) { if ($cell.classList.contains('tree-close')) {
this.rowmanager.openTreeNode(rowIndex); this.rowmanager.openSingleNode(rowIndex);
$cell.classList.remove('tree-close');
} else { } else {
this.rowmanager.closeTreeNode(rowIndex); this.rowmanager.closeSingleNode(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, {
@ -2362,17 +2392,25 @@ class CellManager {
} }
refreshCell(cell) { refreshCell(cell) {
const $cell = $(this.cellSelector(cell.colIndex, cell.rowIndex), this.bodyScrollable); const $cell = $(this.selector(cell.colIndex, cell.rowIndex), this.bodyScrollable);
$cell.innerHTML = this.getCellContent(cell); $cell.innerHTML = this.getCellContent(cell);
} }
toggleTreeButton(rowIndex, flag) {
const colIndex = this.columnmanager.getFirstColumnIndex();
const $cell = this.getCell$(colIndex, rowIndex);
if ($cell) {
$cell.classList[flag ? 'remove' : 'add']('tree-close');
}
}
isStandardCell(colIndex) { isStandardCell(colIndex) {
// Standard cells are in Sr. No and Checkbox column // Standard cells are in Sr. No and Checkbox column
return colIndex < this.columnmanager.getFirstColumnIndex(); return colIndex < this.columnmanager.getFirstColumnIndex();
} }
getCell$(colIndex, rowIndex) { getCell$(colIndex, rowIndex) {
return $(this.cellSelector(colIndex, rowIndex), this.bodyScrollable); return $(this.selector(colIndex, rowIndex), this.bodyScrollable);
} }
getAboveCell$($cell) { getAboveCell$($cell) {
@ -2520,7 +2558,7 @@ class CellManager {
`; `;
} }
cellSelector(colIndex, rowIndex) { selector(colIndex, rowIndex) {
return `.data-table-cell[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`; return `.data-table-cell[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`;
} }
} }
@ -2528,9 +2566,11 @@ class CellManager {
class RowManager { class RowManager {
constructor(instance) { constructor(instance) {
this.instance = instance; this.instance = instance;
this.options = this.instance.options; linkProperties(this, this.instance, [
this.wrapper = this.instance.wrapper; 'options',
this.bodyScrollable = this.instance.bodyScrollable; 'wrapper',
'bodyScrollable'
]);
this.bindEvents(); this.bindEvents();
this.refreshRows = promisify(this.refreshRows, this); this.refreshRows = promisify(this.refreshRows, this);
@ -2676,6 +2716,7 @@ class RowManager {
} }
hideRows(rowIndices) { hideRows(rowIndices) {
rowIndices = ensureArray(rowIndices);
rowIndices.map(rowIndex => { rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex); const $tr = this.getRow$(rowIndex);
$tr.classList.add('hide'); $tr.classList.add('hide');
@ -2683,20 +2724,33 @@ class RowManager {
} }
showRows(rowIndices) { showRows(rowIndices) {
rowIndices = ensureArray(rowIndices);
rowIndices.map(rowIndex => { rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex); const $tr = this.getRow$(rowIndex);
$tr.classList.remove('hide'); $tr.classList.remove('hide');
}); });
} }
openTreeNode(rowIndex) { openSingleNode(rowIndex) {
const rowsToShow = this.datamanager.getChildrenIndices(rowIndex); const rowsToShow = this.datamanager.getImmediateChildren(rowIndex);
this.showRows(rowsToShow); this.showRows(rowsToShow);
this.cellmanager.toggleTreeButton(rowIndex, true);
} }
closeTreeNode(rowIndex) { closeSingleNode(rowIndex) {
const rowsToHide = this.datamanager.getChildrenIndices(rowIndex); const children = this.datamanager.getImmediateChildren(rowIndex);
this.hideRows(rowsToHide); children.forEach(childIndex => {
const row = this.datamanager.getRow(childIndex);
if (row.meta.isLeaf) {
// close
this.hideRows(childIndex);
this.cellmanager.toggleTreeButton(childIndex, false);
} else {
this.closeSingleNode(childIndex);
this.hideRows(childIndex);
}
});
this.cellmanager.toggleTreeButton(rowIndex, false);
} }
getRow$(rowIndex) { getRow$(rowIndex) {

View File

@ -824,6 +824,25 @@ function linkProperties(target, source, properties) {
Object.defineProperties(target, props); Object.defineProperties(target, props);
} }
function isSet(val) {
return val !== undefined || val !== null;
}
function notSet(val) {
return !isSet(val);
}
function isNumber(val) {
return !isNaN(val);
}
function ensureArray(val) {
if (!Array.isArray(val)) {
return [val];
}
return val;
}
class DataManager { class DataManager {
constructor(options) { constructor(options) {
this.options = options; this.options = options;
@ -846,6 +865,7 @@ class DataManager {
this.prepareColumns(); this.prepareColumns();
this.prepareRows(); this.prepareRows();
this.prepareTreeRows();
this.prepareRowView(); this.prepareRowView();
this.prepareNumericColumns(); this.prepareNumericColumns();
@ -994,13 +1014,25 @@ class DataManager {
} }
} }
meta.indent = d.indent; meta.indent = d.indent || 0;
} }
return this.prepareRow(row, meta); return this.prepareRow(row, meta);
}); });
} }
prepareTreeRows() {
this.rows.forEach((row, i) => {
if (isNumber(row.meta.indent)) {
// if (i === 36) debugger;
const nextRow = this.getRow(i + 1);
row.meta.isLeaf = !nextRow ||
notSet(nextRow.meta.indent) ||
nextRow.meta.indent <= row.meta.indent;
}
});
}
prepareRowView() { prepareRowView() {
// This is order in which rows will be rendered in the table. // This is order in which rows will be rendered in the table.
// When sorting happens, only this.rowViewOrder will change // When sorting happens, only this.rowViewOrder will change
@ -1322,21 +1354,44 @@ class DataManager {
return this.getRow(rowIndex)[colIndex]; return this.getRow(rowIndex)[colIndex];
} }
getChildrenIndices(parentRowIndex) { getChildren(parentRowIndex) {
parentRowIndex = +parentRowIndex; parentRowIndex = +parentRowIndex;
const parentIndent = this.getRow(parentRowIndex).meta.indent; const parentIndent = this.getRow(parentRowIndex).meta.indent;
const out = []; const out = [];
let i = parentRowIndex + 1; for (let i = parentRowIndex + 1; i < this.rowCount; i++) {
let nextRow = this.getRow(i); const row = this.getRow(i);
let nextIndent = nextRow ? (nextRow.meta.indent || 0) : -1; if (isNaN(row.meta.indent)) continue;
while (nextIndent > parentIndent) { if (row.meta.indent > parentIndent) {
out.push(i); out.push(i);
}
i++; if (row.meta.indent === parentIndent) {
nextRow = this.getRow(i); break;
nextIndent = nextRow ? (nextRow.meta.indent || 0) : -1; }
}
return out;
}
getImmediateChildren(parentRowIndex) {
parentRowIndex = +parentRowIndex;
const parentIndent = this.getRow(parentRowIndex).meta.indent;
const out = [];
const childIndent = parentIndent + 1;
for (let i = parentRowIndex + 1; i < this.rowCount; i++) {
const row = this.getRow(i);
if (isNaN(row.meta.indent) || row.meta.indent > childIndent) continue;
if (row.meta.indent === childIndent) {
out.push(i);
}
if (row.meta.indent === parentIndent) {
break;
}
} }
return out; return out;
@ -1773,15 +1828,7 @@ class ColumnManager {
} }
getFirstColumnIndex() { getFirstColumnIndex() {
if (this.options.addCheckboxColumn && this.options.addSerialNoColumn) { return this.datamanager.getColumnIndexById('_rowIndex') + 1;
return 2;
}
if (this.options.addCheckboxColumn || this.options.addSerialNoColumn) {
return 1;
}
return 0;
} }
getHeaderCell$(colIndex) { getHeaderCell$(colIndex) {
@ -1814,14 +1861,16 @@ var getDropdownHTML = function getDropdownHTML(dropdownButton = 'v') {
class CellManager { class CellManager {
constructor(instance) { constructor(instance) {
this.instance = instance; this.instance = instance;
this.wrapper = this.instance.wrapper; linkProperties(this, this.instance, [
this.options = this.instance.options; 'wrapper',
this.style = this.instance.style; 'options',
this.bodyScrollable = this.instance.bodyScrollable; 'style',
this.columnmanager = this.instance.columnmanager; 'bodyScrollable',
this.rowmanager = this.instance.rowmanager; 'columnmanager',
this.datamanager = this.instance.datamanager; 'rowmanager',
this.keyboard = this.instance.keyboard; 'datamanager',
'keyboard'
]);
this.bindEvents(); this.bindEvents();
} }
@ -1985,30 +2034,11 @@ class CellManager {
const { rowIndex } = $.data($cell); const { rowIndex } = $.data($cell);
if ($cell.classList.contains('tree-close')) { if ($cell.classList.contains('tree-close')) {
this.rowmanager.openTreeNode(rowIndex); this.rowmanager.openSingleNode(rowIndex);
$cell.classList.remove('tree-close');
} else { } else {
this.rowmanager.closeTreeNode(rowIndex); this.rowmanager.closeSingleNode(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, {
@ -2361,17 +2391,25 @@ class CellManager {
} }
refreshCell(cell) { refreshCell(cell) {
const $cell = $(this.cellSelector(cell.colIndex, cell.rowIndex), this.bodyScrollable); const $cell = $(this.selector(cell.colIndex, cell.rowIndex), this.bodyScrollable);
$cell.innerHTML = this.getCellContent(cell); $cell.innerHTML = this.getCellContent(cell);
} }
toggleTreeButton(rowIndex, flag) {
const colIndex = this.columnmanager.getFirstColumnIndex();
const $cell = this.getCell$(colIndex, rowIndex);
if ($cell) {
$cell.classList[flag ? 'remove' : 'add']('tree-close');
}
}
isStandardCell(colIndex) { isStandardCell(colIndex) {
// Standard cells are in Sr. No and Checkbox column // Standard cells are in Sr. No and Checkbox column
return colIndex < this.columnmanager.getFirstColumnIndex(); return colIndex < this.columnmanager.getFirstColumnIndex();
} }
getCell$(colIndex, rowIndex) { getCell$(colIndex, rowIndex) {
return $(this.cellSelector(colIndex, rowIndex), this.bodyScrollable); return $(this.selector(colIndex, rowIndex), this.bodyScrollable);
} }
getAboveCell$($cell) { getAboveCell$($cell) {
@ -2519,7 +2557,7 @@ class CellManager {
`; `;
} }
cellSelector(colIndex, rowIndex) { selector(colIndex, rowIndex) {
return `.data-table-cell[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`; return `.data-table-cell[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`;
} }
} }
@ -2527,9 +2565,11 @@ class CellManager {
class RowManager { class RowManager {
constructor(instance) { constructor(instance) {
this.instance = instance; this.instance = instance;
this.options = this.instance.options; linkProperties(this, this.instance, [
this.wrapper = this.instance.wrapper; 'options',
this.bodyScrollable = this.instance.bodyScrollable; 'wrapper',
'bodyScrollable'
]);
this.bindEvents(); this.bindEvents();
this.refreshRows = promisify(this.refreshRows, this); this.refreshRows = promisify(this.refreshRows, this);
@ -2675,6 +2715,7 @@ class RowManager {
} }
hideRows(rowIndices) { hideRows(rowIndices) {
rowIndices = ensureArray(rowIndices);
rowIndices.map(rowIndex => { rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex); const $tr = this.getRow$(rowIndex);
$tr.classList.add('hide'); $tr.classList.add('hide');
@ -2682,20 +2723,33 @@ class RowManager {
} }
showRows(rowIndices) { showRows(rowIndices) {
rowIndices = ensureArray(rowIndices);
rowIndices.map(rowIndex => { rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex); const $tr = this.getRow$(rowIndex);
$tr.classList.remove('hide'); $tr.classList.remove('hide');
}); });
} }
openTreeNode(rowIndex) { openSingleNode(rowIndex) {
const rowsToShow = this.datamanager.getChildrenIndices(rowIndex); const rowsToShow = this.datamanager.getImmediateChildren(rowIndex);
this.showRows(rowsToShow); this.showRows(rowsToShow);
this.cellmanager.toggleTreeButton(rowIndex, true);
} }
closeTreeNode(rowIndex) { closeSingleNode(rowIndex) {
const rowsToHide = this.datamanager.getChildrenIndices(rowIndex); const children = this.datamanager.getImmediateChildren(rowIndex);
this.hideRows(rowsToHide); children.forEach(childIndex => {
const row = this.datamanager.getRow(childIndex);
if (row.meta.isLeaf) {
// close
this.hideRows(childIndex);
this.cellmanager.toggleTreeButton(childIndex, false);
} else {
this.closeSingleNode(childIndex);
this.hideRows(childIndex);
}
});
this.cellmanager.toggleTreeButton(rowIndex, false);
} }
getRow$(rowIndex) { getRow$(rowIndex) {

View File

@ -824,6 +824,25 @@ function linkProperties(target, source, properties) {
Object.defineProperties(target, props); Object.defineProperties(target, props);
} }
function isSet(val) {
return val !== undefined || val !== null;
}
function notSet(val) {
return !isSet(val);
}
function isNumber(val) {
return !isNaN(val);
}
function ensureArray(val) {
if (!Array.isArray(val)) {
return [val];
}
return val;
}
class DataManager { class DataManager {
constructor(options) { constructor(options) {
this.options = options; this.options = options;
@ -846,6 +865,7 @@ class DataManager {
this.prepareColumns(); this.prepareColumns();
this.prepareRows(); this.prepareRows();
this.prepareTreeRows();
this.prepareRowView(); this.prepareRowView();
this.prepareNumericColumns(); this.prepareNumericColumns();
@ -994,13 +1014,25 @@ class DataManager {
} }
} }
meta.indent = d.indent; meta.indent = d.indent || 0;
} }
return this.prepareRow(row, meta); return this.prepareRow(row, meta);
}); });
} }
prepareTreeRows() {
this.rows.forEach((row, i) => {
if (isNumber(row.meta.indent)) {
// if (i === 36) debugger;
const nextRow = this.getRow(i + 1);
row.meta.isLeaf = !nextRow ||
notSet(nextRow.meta.indent) ||
nextRow.meta.indent <= row.meta.indent;
}
});
}
prepareRowView() { prepareRowView() {
// This is order in which rows will be rendered in the table. // This is order in which rows will be rendered in the table.
// When sorting happens, only this.rowViewOrder will change // When sorting happens, only this.rowViewOrder will change
@ -1322,21 +1354,44 @@ class DataManager {
return this.getRow(rowIndex)[colIndex]; return this.getRow(rowIndex)[colIndex];
} }
getChildrenIndices(parentRowIndex) { getChildren(parentRowIndex) {
parentRowIndex = +parentRowIndex; parentRowIndex = +parentRowIndex;
const parentIndent = this.getRow(parentRowIndex).meta.indent; const parentIndent = this.getRow(parentRowIndex).meta.indent;
const out = []; const out = [];
let i = parentRowIndex + 1; for (let i = parentRowIndex + 1; i < this.rowCount; i++) {
let nextRow = this.getRow(i); const row = this.getRow(i);
let nextIndent = nextRow ? (nextRow.meta.indent || 0) : -1; if (isNaN(row.meta.indent)) continue;
while (nextIndent > parentIndent) { if (row.meta.indent > parentIndent) {
out.push(i); out.push(i);
}
i++; if (row.meta.indent === parentIndent) {
nextRow = this.getRow(i); break;
nextIndent = nextRow ? (nextRow.meta.indent || 0) : -1; }
}
return out;
}
getImmediateChildren(parentRowIndex) {
parentRowIndex = +parentRowIndex;
const parentIndent = this.getRow(parentRowIndex).meta.indent;
const out = [];
const childIndent = parentIndent + 1;
for (let i = parentRowIndex + 1; i < this.rowCount; i++) {
const row = this.getRow(i);
if (isNaN(row.meta.indent) || row.meta.indent > childIndent) continue;
if (row.meta.indent === childIndent) {
out.push(i);
}
if (row.meta.indent === parentIndent) {
break;
}
} }
return out; return out;
@ -1773,15 +1828,7 @@ class ColumnManager {
} }
getFirstColumnIndex() { getFirstColumnIndex() {
if (this.options.addCheckboxColumn && this.options.addSerialNoColumn) { return this.datamanager.getColumnIndexById('_rowIndex') + 1;
return 2;
}
if (this.options.addCheckboxColumn || this.options.addSerialNoColumn) {
return 1;
}
return 0;
} }
getHeaderCell$(colIndex) { getHeaderCell$(colIndex) {
@ -1814,14 +1861,16 @@ var getDropdownHTML = function getDropdownHTML(dropdownButton = 'v') {
class CellManager { class CellManager {
constructor(instance) { constructor(instance) {
this.instance = instance; this.instance = instance;
this.wrapper = this.instance.wrapper; linkProperties(this, this.instance, [
this.options = this.instance.options; 'wrapper',
this.style = this.instance.style; 'options',
this.bodyScrollable = this.instance.bodyScrollable; 'style',
this.columnmanager = this.instance.columnmanager; 'bodyScrollable',
this.rowmanager = this.instance.rowmanager; 'columnmanager',
this.datamanager = this.instance.datamanager; 'rowmanager',
this.keyboard = this.instance.keyboard; 'datamanager',
'keyboard'
]);
this.bindEvents(); this.bindEvents();
} }
@ -1985,30 +2034,11 @@ class CellManager {
const { rowIndex } = $.data($cell); const { rowIndex } = $.data($cell);
if ($cell.classList.contains('tree-close')) { if ($cell.classList.contains('tree-close')) {
this.rowmanager.openTreeNode(rowIndex); this.rowmanager.openSingleNode(rowIndex);
$cell.classList.remove('tree-close');
} else { } else {
this.rowmanager.closeTreeNode(rowIndex); this.rowmanager.closeSingleNode(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, {
@ -2361,17 +2391,25 @@ class CellManager {
} }
refreshCell(cell) { refreshCell(cell) {
const $cell = $(this.cellSelector(cell.colIndex, cell.rowIndex), this.bodyScrollable); const $cell = $(this.selector(cell.colIndex, cell.rowIndex), this.bodyScrollable);
$cell.innerHTML = this.getCellContent(cell); $cell.innerHTML = this.getCellContent(cell);
} }
toggleTreeButton(rowIndex, flag) {
const colIndex = this.columnmanager.getFirstColumnIndex();
const $cell = this.getCell$(colIndex, rowIndex);
if ($cell) {
$cell.classList[flag ? 'remove' : 'add']('tree-close');
}
}
isStandardCell(colIndex) { isStandardCell(colIndex) {
// Standard cells are in Sr. No and Checkbox column // Standard cells are in Sr. No and Checkbox column
return colIndex < this.columnmanager.getFirstColumnIndex(); return colIndex < this.columnmanager.getFirstColumnIndex();
} }
getCell$(colIndex, rowIndex) { getCell$(colIndex, rowIndex) {
return $(this.cellSelector(colIndex, rowIndex), this.bodyScrollable); return $(this.selector(colIndex, rowIndex), this.bodyScrollable);
} }
getAboveCell$($cell) { getAboveCell$($cell) {
@ -2519,7 +2557,7 @@ class CellManager {
`; `;
} }
cellSelector(colIndex, rowIndex) { selector(colIndex, rowIndex) {
return `.data-table-cell[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`; return `.data-table-cell[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`;
} }
} }
@ -2527,9 +2565,11 @@ class CellManager {
class RowManager { class RowManager {
constructor(instance) { constructor(instance) {
this.instance = instance; this.instance = instance;
this.options = this.instance.options; linkProperties(this, this.instance, [
this.wrapper = this.instance.wrapper; 'options',
this.bodyScrollable = this.instance.bodyScrollable; 'wrapper',
'bodyScrollable'
]);
this.bindEvents(); this.bindEvents();
this.refreshRows = promisify(this.refreshRows, this); this.refreshRows = promisify(this.refreshRows, this);
@ -2675,6 +2715,7 @@ class RowManager {
} }
hideRows(rowIndices) { hideRows(rowIndices) {
rowIndices = ensureArray(rowIndices);
rowIndices.map(rowIndex => { rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex); const $tr = this.getRow$(rowIndex);
$tr.classList.add('hide'); $tr.classList.add('hide');
@ -2682,20 +2723,33 @@ class RowManager {
} }
showRows(rowIndices) { showRows(rowIndices) {
rowIndices = ensureArray(rowIndices);
rowIndices.map(rowIndex => { rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex); const $tr = this.getRow$(rowIndex);
$tr.classList.remove('hide'); $tr.classList.remove('hide');
}); });
} }
openTreeNode(rowIndex) { openSingleNode(rowIndex) {
const rowsToShow = this.datamanager.getChildrenIndices(rowIndex); const rowsToShow = this.datamanager.getImmediateChildren(rowIndex);
this.showRows(rowsToShow); this.showRows(rowsToShow);
this.cellmanager.toggleTreeButton(rowIndex, true);
} }
closeTreeNode(rowIndex) { closeSingleNode(rowIndex) {
const rowsToHide = this.datamanager.getChildrenIndices(rowIndex); const children = this.datamanager.getImmediateChildren(rowIndex);
this.hideRows(rowsToHide); children.forEach(childIndex => {
const row = this.datamanager.getRow(childIndex);
if (row.meta.isLeaf) {
// close
this.hideRows(childIndex);
this.cellmanager.toggleTreeButton(childIndex, false);
} else {
this.closeSingleNode(childIndex);
this.hideRows(childIndex);
}
});
this.cellmanager.toggleTreeButton(rowIndex, false);
} }
getRow$(rowIndex) { getRow$(rowIndex) {

View File

@ -1,7 +1,8 @@
import { import {
copyTextToClipboard, copyTextToClipboard,
makeDataAttributeString, makeDataAttributeString,
throttle throttle,
linkProperties
} from './utils'; } from './utils';
import $ from './dom'; import $ from './dom';
import { import {
@ -11,14 +12,16 @@ import {
export default class CellManager { export default class CellManager {
constructor(instance) { constructor(instance) {
this.instance = instance; this.instance = instance;
this.wrapper = this.instance.wrapper; linkProperties(this, this.instance, [
this.options = this.instance.options; 'wrapper',
this.style = this.instance.style; 'options',
this.bodyScrollable = this.instance.bodyScrollable; 'style',
this.columnmanager = this.instance.columnmanager; 'bodyScrollable',
this.rowmanager = this.instance.rowmanager; 'columnmanager',
this.datamanager = this.instance.datamanager; 'rowmanager',
this.keyboard = this.instance.keyboard; 'datamanager',
'keyboard'
]);
this.bindEvents(); this.bindEvents();
} }
@ -182,30 +185,11 @@ export default class CellManager {
const { rowIndex } = $.data($cell); const { rowIndex } = $.data($cell);
if ($cell.classList.contains('tree-close')) { if ($cell.classList.contains('tree-close')) {
this.rowmanager.openTreeNode(rowIndex); this.rowmanager.openSingleNode(rowIndex);
$cell.classList.remove('tree-close');
} else { } else {
this.rowmanager.closeTreeNode(rowIndex); this.rowmanager.closeSingleNode(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, {
@ -558,17 +542,25 @@ export default class CellManager {
} }
refreshCell(cell) { refreshCell(cell) {
const $cell = $(this.cellSelector(cell.colIndex, cell.rowIndex), this.bodyScrollable); const $cell = $(this.selector(cell.colIndex, cell.rowIndex), this.bodyScrollable);
$cell.innerHTML = this.getCellContent(cell); $cell.innerHTML = this.getCellContent(cell);
} }
toggleTreeButton(rowIndex, flag) {
const colIndex = this.columnmanager.getFirstColumnIndex();
const $cell = this.getCell$(colIndex, rowIndex);
if ($cell) {
$cell.classList[flag ? 'remove' : 'add']('tree-close');
}
}
isStandardCell(colIndex) { isStandardCell(colIndex) {
// Standard cells are in Sr. No and Checkbox column // Standard cells are in Sr. No and Checkbox column
return colIndex < this.columnmanager.getFirstColumnIndex(); return colIndex < this.columnmanager.getFirstColumnIndex();
} }
getCell$(colIndex, rowIndex) { getCell$(colIndex, rowIndex) {
return $(this.cellSelector(colIndex, rowIndex), this.bodyScrollable); return $(this.selector(colIndex, rowIndex), this.bodyScrollable);
} }
getAboveCell$($cell) { getAboveCell$($cell) {
@ -716,7 +708,7 @@ export default class CellManager {
`; `;
} }
cellSelector(colIndex, rowIndex) { selector(colIndex, rowIndex) {
return `.data-table-cell[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`; return `.data-table-cell[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`;
} }
} }

View File

@ -406,15 +406,7 @@ export default class ColumnManager {
} }
getFirstColumnIndex() { getFirstColumnIndex() {
if (this.options.addCheckboxColumn && this.options.addSerialNoColumn) { return this.datamanager.getColumnIndexById('_rowIndex') + 1;
return 2;
}
if (this.options.addCheckboxColumn || this.options.addSerialNoColumn) {
return 1;
}
return 0;
} }
getHeaderCell$(colIndex) { getHeaderCell$(colIndex) {

View File

@ -1,6 +1,8 @@
import { import {
isNumeric, isNumeric,
promisify promisify,
isNumber,
notSet
} from './utils'; } from './utils';
export default class DataManager { export default class DataManager {
@ -25,6 +27,7 @@ export default class DataManager {
this.prepareColumns(); this.prepareColumns();
this.prepareRows(); this.prepareRows();
this.prepareTreeRows();
this.prepareRowView(); this.prepareRowView();
this.prepareNumericColumns(); this.prepareNumericColumns();
@ -173,13 +176,25 @@ export default class DataManager {
} }
} }
meta.indent = d.indent; meta.indent = d.indent || 0;
} }
return this.prepareRow(row, meta); return this.prepareRow(row, meta);
}); });
} }
prepareTreeRows() {
this.rows.forEach((row, i) => {
if (isNumber(row.meta.indent)) {
// if (i === 36) debugger;
const nextRow = this.getRow(i + 1);
row.meta.isLeaf = !nextRow ||
notSet(nextRow.meta.indent) ||
nextRow.meta.indent <= row.meta.indent;
}
});
}
prepareRowView() { prepareRowView() {
// This is order in which rows will be rendered in the table. // This is order in which rows will be rendered in the table.
// When sorting happens, only this.rowViewOrder will change // When sorting happens, only this.rowViewOrder will change
@ -501,21 +516,44 @@ export default class DataManager {
return this.getRow(rowIndex)[colIndex]; return this.getRow(rowIndex)[colIndex];
} }
getChildrenIndices(parentRowIndex) { getChildren(parentRowIndex) {
parentRowIndex = +parentRowIndex; parentRowIndex = +parentRowIndex;
const parentIndent = this.getRow(parentRowIndex).meta.indent; const parentIndent = this.getRow(parentRowIndex).meta.indent;
const out = []; const out = [];
let i = parentRowIndex + 1; for (let i = parentRowIndex + 1; i < this.rowCount; i++) {
let nextRow = this.getRow(i); const row = this.getRow(i);
let nextIndent = nextRow ? (nextRow.meta.indent || 0) : -1; if (isNaN(row.meta.indent)) continue;
while (nextIndent > parentIndent) { if (row.meta.indent > parentIndent) {
out.push(i); out.push(i);
}
i++; if (row.meta.indent === parentIndent) {
nextRow = this.getRow(i); break;
nextIndent = nextRow ? (nextRow.meta.indent || 0) : -1; }
}
return out;
}
getImmediateChildren(parentRowIndex) {
parentRowIndex = +parentRowIndex;
const parentIndent = this.getRow(parentRowIndex).meta.indent;
const out = [];
const childIndent = parentIndent + 1;
for (let i = parentRowIndex + 1; i < this.rowCount; i++) {
const row = this.getRow(i);
if (isNaN(row.meta.indent) || row.meta.indent > childIndent) continue;
if (row.meta.indent === childIndent) {
out.push(i);
}
if (row.meta.indent === parentIndent) {
break;
}
} }
return out; return out;

View File

@ -1,15 +1,19 @@
import $ from './dom'; import $ from './dom';
import { import {
makeDataAttributeString, makeDataAttributeString,
promisify promisify,
ensureArray,
linkProperties
} from './utils'; } from './utils';
export default class RowManager { export default class RowManager {
constructor(instance) { constructor(instance) {
this.instance = instance; this.instance = instance;
this.options = this.instance.options; linkProperties(this, this.instance, [
this.wrapper = this.instance.wrapper; 'options',
this.bodyScrollable = this.instance.bodyScrollable; 'wrapper',
'bodyScrollable'
]);
this.bindEvents(); this.bindEvents();
this.refreshRows = promisify(this.refreshRows, this); this.refreshRows = promisify(this.refreshRows, this);
@ -155,6 +159,7 @@ export default class RowManager {
} }
hideRows(rowIndices) { hideRows(rowIndices) {
rowIndices = ensureArray(rowIndices);
rowIndices.map(rowIndex => { rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex); const $tr = this.getRow$(rowIndex);
$tr.classList.add('hide'); $tr.classList.add('hide');
@ -162,20 +167,33 @@ export default class RowManager {
} }
showRows(rowIndices) { showRows(rowIndices) {
rowIndices = ensureArray(rowIndices);
rowIndices.map(rowIndex => { rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex); const $tr = this.getRow$(rowIndex);
$tr.classList.remove('hide'); $tr.classList.remove('hide');
}); });
} }
openTreeNode(rowIndex) { openSingleNode(rowIndex) {
const rowsToShow = this.datamanager.getChildrenIndices(rowIndex); const rowsToShow = this.datamanager.getImmediateChildren(rowIndex);
this.showRows(rowsToShow); this.showRows(rowsToShow);
this.cellmanager.toggleTreeButton(rowIndex, true);
} }
closeTreeNode(rowIndex) { closeSingleNode(rowIndex) {
const rowsToHide = this.datamanager.getChildrenIndices(rowIndex); const children = this.datamanager.getImmediateChildren(rowIndex);
this.hideRows(rowsToHide); children.forEach(childIndex => {
const row = this.datamanager.getRow(childIndex);
if (row.meta.isLeaf) {
// close
this.hideRows(childIndex);
this.cellmanager.toggleTreeButton(childIndex, false);
} else {
this.closeSingleNode(childIndex);
this.hideRows(childIndex);
}
});
this.cellmanager.toggleTreeButton(rowIndex, false);
} }
getRow$(rowIndex) { getRow$(rowIndex) {

View File

@ -183,3 +183,22 @@ export function linkProperties(target, source, properties) {
}, {}); }, {});
Object.defineProperties(target, props); Object.defineProperties(target, props);
}; };
export function isSet(val) {
return val !== undefined || val !== null;
}
export function notSet(val) {
return !isSet(val);
}
export function isNumber(val) {
return !isNaN(val);
}
export function ensureArray(val) {
if (!Array.isArray(val)) {
return [val];
}
return val;
}