UNPKG

@paperbits/core

Version:
167 lines (136 loc) 5.38 kB
import * as ko from "knockout"; import template from "./tableEditor.html"; import { Component, OnMounted, Param, Event } from "@paperbits/common/ko/decorators"; import { ChangeRateLimit } from "@paperbits/common/ko/consts"; import { TableModel } from "../tableModel"; import { TableCellModel } from "../../table-cell"; @Component({ selector: "table-editor", template: template }) export class TableEditor { public readonly numOfCols: ko.Observable<number>; public readonly numOfRows: ko.Observable<number>; constructor() { this.numOfCols = ko.observable(); this.numOfRows = ko.observable(); } @Param() public model: TableModel; @Event() public onChange: (model: TableModel) => void; @OnMounted() public async initialize(): Promise<void> { this.numOfCols(this.model.numOfCols); this.numOfRows(this.model.numOfRows); this.numOfCols .extend(ChangeRateLimit) .subscribe(this.applyChanges); this.numOfRows .extend(ChangeRateLimit) .subscribe(this.applyChanges); } private removeColumn(columnIndex: number): void { const currentNumOfCols = this.model.numOfCols; this.model.styles.instance.table.cols.splice(columnIndex, 1); this.model.numOfCols--; for (let rowIndex = this.model.numOfRows; rowIndex >= 0; rowIndex--) { const cellIndex = (rowIndex * currentNumOfCols) + columnIndex; this.model.widgets.splice(cellIndex, 1); } } private addColumn(columnIndex: number): void { const currentNumOfCols = this.model.numOfCols; this.model.styles.instance.table.cols.push("1fr"); this.model.numOfCols++; for (let rowIndex = 0; rowIndex < this.model.numOfRows; rowIndex++) { const cellIndex = (rowIndex * currentNumOfCols) + columnIndex + rowIndex; const cell = this.createCell(columnIndex + 1, rowIndex + 1); this.model.widgets.splice(cellIndex, 0, cell); } } private removeRow(rowIndex: number): void { this.model.styles.instance.table.rows.splice(rowIndex, 1); this.model.numOfRows--; const rowStart = rowIndex * this.model.numOfCols; this.model.widgets.splice(rowStart, this.model.numOfCols); } private addRow(rowIndex: number): void { this.model.styles.instance.table.rows.push("1fr"); this.model.numOfRows++; for (let columnIndex = 0; columnIndex < this.model.numOfCols; columnIndex++) { const cell = this.createCell(columnIndex + 1, rowIndex + 1); this.model.widgets.push(cell); } } private createCell(columnIndex: number, rowIndex: number): TableCellModel { const cell = new TableCellModel(); cell.role = "cell"; cell.styles = { instance: { "table-cell": { position: { col: columnIndex, row: rowIndex }, span: { cols: 1, rows: 1 } }, "border": { bottom: { colorKey: "colors/default", style: "solid", width: "1" }, left: { colorKey: "colors/default", style: "solid", width: "1" }, right: { colorKey: "colors/default", style: "solid", width: "1" }, top: { colorKey: "colors/default", style: "solid", width: "1" } } } }; return cell; } private applyChanges(): void { const numOfCols = this.numOfCols(); const numOfRows = this.numOfRows(); if (numOfCols > this.model.numOfCols) { const missingCols = numOfCols - this.model.numOfCols; for (let i = 0; i < missingCols; i++) { this.addColumn(this.model.numOfCols); } } if (numOfCols < this.model.numOfCols) { const colsToDelete = this.model.numOfCols - numOfCols; for (let i = 0; i < colsToDelete; i++) { this.removeColumn(this.model.numOfCols - 1); } } if (numOfRows > this.model.numOfRows) { const rowsToAdd = numOfRows - this.model.numOfRows; for (let i = 0; i < rowsToAdd; i++) { this.addRow(this.model.numOfRows); } } if (numOfRows < this.model.numOfRows) { const rowsToDelete = this.model.numOfRows - numOfRows; for (let i = 0; i < rowsToDelete; i++) { this.removeRow(this.model.numOfRows - 1); } } this.onChange(this.model); } }