datatable/src/rowmanager.js
Faris Ansari 0ebe0461e1
Rmehta cell refactor (#13)
* refactor: prepare cells

* checkbox sequence and always focus before deactivate

* don't set model

* fixes

* minor
2018-02-11 22:05:15 +05:30

198 lines
4.8 KiB
JavaScript

import $ from './dom';
import { makeDataAttributeString, promisify } from './utils';
import { getCellHTML } from './cellmanager';
export default class RowManager {
constructor(instance) {
this.instance = instance;
this.options = this.instance.options;
this.wrapper = this.instance.wrapper;
this.bodyScrollable = this.instance.bodyScrollable;
this.bindEvents();
this.refreshRows = promisify(this.refreshRows, this);
}
get datamanager() {
return this.instance.datamanager;
}
get cellmanager() {
return this.instance.cellmanager;
}
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();
}
refreshRow(row, rowIndex) {
const _row = this.datamanager.updateRow(row, rowIndex);
_row.forEach(cell => {
this.cellmanager.refreshCell(cell);
});
}
getCheckedRows() {
if (!this.checkMap) {
return [];
}
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 = this.getRow$(rowIndex);
if (!$row) return;
if (!toggle && this.bodyScrollable.classList.contains('row-highlight-all')) {
$row.classList.add('row-unhighlight');
return;
}
if (toggle && $row.classList.contains('row-unhighlight')) {
$row.classList.remove('row-unhighlight');
}
this._highlightedRows = this._highlightedRows || {};
if (toggle) {
$row.classList.add('row-highlight');
this._highlightedRows[rowIndex] = $row;
} else {
$row.classList.remove('row-highlight');
delete this._highlightedRows[rowIndex];
}
}
highlightAll(toggle = true) {
if (toggle) {
this.bodyScrollable.classList.add('row-highlight-all');
} else {
this.bodyScrollable.classList.remove('row-highlight-all');
for (const rowIndex in this._highlightedRows) {
const $row = this._highlightedRows[rowIndex];
$row.classList.remove('row-highlight');
}
this._highlightedRows = {};
}
}
getRow$(rowIndex) {
return $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
}
getTotalRows() {
return this.datamanager.getRowCount();
}
getFirstRowIndex() {
return 0;
}
getLastRowIndex() {
return this.datamanager.getRowCount() - 1;
}
scrollToRow(rowIndex) {
rowIndex = +rowIndex;
this._lastScrollTo = this._lastScrollTo || 0;
const $row = this.getRow$(rowIndex);
if ($.inViewport($row, this.bodyScrollable)) return;
const { height } = $row.getBoundingClientRect();
const { top, bottom } = this.bodyScrollable.getBoundingClientRect();
const rowsInView = Math.floor((bottom - top) / height);
let offset = 0;
if (rowIndex > this._lastScrollTo) {
offset = height * ((rowIndex + 1) - rowsInView);
} else {
offset = height * ((rowIndex + 1) - 1);
}
this._lastScrollTo = rowIndex;
$.scrollTop(this.bodyScrollable, offset);
}
}
export function getRowHTML(row, props) {
const dataAttr = makeDataAttributeString(props);
return `
<tr class="data-table-row" ${dataAttr}>
${row.map(getCellHTML).join('')}
</tr>
`;
}