From d674203a4d198f4fecbeadb022cfd7d062babe3a Mon Sep 17 00:00:00 2001 From: Sergey Krylov Date: Tue, 12 Jul 2022 13:27:38 +0500 Subject: [PATCH] add row button, add row after enter press in last row --- src/components/table/Table.ts | 43 ++++++++++++++----- src/components/table/TableSelection.ts | 20 +++++++-- .../table/handlers/table.select.handler.ts | 6 +-- src/components/table/table.template.ts | 11 ++++- src/components/toolbar/Toolbar.ts | 12 +++++- src/components/toolbar/toolbar.template.ts | 9 ++++ src/core/ExcelComponent.ts | 4 +- src/styles/components/table.scss | 2 +- 8 files changed, 84 insertions(+), 23 deletions(-) diff --git a/src/components/table/Table.ts b/src/components/table/Table.ts index 4268c23..a3c0bd1 100644 --- a/src/components/table/Table.ts +++ b/src/components/table/Table.ts @@ -4,7 +4,7 @@ import { $, Dom } from 'core/Dom'; import { ComponentOptionsType, ExcelComponent } from 'core/ExcelComponent'; import { TableSelection } from 'components/table/TableSelection'; import { changeCurrentStyles, changeCurrentText } from 'redux/action-creators'; -import { createTable } from 'components/table/table.template'; +import { createTable, getNewRowHTML } from 'components/table/table.template'; import { initialStyleState } from 'src/constants'; import { parse } from 'core/utils'; import { resizeHandler } from 'components/table/handlers/table.resize'; @@ -15,6 +15,10 @@ export class Table extends ExcelComponent { private selection: TableSelection; private isMouseDowned: boolean; + public tableSize = { + row: 50, + col: 24, + }; constructor($root: Dom, options: ComponentOptionsType) { super($root, { @@ -27,11 +31,11 @@ export class Table extends ExcelComponent { } toHTML(): string { - return createTable(50, 24); + return createTable(this.tableSize.row, this.tableSize.col); } prepare() { - this.selection = new TableSelection(this.$root); + this.selection = new TableSelection(this); } init() { @@ -42,6 +46,7 @@ export class Table extends ExcelComponent { this.$onEventFromObserver('formula:input', this.updateCurrentText); this.$onEventFromObserver('formula:enter-press', () => this.selection.current.focus()); this.$onEventFromObserver('toolbar:applyStyle', this.updateCurrentStyles); + this.$onEventFromObserver('toolbar:add-row', this.addNewRowHandler); } initTable() { @@ -56,14 +61,25 @@ export class Table extends ExcelComponent { row: this.store.getState()?.rowState, }; - Object.keys(size.col).forEach(key => { - const cols = this.$root.findAll(`[data-col="${key}"]`); - cols.forEach(el => $(el as HTMLElement).css({ width: `${size.col[+key]}px` })); - }); + this.initColSizes(this.$root, size.col); + this.initRowSizes(this.$root, size.row); + } - Object.keys(size.row).forEach(key => { - const rows = this.$root.findAll(`[data-row="${key}"]`); - rows.forEach(el => $(el as HTMLElement).css({ height: `${size.row[+key]}px` })); + initRowSizes(rootElem: Dom, rowState = this.store.getState()?.rowState) { + if (!rootElem || !rootElem?.$el) return; + + Object.keys(rowState).forEach(key => { + const rows = rootElem.findAll(`[data-row="${key}"]`); + rows.forEach(el => $(el as HTMLElement).css({ height: `${rowState[+key]}px` })); + }); + } + + initColSizes(rootElem: Dom, colState = this.store.getState()?.colState) { + if (!rootElem || !rootElem?.$el) return; + + Object.keys(colState).forEach(key => { + const cols = rootElem.findAll(`[data-col="${key}"]`); + cols.forEach(el => $(el as HTMLElement).css({ width: `${colState[+key]}px` })); }); } @@ -125,6 +141,13 @@ export class Table extends ExcelComponent { })); }; + addNewRowHandler = () => { + this.tableSize.row++; + this.$root.$el.insertAdjacentHTML('beforeend', getNewRowHTML(this.tableSize.row, this.tableSize.col)); + const $newRow = $(`[data-row="${this.tableSize.row - 1}"]`); + this.initColSizes($newRow); + }; + onMousedown(event: MouseEvent) { this.isMouseDowned = true; selectHandler(event, this.selection, this.emitSelectCallback.bind(this)); diff --git a/src/components/table/TableSelection.ts b/src/components/table/TableSelection.ts index 8c5658c..2be8dfa 100644 --- a/src/components/table/TableSelection.ts +++ b/src/components/table/TableSelection.ts @@ -1,3 +1,4 @@ +import { Table } from 'components/table/Table'; import { $, Dom } from 'core/Dom'; import { getParamsFromCellId, startCellId } from 'components/table/table.functions'; @@ -5,9 +6,9 @@ export class TableSelection { static selectedClassName = 'selected'; private group: Dom[]; public current: Dom; - public rootTable: Dom; + public rootTable: Table; - constructor(rootTable: Dom) { + constructor(rootTable: Table) { this.group = []; this.rootTable = rootTable; } @@ -16,12 +17,23 @@ export class TableSelection { return this.group.map(el => el.data.id); } + // TODO make a focus manager + focusToCell($cell: Dom) { + const range = new Range(); + const node = $cell.$el; + + range.setStartAfter(node.childNodes[0]); + + window.getSelection()?.removeAllRanges(); + window.getSelection()?.addRange(range); + } + select($el: Dom) { this.clearSelection(); this.group = [$el]; this.current = $el; $el.addClass(TableSelection.selectedClassName); - $el.focus(); + this.focusToCell($el); } selectByCellId(cellID: { col: number, row: number }) { @@ -32,7 +44,7 @@ export class TableSelection { this.clearSelection(); this.current = $(`[data-id="${row}:${col}"]`); - this.current.focus(); + this.focusToCell(this.current); this.current.addClass(TableSelection.selectedClassName); } diff --git a/src/components/table/handlers/table.select.handler.ts b/src/components/table/handlers/table.select.handler.ts index c28dcbe..a1fb57e 100644 --- a/src/components/table/handlers/table.select.handler.ts +++ b/src/components/table/handlers/table.select.handler.ts @@ -35,7 +35,7 @@ export function selectHandler(event: MouseEvent | KeyboardEvent, selection: Tabl } else { const row = target.closest('[data-header="row"]'); const col = target.closest('[data-header="col"]'); - const resizer = target.closest('[data-resizer]'); + const resizer = target.closest('[data-resize]'); if (row.$el && !resizer.$el) { const cells = row.closest('[data-row]').findAll('[data-type="cell"]'); @@ -44,7 +44,7 @@ export function selectHandler(event: MouseEvent | KeyboardEvent, selection: Tabl selection.selectGroupies($cells); } else if (col.$el && !resizer.$el) { const colNumber = col.data.col; - const colls = selection.rootTable.findAll(`[data-col="${colNumber}"]`); + const colls = selection.rootTable.$root.findAll(`[data-col="${colNumber}"]`); const $cells = Array.from(colls).filter(el => el !== col.$el).map(el => $(el as HTMLElement)); selection.selectGroupies($cells); @@ -88,9 +88,9 @@ export function selectHandler(event: MouseEvent | KeyboardEvent, selection: Tabl } case 'Enter': { if (event.shiftKey) return; - event.preventDefault(); row++; + if (row === selection.rootTable.tableSize.row) selection.rootTable.addNewRowHandler(); break; } case 'Tab': { diff --git a/src/components/table/table.template.ts b/src/components/table/table.template.ts index ae774f6..5c8569f 100644 --- a/src/components/table/table.template.ts +++ b/src/components/table/table.template.ts @@ -27,7 +27,7 @@ function createCol(columnContent = '', index = 1) { `; } -function createRow(dataContent = '', infoContent = '', needResize = true, rowIndex = -1) { +function createRow(dataContent = '', infoContent = '', needResize = true, rowIndex = -1): string { return `
@@ -62,3 +62,12 @@ export function createTable(rowsCount = 10, columnCount = 10) { return rows.join(''); } + +export function getNewRowHTML(rowIndex: number, colCount: number): string { + const cells = new Array(colCount) + .fill('') + .map((el, colIndex) => createCell('', colIndex, rowIndex - 1)) + .join(''); + + return createRow(cells, rowIndex.toString(), true, rowIndex - 1); +} diff --git a/src/components/toolbar/Toolbar.ts b/src/components/toolbar/Toolbar.ts index b07bc79..b972ea7 100644 --- a/src/components/toolbar/Toolbar.ts +++ b/src/components/toolbar/Toolbar.ts @@ -43,8 +43,14 @@ export class Toolbar extends ExcelComponentState { } onClick(event: MouseEvent) { + //TODO refactor, make style handler const target = $(event.target as HTMLElement); + if (target.closest('[data-addbtn]')) { + this.$emitEventToObserver('toolbar:add-row'); + return; + } + let stringValue; let value; let key; @@ -80,8 +86,10 @@ export class Toolbar extends ExcelComponentState { } } - this.$emitEventToObserver('toolbar:applyStyle', value); - this.setComponentState({ [key]: value[key] }); + if (value && key) { + this.$emitEventToObserver('toolbar:applyStyle', value); + this.setComponentState({ [key]: value[key] }); + } } onChange(e: any) { diff --git a/src/components/toolbar/toolbar.template.ts b/src/components/toolbar/toolbar.template.ts index 2e1b179..51a80cd 100644 --- a/src/components/toolbar/toolbar.template.ts +++ b/src/components/toolbar/toolbar.template.ts @@ -88,6 +88,7 @@ export function createToolbar(state: ToolbarStateType): string { buttons.push(increaseDecreaseFontSize); buttons.push(selectGroup); + buttons.push(createAddRowTable()); return buttons.join(''); } @@ -168,3 +169,11 @@ function createButtonFromConfig(btnConfig: ButtonConfigType) {
`; } + +function createAddRowTable() { + return ` +
+ add_circle +
+ `; +} diff --git a/src/core/ExcelComponent.ts b/src/core/ExcelComponent.ts index 79fe6f2..c581ab1 100644 --- a/src/core/ExcelComponent.ts +++ b/src/core/ExcelComponent.ts @@ -38,8 +38,8 @@ export abstract class ExcelComponent extends DomListener { return ''; } - $emitEventToObserver(event: string, args?: any): void { - this.observer?.emit(event, args); + $emitEventToObserver(event: string, args?: any): boolean { + return this.observer?.emit(event, args); } $onEventFromObserver(event: string, callback: (args: any) => any) { diff --git a/src/styles/components/table.scss b/src/styles/components/table.scss index 2e6963d..e1759a8 100644 --- a/src/styles/components/table.scss +++ b/src/styles/components/table.scss @@ -8,7 +8,7 @@ top: $header-height + $toolbar-height + $formula-height; overflow: auto; font-size: $default-cell-font-size; - cursor: url('https://upload.wikimedia.org/wikipedia/commons/thumb/5/5e/Small_arrow_pointing_left.svg/1200px-Small_arrow_pointing_left.svg.png') !important; + .row{ display: flex; flex-direction: row;