add row button, add row after enter press in last row
This commit is contained in:
parent
09ff3a751d
commit
d674203a4d
@ -4,7 +4,7 @@ import { $, Dom } from 'core/Dom';
|
|||||||
import { ComponentOptionsType, ExcelComponent } from 'core/ExcelComponent';
|
import { ComponentOptionsType, ExcelComponent } from 'core/ExcelComponent';
|
||||||
import { TableSelection } from 'components/table/TableSelection';
|
import { TableSelection } from 'components/table/TableSelection';
|
||||||
import { changeCurrentStyles, changeCurrentText } from 'redux/action-creators';
|
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 { initialStyleState } from 'src/constants';
|
||||||
import { parse } from 'core/utils';
|
import { parse } from 'core/utils';
|
||||||
import { resizeHandler } from 'components/table/handlers/table.resize';
|
import { resizeHandler } from 'components/table/handlers/table.resize';
|
||||||
@ -15,6 +15,10 @@ export class Table extends ExcelComponent {
|
|||||||
|
|
||||||
private selection: TableSelection;
|
private selection: TableSelection;
|
||||||
private isMouseDowned: boolean;
|
private isMouseDowned: boolean;
|
||||||
|
public tableSize = {
|
||||||
|
row: 50,
|
||||||
|
col: 24,
|
||||||
|
};
|
||||||
|
|
||||||
constructor($root: Dom, options: ComponentOptionsType) {
|
constructor($root: Dom, options: ComponentOptionsType) {
|
||||||
super($root, {
|
super($root, {
|
||||||
@ -27,11 +31,11 @@ export class Table extends ExcelComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toHTML(): string {
|
toHTML(): string {
|
||||||
return createTable(50, 24);
|
return createTable(this.tableSize.row, this.tableSize.col);
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare() {
|
prepare() {
|
||||||
this.selection = new TableSelection(this.$root);
|
this.selection = new TableSelection(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
@ -42,6 +46,7 @@ export class Table extends ExcelComponent {
|
|||||||
this.$onEventFromObserver('formula:input', this.updateCurrentText);
|
this.$onEventFromObserver('formula:input', this.updateCurrentText);
|
||||||
this.$onEventFromObserver('formula:enter-press', () => this.selection.current.focus());
|
this.$onEventFromObserver('formula:enter-press', () => this.selection.current.focus());
|
||||||
this.$onEventFromObserver('toolbar:applyStyle', this.updateCurrentStyles);
|
this.$onEventFromObserver('toolbar:applyStyle', this.updateCurrentStyles);
|
||||||
|
this.$onEventFromObserver('toolbar:add-row', this.addNewRowHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
initTable() {
|
initTable() {
|
||||||
@ -56,14 +61,25 @@ export class Table extends ExcelComponent {
|
|||||||
row: this.store.getState()?.rowState,
|
row: this.store.getState()?.rowState,
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.keys(size.col).forEach(key => {
|
this.initColSizes(this.$root, size.col);
|
||||||
const cols = this.$root.findAll(`[data-col="${key}"]`);
|
this.initRowSizes(this.$root, size.row);
|
||||||
cols.forEach(el => $(el as HTMLElement).css({ width: `${size.col[+key]}px` }));
|
}
|
||||||
});
|
|
||||||
|
|
||||||
Object.keys(size.row).forEach(key => {
|
initRowSizes(rootElem: Dom, rowState = this.store.getState()?.rowState) {
|
||||||
const rows = this.$root.findAll(`[data-row="${key}"]`);
|
if (!rootElem || !rootElem?.$el) return;
|
||||||
rows.forEach(el => $(el as HTMLElement).css({ height: `${size.row[+key]}px` }));
|
|
||||||
|
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) {
|
onMousedown(event: MouseEvent) {
|
||||||
this.isMouseDowned = true;
|
this.isMouseDowned = true;
|
||||||
selectHandler(event, this.selection, this.emitSelectCallback.bind(this));
|
selectHandler(event, this.selection, this.emitSelectCallback.bind(this));
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { Table } from 'components/table/Table';
|
||||||
import { $, Dom } from 'core/Dom';
|
import { $, Dom } from 'core/Dom';
|
||||||
import { getParamsFromCellId, startCellId } from 'components/table/table.functions';
|
import { getParamsFromCellId, startCellId } from 'components/table/table.functions';
|
||||||
|
|
||||||
@ -5,9 +6,9 @@ export class TableSelection {
|
|||||||
static selectedClassName = 'selected';
|
static selectedClassName = 'selected';
|
||||||
private group: Dom[];
|
private group: Dom[];
|
||||||
public current: Dom;
|
public current: Dom;
|
||||||
public rootTable: Dom;
|
public rootTable: Table;
|
||||||
|
|
||||||
constructor(rootTable: Dom) {
|
constructor(rootTable: Table) {
|
||||||
this.group = [];
|
this.group = [];
|
||||||
this.rootTable = rootTable;
|
this.rootTable = rootTable;
|
||||||
}
|
}
|
||||||
@ -16,12 +17,23 @@ export class TableSelection {
|
|||||||
return this.group.map(el => el.data.id);
|
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) {
|
select($el: Dom) {
|
||||||
this.clearSelection();
|
this.clearSelection();
|
||||||
this.group = [$el];
|
this.group = [$el];
|
||||||
this.current = $el;
|
this.current = $el;
|
||||||
$el.addClass(TableSelection.selectedClassName);
|
$el.addClass(TableSelection.selectedClassName);
|
||||||
$el.focus();
|
this.focusToCell($el);
|
||||||
}
|
}
|
||||||
|
|
||||||
selectByCellId(cellID: { col: number, row: number }) {
|
selectByCellId(cellID: { col: number, row: number }) {
|
||||||
@ -32,7 +44,7 @@ export class TableSelection {
|
|||||||
|
|
||||||
this.clearSelection();
|
this.clearSelection();
|
||||||
this.current = $(`[data-id="${row}:${col}"]`);
|
this.current = $(`[data-id="${row}:${col}"]`);
|
||||||
this.current.focus();
|
this.focusToCell(this.current);
|
||||||
this.current.addClass(TableSelection.selectedClassName);
|
this.current.addClass(TableSelection.selectedClassName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,7 @@ export function selectHandler(event: MouseEvent | KeyboardEvent, selection: Tabl
|
|||||||
} else {
|
} else {
|
||||||
const row = target.closest('[data-header="row"]');
|
const row = target.closest('[data-header="row"]');
|
||||||
const col = target.closest('[data-header="col"]');
|
const col = target.closest('[data-header="col"]');
|
||||||
const resizer = target.closest('[data-resizer]');
|
const resizer = target.closest('[data-resize]');
|
||||||
|
|
||||||
if (row.$el && !resizer.$el) {
|
if (row.$el && !resizer.$el) {
|
||||||
const cells = row.closest('[data-row]').findAll('[data-type="cell"]');
|
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);
|
selection.selectGroupies($cells);
|
||||||
} else if (col.$el && !resizer.$el) {
|
} else if (col.$el && !resizer.$el) {
|
||||||
const colNumber = col.data.col;
|
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));
|
const $cells = Array.from(colls).filter(el => el !== col.$el).map(el => $(el as HTMLElement));
|
||||||
|
|
||||||
selection.selectGroupies($cells);
|
selection.selectGroupies($cells);
|
||||||
@ -88,9 +88,9 @@ export function selectHandler(event: MouseEvent | KeyboardEvent, selection: Tabl
|
|||||||
}
|
}
|
||||||
case 'Enter': {
|
case 'Enter': {
|
||||||
if (event.shiftKey) return;
|
if (event.shiftKey) return;
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
row++;
|
row++;
|
||||||
|
if (row === selection.rootTable.tableSize.row) selection.rootTable.addNewRowHandler();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'Tab': {
|
case 'Tab': {
|
||||||
|
|||||||
@ -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 `
|
return `
|
||||||
<div class="row" data-type="resizable" data-row="${rowIndex}">
|
<div class="row" data-type="resizable" data-row="${rowIndex}">
|
||||||
<div class="row-info" data-header="row">
|
<div class="row-info" data-header="row">
|
||||||
@ -62,3 +62,12 @@ export function createTable(rowsCount = 10, columnCount = 10) {
|
|||||||
|
|
||||||
return rows.join('');
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@ -43,8 +43,14 @@ export class Toolbar extends ExcelComponentState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onClick(event: MouseEvent) {
|
onClick(event: MouseEvent) {
|
||||||
|
//TODO refactor, make style handler
|
||||||
const target = $(event.target as HTMLElement);
|
const target = $(event.target as HTMLElement);
|
||||||
|
|
||||||
|
if (target.closest('[data-addbtn]')) {
|
||||||
|
this.$emitEventToObserver('toolbar:add-row');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let stringValue;
|
let stringValue;
|
||||||
let value;
|
let value;
|
||||||
let key;
|
let key;
|
||||||
@ -80,8 +86,10 @@ export class Toolbar extends ExcelComponentState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$emitEventToObserver('toolbar:applyStyle', value);
|
if (value && key) {
|
||||||
this.setComponentState({ [key]: value[key] });
|
this.$emitEventToObserver('toolbar:applyStyle', value);
|
||||||
|
this.setComponentState({ [key]: value[key] });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange(e: any) {
|
onChange(e: any) {
|
||||||
|
|||||||
@ -88,6 +88,7 @@ export function createToolbar(state: ToolbarStateType): string {
|
|||||||
|
|
||||||
buttons.push(increaseDecreaseFontSize);
|
buttons.push(increaseDecreaseFontSize);
|
||||||
buttons.push(selectGroup);
|
buttons.push(selectGroup);
|
||||||
|
buttons.push(createAddRowTable());
|
||||||
|
|
||||||
return buttons.join('');
|
return buttons.join('');
|
||||||
}
|
}
|
||||||
@ -168,3 +169,11 @@ function createButtonFromConfig(btnConfig: ButtonConfigType) {
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createAddRowTable() {
|
||||||
|
return `
|
||||||
|
<div class="button" data-addbtn>
|
||||||
|
<i class="material-icons" data-addbtn>add_circle</i>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|||||||
@ -38,8 +38,8 @@ export abstract class ExcelComponent extends DomListener {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$emitEventToObserver(event: string, args?: any): void {
|
$emitEventToObserver(event: string, args?: any): boolean {
|
||||||
this.observer?.emit(event, args);
|
return this.observer?.emit(event, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
$onEventFromObserver(event: string, callback: (args: any) => any) {
|
$onEventFromObserver(event: string, callback: (args: any) => any) {
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
top: $header-height + $toolbar-height + $formula-height;
|
top: $header-height + $toolbar-height + $formula-height;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
font-size: $default-cell-font-size;
|
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{
|
.row{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user