Add RowManager and ColumnManager

This commit is contained in:
Faris Ansari 2017-11-06 18:25:07 +05:30
parent 785cf8f466
commit 0ccc3627ae
9 changed files with 1348 additions and 1075 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -9,6 +9,8 @@ export default class CellManager {
this.options = this.instance.options;
this.style = this.instance.style;
this.bodyScrollable = this.instance.bodyScrollable;
this.columnmanager = this.instance.columnmanager;
this.rowmanager = this.instance.rowmanager;
this.bindEvents();
}
@ -77,7 +79,7 @@ export default class CellManager {
}
let $cell = this.$focusedCell;
const { rowIndex, colIndex } = this.getCellAttr($cell);
const { rowIndex, colIndex } = $.data($cell);
if (direction === 'left') {
$cell = this.getLeftMostCell$(rowIndex);
@ -97,7 +99,7 @@ export default class CellManager {
if (!this.$focusedCell) return false;
if (!this.inViewport(this.$focusedCell)) {
const { rowIndex } = this.getCellAttr(this.$focusedCell);
const { rowIndex } = $.data(this.$focusedCell);
this.scrollToRow(rowIndex - this.getRowCountPerPage() + 2);
return true;
@ -173,9 +175,9 @@ export default class CellManager {
focusCell($cell) {
if (!$cell) return;
const { colIndex } = this.getCellAttr($cell);
const { colIndex, isHeader } = $.data($cell);
if (this.isStandardCell(colIndex)) {
if (this.isStandardCell(colIndex) || isHeader) {
return;
}
@ -197,8 +199,8 @@ export default class CellManager {
}
highlightRowColumnHeader($cell) {
const { colIndex, rowIndex } = this.getCellAttr($cell);
const _colIndex = this.instance.getSerialColumnIndex();
const { colIndex, rowIndex } = $.data($cell);
const _colIndex = this.columnmanager.getSerialColumnIndex();
const colHeaderSelector = `.data-table-header .data-table-col[data-col-index="${colIndex}"]`;
const rowHeaderSelector = `.data-table-col[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
@ -226,6 +228,8 @@ export default class CellManager {
};
_selectArea($cell1, $cell2) {
if ($cell1 === $cell2) return false;
const cells = this.getCellsInRange($cell1, $cell2);
if (!cells) return false;
@ -246,8 +250,8 @@ export default class CellManager {
return false;
}
const cell1 = this.getCellAttr($cell1);
const cell2 = this.getCellAttr($cell2);
const cell1 = $.data($cell1);
const cell2 = $.data($cell2);
colIndex1 = cell1.colIndex;
rowIndex1 = cell1.rowIndex;
@ -300,15 +304,15 @@ export default class CellManager {
}
activateEditing($cell) {
const { rowIndex, colIndex } = this.getCellAttr($cell);
const col = this.instance.getColumn(colIndex);
const { rowIndex, colIndex } = $.data($cell);
const col = this.instance.columnmanager.getColumn(colIndex);
if (col && col.editable === false) {
return;
}
if (this.$editingCell) {
const { _rowIndex, _colIndex } = this.getCellAttr(this.$editingCell);
const { _rowIndex, _colIndex } = $.data(this.$editingCell);
if (rowIndex === _rowIndex && colIndex === _colIndex) {
// editing the same cell
@ -364,7 +368,7 @@ export default class CellManager {
}
submitEditing($cell) {
const { rowIndex, colIndex } = this.getCellAttr($cell);
const { rowIndex, colIndex } = $.data($cell);
if ($cell) {
const editing = this.currentCellEditing;
@ -428,7 +432,7 @@ export default class CellManager {
isStandardCell(colIndex) {
// Standard cells are in Sr. No and Checkbox column
return colIndex < this.instance.getFirstColumnIndex();
return colIndex < this.columnmanager.getFirstColumnIndex();
}
getCell$(colIndex, rowIndex) {
@ -436,14 +440,14 @@ export default class CellManager {
}
getAboveCell$($cell) {
const { colIndex } = this.getCellAttr($cell);
const { colIndex } = $.data($cell);
const $aboveRow = $cell.parentElement.previousElementSibling;
return $(`[data-col-index="${colIndex}"]`, $aboveRow);
}
getBelowCell$($cell) {
const { colIndex } = this.getCellAttr($cell);
const { colIndex } = $.data($cell);
const $belowRow = $cell.parentElement.nextElementSibling;
return $(`[data-col-index="${colIndex}"]`, $belowRow);
@ -458,19 +462,19 @@ export default class CellManager {
}
getLeftMostCell$(rowIndex) {
return this.getCell$(rowIndex, this.instance.getFirstColumnIndex());
return this.getCell$(rowIndex, this.columnmanager.getFirstColumnIndex());
}
getRightMostCell$(rowIndex) {
return this.getCell$(rowIndex, this.instance.getLastColumnIndex());
return this.getCell$(rowIndex, this.columnmanager.getLastColumnIndex());
}
getTopMostCell$(colIndex) {
return this.getCell$(0, colIndex);
return this.getCell$(this.rowmanager.getFirstRowIndex(), colIndex);
}
getBottomMostCell$(colIndex) {
return this.getCell$(this.instance.getLastRowIndex(), colIndex);
return this.getCell$(this.rowmanager.getLastRowIndex(), colIndex);
}
getCell(colIndex, rowIndex) {
@ -486,12 +490,12 @@ export default class CellManager {
}
inViewport($cell) {
let colIndex, rowIndex;
let colIndex, rowIndex; // eslint-disable-line
if (typeof $cell === 'number') {
[colIndex, rowIndex] = arguments;
} else {
let cell = this.getCellAttr($cell);
let cell = $.data($cell);
colIndex = cell.colIndex;
rowIndex = cell.rowIndex;
@ -511,7 +515,7 @@ export default class CellManager {
}
scrollToCell($cell) {
const { rowIndex } = this.getCellAttr($cell);
const { rowIndex } = $.data($cell);
this.scrollToRow(rowIndex);
}

271
src/columnmanager.js Normal file
View File

@ -0,0 +1,271 @@
import $ from './dom';
import { getDefault, getHeaderHTML } from './utils';
export default class ColumnManager {
constructor(instance) {
this.instance = instance;
this.options = this.instance.options;
this.header = this.instance.header;
this.datamanager = this.instance.datamanager;
this.style = this.instance.style;
this.wrapper = this.instance.wrapper;
this.rowmanager = this.instance.rowmanager;
this.bindEvents();
}
renderHeader() {
const columns = this.datamanager.getColumns();
this.header.innerHTML = getHeaderHTML(columns);
}
bindEvents() {
this.bindResizeColumn();
this.bindSortColumn();
}
bindResizeColumn() {
let isDragging = false;
let $currCell, startWidth, startX;
$.on(this.header, 'mousedown', '.data-table-col', (e, $cell) => {
$currCell = $cell;
const { colIndex } = $.data($currCell);
const col = this.getColumn(colIndex);
if (col && col.resizable === false) {
return;
}
isDragging = true;
startWidth = $.style($('.content', $currCell), 'width');
startX = e.pageX;
});
$.on(document.body, 'mouseup', (e) => {
if (!$currCell) return;
isDragging = false;
const { colIndex } = $.data($currCell);
const width = $.style($('.content', $currCell), 'width');
this.setColumnWidth(colIndex, width);
this.instance.setBodyWidth();
$currCell = null;
});
$.on(document.body, 'mousemove', (e) => {
if (!isDragging) return;
const finalWidth = startWidth + (e.pageX - startX);
const { colIndex } = $.data($currCell);
if (this.getColumnMinWidth(colIndex) > finalWidth) {
// don't resize past minWidth
return;
}
this.setColumnHeaderWidth(colIndex, finalWidth);
});
}
bindSortColumn() {
$.on(this.header, 'click', '.data-table-col .content span', (e, span) => {
const $cell = span.closest('.data-table-col');
let { colIndex, sortOrder } = $.data($cell);
sortOrder = getDefault(sortOrder, 'none');
const col = this.getColumn(colIndex);
if (col && col.sortable === false) {
return;
}
// reset sort indicator
$('.sort-indicator', this.header).textContent = '';
$.each('.data-table-col', this.header).map($cell => {
$.data($cell, {
sortOrder: 'none'
});
});
let nextSortOrder, textContent;
if (sortOrder === 'none') {
nextSortOrder = 'asc';
textContent = '▲';
} else if (sortOrder === 'asc') {
nextSortOrder = 'desc';
textContent = '▼';
} else if (sortOrder === 'desc') {
nextSortOrder = 'none';
textContent = '';
}
$.data($cell, {
sortOrder: nextSortOrder
});
$('.sort-indicator', $cell).textContent = textContent;
if (this.events && this.events.onSort) {
this.events.onSort(colIndex, nextSortOrder);
} else {
this.sortRows(colIndex, nextSortOrder);
this.rowmanager.refreshRows();
}
});
}
setDimensions() {
this.setHeaderStyle();
this.setupMinWidth();
this.setNaturalColumnWidth();
this.distributeRemainingWidth();
this.setColumnAlignments();
}
setHeaderStyle() {
if (!this.options.takeAvailableSpace) {
// setting width as 0 will ensure that the
// header doesn't take the available space
$.style(this.header, {
width: 0
});
}
$.style(this.header, {
margin: 0
});
}
setupMinWidth() {
// cache minWidth for each column
this.minWidthMap = getDefault(this.minWidthMap, []);
$.each('.data-table-col', this.header).map(col => {
const width = $.style($('.content', col), 'width');
const { colIndex } = $.data(col);
if (!this.minWidthMap[colIndex]) {
// only set this once
this.minWidthMap[colIndex] = width;
}
});
}
setNaturalColumnWidth() {
// 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 => {
let width = $.style($('.content', $cell), 'width');
const height = $.style($('.content', $cell), 'height');
const { colIndex } = $.data($cell);
const minWidth = this.getColumnMinWidth(colIndex);
if (width < minWidth) {
width = minWidth;
}
this.setColumnWidth(colIndex, width);
this.setDefaultCellHeight(height);
});
}
distributeRemainingWidth() {
if (!this.options.takeAvailableSpace) return;
const wrapperWidth = $.style(this.instance.datatableWrapper, 'width');
const headerWidth = $.style(this.header, 'width');
if (headerWidth >= wrapperWidth) {
// don't resize, horizontal scroll takes place
return;
}
const deltaWidth = (wrapperWidth - headerWidth) / this.datamanager.getColumnCount(true);
this.datamanager.getColumns(true).map(col => {
const width = $.style(this.getColumnHeaderElement(col.colIndex), 'width');
let finalWidth = Math.min(width + deltaWidth) - 2;
this.setColumnHeaderWidth(col.colIndex, finalWidth);
this.setColumnWidth(col.colIndex, finalWidth);
});
this.instance.setBodyWidth();
}
setDefaultCellHeight(height) {
this.style.setStyle('.data-table-col .content', {
height: height + 'px'
});
}
setColumnAlignments() {
// align columns
this.getColumns()
.map(column => {
if (column.align && ['left', 'center', 'right'].includes(column.align)) {
this.style.setStyle(`.data-table [data-col-index="${column.colIndex}"]`, {
'text-align': column.align
});
}
});
}
sortRows(colIndex, sortOrder) {
this.datamanager.sortRows(colIndex, sortOrder);
}
getColumn(colIndex) {
return this.datamanager.getColumn(colIndex);
}
getColumns() {
return this.datamanager.getColumns();
}
setColumnWidth(colIndex, width) {
const selector = `[data-col-index="${colIndex}"] .content, [data-col-index="${colIndex}"] .edit-cell`;
this.style.setStyle(selector, {
width: width + 'px'
});
}
setColumnHeaderWidth(colIndex, width) {
this.style.setStyle(`[data-col-index="${colIndex}"][data-is-header] .content`, {
width: width + 'px'
});
}
getColumnMinWidth(colIndex) {
colIndex = +colIndex;
return this.minWidthMap && this.minWidthMap[colIndex];
}
getFirstColumnIndex() {
if (this.options.addCheckboxColumn && this.options.addSerialNoColumn) {
return 2;
}
if (this.options.addCheckboxColumn || this.options.addSerialNoColumn) {
return 1;
}
return 0;
}
getLastColumnIndex() {
return this.datamanager.getColumnCount() - 1;
}
getColumnHeaderElement(colIndex) {
colIndex = +colIndex;
if (colIndex < 0) return null;
return $(`.data-table-col[data-is-header][data-col-index="${colIndex}"]`, this.wrapper);
}
getSerialColumnIndex() {
const columns = this.datamanager.getColumns();
return columns.findIndex(column => column.content.includes('Sr. No'));
}
}

View File

@ -1,3 +1,4 @@
import { isNumeric } from './utils';
export default class DataManager {
constructor(options) {
@ -14,6 +15,8 @@ export default class DataManager {
this.columns = this.prepareColumns(columns);
this.rows = this.prepareRows(rows);
this.prepareNumericColumns();
}
prepareColumns(columns) {
@ -25,7 +28,8 @@ export default class DataManager {
const val = {
content: 'Sr. No',
editable: false,
resizable: false
resizable: false,
align: 'center'
};
columns = [val].concat(columns);
@ -60,6 +64,19 @@ export default class DataManager {
});
}
prepareNumericColumns() {
const row0 = this.getRow(0);
this.columns = this.columns.map((column, i) => {
const cellValue = row0[i].content;
if (!column.align && cellValue && isNumeric(cellValue)) {
column.align = 'right';
}
return column;
});
}
prepareRows(rows) {
if (!Array.isArray(rows) || !Array.isArray(rows[0])) {
throw new TypeError('`rows` must be an array of arrays');
@ -164,12 +181,36 @@ export default class DataManager {
return this.rows.slice(start, end);
}
getColumns() {
return this.columns;
getColumns(skipStandardColumns) {
let columns = this.columns;
if (skipStandardColumns) {
columns = columns.slice(this.getStandardColumnCount());
}
return columns;
}
getColumnCount() {
return this.columns.length;
getStandardColumnCount() {
if (this.options.addCheckboxColumn && this.options.addSerialNoColumn) {
return 2;
}
if (this.options.addCheckboxColumn || this.options.addSerialNoColumn) {
return 1;
}
return 0;
}
getColumnCount(skipStandardColumns) {
let val = this.columns.length;
if (skipStandardColumns) {
val = val - this.getStandardColumnCount();
}
return val;
}
getColumn(colIndex) {

View File

@ -1,14 +1,14 @@
import {
getHeaderHTML,
getBodyHTML,
getRowHTML,
getDefault
getRowHTML
} from './utils';
import $ from './dom';
import DataManager from './datamanager';
import CellManager from './cellmanager';
import ColumnManager from './columnmanager';
import RowManager from './rowmanager';
import Style from './style';
import './style.scss';
@ -24,7 +24,7 @@ const DEFAULT_OPTIONS = {
addCheckboxColumn: true,
enableClusterize: true,
enableLogs: false,
takeAvailableSpace: false
takeAvailableSpace: true
};
export default class DataTable {
@ -38,13 +38,13 @@ export default class DataTable {
this.options = Object.assign({}, DEFAULT_OPTIONS, options);
// custom user events
this.events = this.options.events;
// map of checked rows
this.checkMap = [];
// make dom, make style, bind events
this.make();
this.prepare();
this.style = new Style(this.wrapper);
this.datamanager = new DataManager(this.options);
this.rowmanager = new RowManager(this);
this.columnmanager = new ColumnManager(this);
this.cellmanager = new CellManager(this);
if (this.options.data) {
@ -52,13 +52,11 @@ export default class DataTable {
}
}
make() {
this.makeDom();
this.makeStyle();
this.bindEvents();
prepare() {
this.prepareDom();
}
makeDom() {
prepareDom() {
this.wrapper.innerHTML = `
<div class="data-table">
<table class="data-table-header">
@ -74,6 +72,7 @@ export default class DataTable {
</div>
`;
this.datatableWrapper = $('.data-table', this.wrapper);
this.header = $('.data-table-header', this.wrapper);
this.bodyScrollable = $('.body-scrollable', this.wrapper);
}
@ -85,7 +84,7 @@ export default class DataTable {
appendRows(rows) {
this.datamanager.appendRows(rows);
this.render();
this.rowmanager.refreshRows();
}
render() {
@ -95,9 +94,7 @@ export default class DataTable {
}
renderHeader() {
const columns = this.datamanager.getColumns();
this.header.innerHTML = getHeaderHTML(columns);
this.columnmanager.renderHeader();
}
renderBody() {
@ -119,8 +116,6 @@ export default class DataTable {
}
renderBodyWithClusterize() {
const self = this;
// empty body
this.bodyScrollable.innerHTML = `
<table class="data-table-body">
@ -142,8 +137,8 @@ export default class DataTable {
scrollElem: this.bodyScrollable,
contentElem: $('tbody', this.bodyScrollable),
callbacks: {
clusterChanged() {
self.highlightCheckedRows();
clusterChanged: () => {
this.rowmanager.highlightCheckedRows();
}
}
});
@ -192,59 +187,8 @@ export default class DataTable {
return rows.map((row) => getRowHTML(row, { rowIndex: row[0].rowIndex }));
}
refreshRows() {
this.renderBody();
this.setDimensions();
}
bindEvents() {
this.bindResizeColumn();
this.bindSortColumn();
this.bindCheckbox();
}
setDimensions() {
const self = this;
if (!this.options.takeAvailableSpace) {
// setting width as 0 will ensure that the
// header doesn't take the available space
$.style(this.header, {
width: 0
});
}
$.style(this.header, {
margin: 0
});
// cache minWidth for each column
this.minWidthMap = getDefault(this.minWidthMap, []);
$.each('.data-table-col', this.header).map(col => {
const width = $.style($('.content', col), 'width');
const { colIndex } = $.data(col);
if (!self.minWidthMap[colIndex]) {
// only set this once
self.minWidthMap[colIndex] = width;
}
});
// 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 => {
let width = $.style($('.content', $cell), 'width');
const height = $.style($('.content', $cell), 'height');
const { colIndex } = self.getCellAttr($cell);
const minWidth = self.getColumnMinWidth(colIndex);
if (width < minWidth) {
width = minWidth;
}
self.setColumnWidth(colIndex, width);
self.setDefaultCellHeight(height);
});
this.columnmanager.setDimensions();
this.setBodyWidth();
@ -252,315 +196,19 @@ export default class DataTable {
marginTop: $.style(this.header, 'height') + 'px'
});
// center align Sr. No column
if (this.options.addSerialNoColumn) {
const index = this.getSerialColumnIndex();
this.style.setStyle(`.data-table [data-col-index="${index}"]`, {
'text-align': 'center'
});
}
$.style($('table', this.bodyScrollable), {
margin: 0
});
}
bindResizeColumn() {
const self = this;
let isDragging = false;
let $currCell, startWidth, startX;
$.on(this.header, 'mousedown', '.data-table-col', (e, cell) => {
$currCell = cell;
const { colIndex } = this.getCellAttr($currCell);
const col = self.getColumn(colIndex);
if (col && col.resizable === false) {
return;
}
isDragging = true;
startWidth = $.style($('.content', $currCell), 'width');
startX = e.pageX;
});
$.on(document.body, 'mouseup', (e) => {
if (!$currCell) return;
isDragging = false;
const { colIndex } = this.getCellAttr($currCell);
const width = $.style($('.content', $currCell), 'width');
self.setColumnWidth(colIndex, width);
self.setBodyWidth();
$currCell = null;
});
$.on(document.body, 'mousemove', (e) => {
if (!isDragging) return;
const finalWidth = startWidth + (e.pageX - startX);
const { colIndex } = this.getCellAttr($currCell);
if (self.getColumnMinWidth(colIndex) > finalWidth) {
// don't resize past minWidth
return;
}
self.setColumnHeaderWidth(colIndex, finalWidth);
});
}
bindSortColumn() {
const self = this;
$.on(this.header, 'click', '.data-table-col .content span', (e, span) => {
const $cell = span.closest('.data-table-col');
let { colIndex, sortOrder } = this.getCellAttr($cell);
sortOrder = getDefault(sortOrder, 'none');
const col = self.getColumn(colIndex);
if (col && col.sortable === false) {
return;
}
// reset sort indicator
$('.sort-indicator', this.header).textContent = '';
$.each('.data-table-col', this.header).map($cell => {
$cell.setAttribute('data-sort-order', 'none');
});
if (sortOrder === 'none') {
$cell.setAttribute('data-sort-order', 'asc');
$('.sort-indicator', $cell).textContent = '▲';
} else if (sortOrder === 'asc') {
$cell.setAttribute('data-sort-order', 'desc');
$('.sort-indicator', $cell).textContent = '▼';
} else if (sortOrder === 'desc') {
$cell.setAttribute('data-sort-order', 'none');
$('.sort-indicator', $cell).textContent = '';
}
// sortWith this action
sortOrder = $cell.getAttribute('data-sort-order');
if (self.events && self.events.onSort) {
self.events.onSort(colIndex, sortOrder);
} else {
self.sortRows(colIndex, sortOrder);
self.refreshRows();
}
});
}
sortRows(colIndex, sortOrder) {
this.datamanager.sortRows(colIndex, sortOrder);
}
bindCheckbox() {
if (!this.options.addCheckboxColumn) return;
$.on(this.wrapper, 'click', '.data-table-col[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
const $cell = $checkbox.closest('.data-table-col');
const { rowIndex, isHeader } = this.getCellAttr($cell);
const checked = $checkbox.checked;
if (isHeader) {
this.checkAll(checked);
} else {
this.checkRow(rowIndex, checked);
}
});
}
getCheckedRows() {
return this.checkMap
.map((c, rowIndex) => {
if (c) {
return rowIndex;
}
return null;
})
.filter(c => {
return c !== null || c !== undefined;
});
}
highlightCheckedRows() {
this.getCheckedRows()
.map(rowIndex => this.checkRow(rowIndex, true));
}
checkRow(rowIndex, toggle) {
const value = toggle ? 1 : 0;
// update internal map
this.checkMap[rowIndex] = value;
// set checkbox value explicitly
$.each(`.data-table-col[data-row-index="${rowIndex}"][data-col-index="0"] [type="checkbox"]`, this.bodyScrollable)
.map(input => {
input.checked = toggle;
});
// highlight row
this.highlightRow(rowIndex, toggle);
}
checkAll(toggle) {
const value = toggle ? 1 : 0;
// update internal map
if (toggle) {
this.checkMap = Array.from(Array(this.getTotalRows())).map(c => value);
} else {
this.checkMap = [];
}
// set checkbox value
$.each('.data-table-col[data-col-index="0"] [type="checkbox"]', this.bodyScrollable)
.map(input => {
input.checked = toggle;
});
// highlight all
this.highlightAll(toggle);
}
highlightRow(rowIndex, toggle = true) {
const $row = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
if (toggle) {
$row.classList.add('row-highlight');
} else {
$row.classList.remove('row-highlight');
}
}
highlightAll(toggle = true) {
if (toggle) {
this.bodyScrollable.classList.add('row-highlight-all');
} else {
this.bodyScrollable.classList.remove('row-highlight-all');
}
}
setColumnWidth(colIndex, width) {
// set width for content
this.style.setStyle(`[data-col-index="${colIndex}"] .content`, {
width: width + 'px'
});
// set width for edit cell
this.style.setStyle(`[data-col-index="${colIndex}"] .edit-cell`, {
width: width + 'px'
});
}
setColumnHeaderWidth(colIndex, width) {
this.style.setStyle(`[data-col-index="${colIndex}"][data-is-header] .content`, {
width: width + 'px'
});
}
setDefaultCellHeight(height) {
this.style.setStyle('.data-table-col .content', {
height: height + 'px'
});
}
setRowHeight(rowIndex, height) {
this.style.setStyle(`[data-row-index="${rowIndex}"] .content`, {
height: height + 'px'
});
}
setColumnWidths() {
const availableWidth = this.wrapper.width();
const headerWidth = this.header.width();
if (headerWidth > availableWidth) {
// don't resize, horizontal scroll takes place
return;
}
const columns = this.datamanager.getColumns();
const deltaWidth = (availableWidth - headerWidth) / this.datamanager.getColumnCount();
columns.map(col => {
const width = $.style(this.getColumnHeaderElement(col.colIndex), 'width');
let finalWidth = width + deltaWidth - 16;
if (this.options.addSerialNoColumn && col.colIndex === 0) {
return;
}
this.setColumnHeaderWidth(col.colIndex, finalWidth);
this.setColumnWidth(col.colIndex, finalWidth);
});
this.setBodyWidth();
}
setBodyWidth() {
const width = $.style(this.header, 'width');
$.style(this.bodyScrollable, { width });
}
makeStyle() {
this.style = new Style(this.wrapper);
}
getColumn(colIndex) {
return this.datamanager.getColumn(colIndex);
}
getRow(rowIndex) {
return this.datamanager.getRow(rowIndex);
}
getCell(colIndex, rowIndex) {
return this.datamanager.getCell(colIndex, rowIndex);
$.style(this.bodyScrollable, { width: width + 'px' });
}
getColumnHeaderElement(colIndex) {
colIndex = +colIndex;
if (colIndex < 0) return null;
return $(`.data-table-col[data-is-header][data-col-index="${colIndex}"]`, this.wrapper);
}
getColumnMinWidth(colIndex) {
colIndex = +colIndex;
return this.minWidthMap && this.minWidthMap[colIndex];
}
getCellAttr($cell) {
return $.data($cell);
}
getTotalRows() {
return this.datamanager.getRowCount();
}
getFirstColumnIndex() {
if (this.options.addCheckboxColumn && this.options.addSerialNoColumn) {
return 2;
}
if (this.options.addCheckboxColumn || this.options.addSerialNoColumn) {
return 1;
}
return 0;
}
getLastColumnIndex() {
return this.datamanager.getColumnCount() - 1;
}
getLastRowIndex() {
return this.datamanager.getRowCount() - 1;
}
getSerialColumnIndex() {
const columns = this.datamanager.getColumns();
return columns.findIndex(column => column.content.includes('Sr. No'));
return this.columnmanager.getColumnHeaderElement(colIndex);
}
getViewportHeight() {

View File

@ -91,8 +91,14 @@ $.fire = (target, type, properties) => {
return target.dispatchEvent(evt);
};
$.data = (element) => {
return element.dataset;
$.data = (element, attrs) => { // eslint-disable-line
if (!attrs) {
return element.dataset;
}
for (const attr in attrs) {
element.dataset[attr] = attrs[attr];
}
};
$.style = (elements, styleMap) => { // eslint-disable-line

120
src/rowmanager.js Normal file
View File

@ -0,0 +1,120 @@
import $ from './dom';
export default class RowManager {
constructor(instance) {
this.instance = instance;
this.options = this.instance.options;
this.wrapper = this.instance.wrapper;
this.datamanager = this.instance.datamanager;
this.bindEvents();
}
bindEvents() {
this.bindCheckbox();
}
bindCheckbox() {
if (!this.options.addCheckboxColumn) return;
// map of checked rows
this.checkMap = [];
$.on(this.wrapper, 'click', '.data-table-col[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
const $cell = $checkbox.closest('.data-table-col');
const { rowIndex, isHeader } = $.data($cell);
const checked = $checkbox.checked;
if (isHeader) {
this.checkAll(checked);
} else {
this.checkRow(rowIndex, checked);
}
});
}
refreshRows() {
this.instance.renderBody();
this.instance.setDimensions();
}
getCheckedRows() {
return this.checkMap
.map((c, rowIndex) => {
if (c) {
return rowIndex;
}
return null;
})
.filter(c => {
return c !== null || c !== undefined;
});
}
highlightCheckedRows() {
this.getCheckedRows()
.map(rowIndex => this.checkRow(rowIndex, true));
}
checkRow(rowIndex, toggle) {
const value = toggle ? 1 : 0;
// update internal map
this.checkMap[rowIndex] = value;
// set checkbox value explicitly
$.each(`.data-table-col[data-row-index="${rowIndex}"][data-col-index="0"] [type="checkbox"]`, this.bodyScrollable)
.map(input => {
input.checked = toggle;
});
// highlight row
this.highlightRow(rowIndex, toggle);
}
checkAll(toggle) {
const value = toggle ? 1 : 0;
// update internal map
if (toggle) {
this.checkMap = Array.from(Array(this.getTotalRows())).map(c => value);
} else {
this.checkMap = [];
}
// set checkbox value
$.each('.data-table-col[data-col-index="0"] [type="checkbox"]', this.bodyScrollable)
.map(input => {
input.checked = toggle;
});
// highlight all
this.highlightAll(toggle);
}
highlightRow(rowIndex, toggle = true) {
const $row = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
if (toggle) {
$row.classList.add('row-highlight');
} else {
$row.classList.remove('row-highlight');
}
}
highlightAll(toggle = true) {
if (toggle) {
this.bodyScrollable.classList.add('row-highlight-all');
} else {
this.bodyScrollable.classList.remove('row-highlight-all');
}
}
getTotalRows() {
return this.datamanager.getRowCount();
}
getFirstRowIndex() {
return 0;
}
getLastRowIndex() {
return this.datamanager.getRowCount() - 1;
}
}

View File

@ -255,6 +255,10 @@ function copyTextToClipboard(text) {
document.body.removeChild(textArea);
}
function isNumeric(val) {
return !isNaN(val);
}
export default {
getHeaderHTML,
getBodyHTML,
@ -272,5 +276,6 @@ export default {
escapeRegExp,
getCellContent,
copyTextToClipboard,
camelCaseToDash
camelCaseToDash,
isNumeric
};