import { isNumeric } from './utils'; export default class DataManager { constructor(options) { this.options = options; this.rowCount = 0; this.currentSort = { sortBy: -1, // colIndex sortOrder: 'none' // asc, desc, none }; } init(data) { let { columns, rows } = data; this.columns = this.prepareColumns(columns); this.rows = this.prepareRows(rows); this.prepareNumericColumns(); } prepareColumns(columns) { if (!Array.isArray(columns)) { throw new TypeError('`columns` must be an array'); } if (this.options.addSerialNoColumn && !this._serialNoColumnAdded) { const val = { content: 'Sr. No', editable: false, resizable: false, align: 'center' }; columns = [val].concat(columns); this._serialNoColumnAdded = true; } if (this.options.addCheckboxColumn && !this._checkboxColumnAdded) { const val = { content: '', editable: false, resizable: false, sortable: false }; columns = [val].concat(columns); this._checkboxColumnAdded = true; } // wrap the title in span columns = columns.map(column => { if (typeof column === 'string') { column = `${column}`; } else if (typeof column === 'object') { column.content = `${column.content}`; } return column; }); return prepareColumns(columns, { isHeader: 1 }); } 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'); } rows = rows.map((row, i) => { const index = this._getNextRowCount(); if (row.length < this.columns.length) { if (this._serialNoColumnAdded) { const val = (index + 1) + ''; row = [val].concat(row); } if (this._checkboxColumnAdded) { const val = ''; row = [val].concat(row); } } return prepareRow(row, index); }); return rows; } appendRows(rows) { if (Array.isArray(rows) && !Array.isArray(rows[0])) { rows = [rows]; } const _rows = this.prepareRows(rows); this.rows = this.rows.concat(_rows); } sortRows(colIndex, sortOrder = 'none') { colIndex = +colIndex; if (this.currentSort.colIndex === colIndex) { // reverse the array if only sortOrder changed if ( (this.currentSort.sortOrder === 'asc' && sortOrder === 'desc') || (this.currentSort.sortOrder === 'desc' && sortOrder === 'asc') ) { this.reverseArray(this.rows); this.currentSort.sortOrder = sortOrder; return; } } this.rows.sort((a, b) => { const _aIndex = a[0].rowIndex; const _bIndex = b[0].rowIndex; const _a = a[colIndex].content; const _b = b[colIndex].content; if (sortOrder === 'none') { return _aIndex - _bIndex; } else if (sortOrder === 'asc') { if (_a < _b) return -1; if (_a > _b) return 1; if (_a === _b) return 0; } else if (sortOrder === 'desc') { if (_a < _b) return 1; if (_a > _b) return -1; if (_a === _b) return 0; } return 0; }); this.currentSort.colIndex = colIndex; this.currentSort.sortOrder = sortOrder; } reverseArray(array) { let left = null; let right = null; let length = array.length; for (left = 0, right = length - 1; left < right; left += 1, right -= 1) { const temporary = array[left]; array[left] = array[right]; array[right] = temporary; } } getRowCount() { return this.rowCount; } _getNextRowCount() { const val = this.rowCount; this.rowCount++; return val; } getRows(start, end) { return this.rows.slice(start, end); } getColumns(skipStandardColumns) { let columns = this.columns; if (skipStandardColumns) { columns = columns.slice(this.getStandardColumnCount()); } return columns; } 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) { colIndex = +colIndex; return this.columns.find(col => col.colIndex === colIndex); } getRow(rowIndex) { rowIndex = +rowIndex; return this.rows.find(row => row[0].rowIndex === rowIndex); } getCell(colIndex, rowIndex) { rowIndex = +rowIndex; colIndex = +colIndex; return this.rows.find(row => row[0].rowIndex === rowIndex)[colIndex]; } get() { return { columns: this.columns, rows: this.rows }; } } function prepareColumns(columns, props = {}) { const _columns = columns.map(prepareCell); return _columns.map(col => Object.assign({}, col, props)); } function prepareRow(row, i) { return prepareColumns(row, { rowIndex: i }); } function prepareCell(col, i) { if (typeof col === 'string') { col = { content: col }; } return Object.assign(col, { colIndex: i }); }