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 `