UNPKG

tabulator-tables

Version:

Interactive table generation JavaScript library

366 lines (292 loc) 8.86 kB
import CoreFeature from '../../core/CoreFeature.js'; import RangeComponent from "./RangeComponent"; export default class Range extends CoreFeature{ constructor(table, rangeManager, start, end) { super(table); this.rangeManager = rangeManager; this.element = null; this.initialized = false; this.initializing = { start:false, end:false, }; this.destroyed = false; this.top = 0; this.bottom = 0; this.left = 0; this.right = 0; this.table = table; this.start = {row:0, col:0}; this.end = {row:0, col:0}; if(this.rangeManager.rowHeader){ this.left = 1; this.right = 1; this.start.col = 1; this.end.col = 1; } this.initElement(); setTimeout(() => { this.initBounds(start, end); }); } initElement(){ this.element = document.createElement("div"); this.element.classList.add("tabulator-range"); } initBounds(start, end){ this._updateMinMax(); if(start){ this.setBounds(start, end || start); } } /////////////////////////////////// /////// Boundary Setup /////// /////////////////////////////////// setStart(row, col) { if(this.start.row !== row || this.start.col !== col){ this.start.row = row; this.start.col = col; this.initializing.start = true; this._updateMinMax(); } } setEnd(row, col) { if(this.end.row !== row || this.end.col !== col){ this.end.row = row; this.end.col = col; this.initializing.end = true; this._updateMinMax(); } } setBounds(start, end, visibleRows){ if(start){ this.setStartBound(start); } this.setEndBound(end || start); this.rangeManager.layoutElement(visibleRows); } setStartBound(element){ var row, col; if (element.type === "column") { if(this.rangeManager.columnSelection){ this.setStart(0, element.getPosition() - 1); } }else{ row = element.row.position - 1; col = element.column.getPosition() - 1; if (element.column === this.rangeManager.rowHeader) { this.setStart(row, 1); } else { this.setStart(row, col); } } } setEndBound(element){ var rowsCount = this._getTableRows().length, row, col, isRowHeader; if (element.type === "column") { if(this.rangeManager.columnSelection){ if (this.rangeManager.selecting === "column") { this.setEnd(rowsCount - 1, element.getPosition() - 1); } else if (this.rangeManager.selecting === "cell") { this.setEnd(0, element.getPosition() - 1); } } }else{ row = element.row.position - 1; col = element.column.getPosition() - 1; isRowHeader = element.column === this.rangeManager.rowHeader; if (this.rangeManager.selecting === "row") { this.setEnd(row, this._getTableColumns().length - 1); } else if (this.rangeManager.selecting !== "row" && isRowHeader) { this.setEnd(row, 0); } else if (this.rangeManager.selecting === "column") { this.setEnd(rowsCount - 1, col); } else { this.setEnd(row, col); } } } _updateMinMax() { this.top = Math.min(this.start.row, this.end.row); this.bottom = Math.max(this.start.row, this.end.row); this.left = Math.min(this.start.col, this.end.col); this.right = Math.max(this.start.col, this.end.col); if(this.initialized){ this.dispatchExternal("rangeChanged", this.getComponent()); }else{ if(this.initializing.start && this.initializing.end){ this.initialized = true; this.dispatchExternal("rangeAdded", this.getComponent()); } } } _getTableColumns() { return this.table.columnManager.getVisibleColumnsByIndex(); } _getTableRows() { return this.table.rowManager.getDisplayRows().filter(row=> row.type === "row"); } /////////////////////////////////// /////// Rendering /////// /////////////////////////////////// layout() { var _vDomTop = this.table.rowManager.renderer.vDomTop, _vDomBottom = this.table.rowManager.renderer.vDomBottom, _vDomLeft = this.table.columnManager.renderer.leftCol, _vDomRight = this.table.columnManager.renderer.rightCol, top, bottom, left, right, topLeftCell, bottomRightCell, topLeftCellEl, bottomRightCellEl, topLeftRowEl, bottomRightRowEl; if(this.table.options.renderHorizontal === "virtual" && this.rangeManager.rowHeader) { _vDomRight += 1; } if (_vDomTop == null) { _vDomTop = 0; } if (_vDomBottom == null) { _vDomBottom = Infinity; } if (_vDomLeft == null) { _vDomLeft = 0; } if (_vDomRight == null) { _vDomRight = Infinity; } if (this.overlaps(_vDomLeft, _vDomTop, _vDomRight, _vDomBottom)) { top = Math.max(this.top, _vDomTop); bottom = Math.min(this.bottom, _vDomBottom); left = Math.max(this.left, _vDomLeft); right = Math.min(this.right, _vDomRight); topLeftCell = this.rangeManager.getCell(top, left); bottomRightCell = this.rangeManager.getCell(bottom, right); topLeftCellEl = topLeftCell.getElement(); bottomRightCellEl = bottomRightCell.getElement(); topLeftRowEl = topLeftCell.row.getElement(); bottomRightRowEl = bottomRightCell.row.getElement(); this.element.classList.add("tabulator-range-active"); // this.element.classList.toggle("tabulator-range-active", this === this.rangeManager.activeRange); if(this.table.rtl){ this.element.style.right = topLeftRowEl.offsetWidth - topLeftCellEl.offsetLeft - topLeftCellEl.offsetWidth + "px"; this.element.style.width = topLeftCellEl.offsetLeft + topLeftCellEl.offsetWidth - bottomRightCellEl.offsetLeft + "px"; }else{ this.element.style.left = topLeftRowEl.offsetLeft + topLeftCellEl.offsetLeft + "px"; this.element.style.width = bottomRightCellEl.offsetLeft + bottomRightCellEl.offsetWidth - topLeftCellEl.offsetLeft + "px"; } this.element.style.top = topLeftRowEl.offsetTop + "px"; this.element.style.height = bottomRightRowEl.offsetTop + bottomRightRowEl.offsetHeight - topLeftRowEl.offsetTop + "px"; } } atTopLeft(cell) { return cell.row.position - 1 === this.top && cell.column.getPosition() - 1 === this.left; } atBottomRight(cell) { return cell.row.position - 1 === this.bottom && cell.column.getPosition() - 1 === this.right; } occupies(cell) { return this.occupiesRow(cell.row) && this.occupiesColumn(cell.column); } occupiesRow(row) { return this.top <= row.position - 1 && row.position - 1 <= this.bottom; } occupiesColumn(col) { return this.left <= col.getPosition() - 1 && col.getPosition() - 1 <= this.right; } overlaps(left, top, right, bottom) { if ((this.left > right || left > this.right) || (this.top > bottom || top > this.bottom)){ return false; } return true; } getData() { var data = [], rows = this.getRows(), columns = this.getColumns(); rows.forEach((row) => { var rowData = row.getData(), result = {}; columns.forEach((column) => { result[column.field] = rowData[column.field]; }); data.push(result); }); return data; } getCells(structured, component) { var cells = [], rows = this.getRows(), columns = this.getColumns(); if (structured) { cells = rows.map((row) => { var arr = []; row.getCells().forEach((cell) => { if (columns.includes(cell.column)) { arr.push(component ? cell.getComponent() : cell); } }); return arr; }); } else { rows.forEach((row) => { row.getCells().forEach((cell) => { if (columns.includes(cell.column)) { cells.push(component ? cell.getComponent() : cell); } }); }); } return cells; } getStructuredCells() { return this.getCells(true, true); } getRows() { return this._getTableRows().slice(this.top, this.bottom + 1); } getColumns() { return this._getTableColumns().slice(this.left, this.right + 1); } clearValues(){ var cells = this.getCells(); var clearValue = this.table.options.selectableRangeClearCellsValue; this.table.blockRedraw(); cells.forEach((cell) => { cell.setValue(clearValue); }); this.table.restoreRedraw(); } getBounds(component){ var cells = this.getCells(false, component), output = { start:null, end:null, }; if(cells.length){ output.start = cells[0]; output.end = cells[cells.length - 1]; }else{ console.warn("No bounds defined on range"); } return output; } getComponent() { if (!this.component) { this.component = new RangeComponent(this); } return this.component; } destroy(notify) { this.destroyed = true; this.element.remove(); if(notify){ this.rangeManager.rangeRemoved(this); } if(this.initialized){ this.dispatchExternal("rangeRemoved", this.getComponent()); } } destroyedGuard(func){ if(this.destroyed){ console.warn("You cannot call the " + func + " function on a destroyed range"); } return !this.destroyed; } }