136 lines
3.7 KiB
TypeScript
136 lines
3.7 KiB
TypeScript
import { $, Dom } from 'core/dom';
|
|
import { ExcelComponent } from 'core/ExcelComponent';
|
|
import { parse } from 'core/parse';
|
|
import { changeCurrentStyles } from 'redux/actions';
|
|
import * as actions from 'redux/actions';
|
|
import { initialStyleState } from '../../constants';
|
|
import { resizeHandler } from './handlers/table.resize';
|
|
import { selectHandler } from './handlers/table.select.handler';
|
|
import { createTable } from './table.template';
|
|
import { TableSelection } from './TableSelection';
|
|
|
|
export class Table extends ExcelComponent {
|
|
static className = 'excel__table';
|
|
|
|
private selection: TableSelection;
|
|
|
|
constructor($root: Dom, options: any) {
|
|
super($root, {
|
|
name: 'Table',
|
|
listeners: ['mousedown', 'keydown', 'input'],
|
|
...options,
|
|
});
|
|
}
|
|
|
|
toHTML(): string {
|
|
return createTable(50, 24);
|
|
}
|
|
|
|
prepare() {
|
|
this.selection = new TableSelection();
|
|
}
|
|
|
|
init() {
|
|
super.init();
|
|
|
|
const $cell = this.$root.find('[data-id="0:0"]');
|
|
this.selection.select($cell);
|
|
|
|
this.$emit('table:select-cell', $cell.data.value);
|
|
|
|
this.$on('formula:input', (data) => {
|
|
this.selection.current.attr('data-value', data);
|
|
this.selection.current.text = parse(data);
|
|
this.updateCurrentTextInStore(data);
|
|
});
|
|
|
|
this.$on('formula:enter-press', () => {
|
|
this.selection.current.focus();
|
|
});
|
|
|
|
this.$on('toolbar:applyStyle', (value) => {
|
|
this.selection.applyStyle(value);
|
|
|
|
this.$dispatch(actions.applyStyle({
|
|
value,
|
|
ids: this.selection.selectedIds,
|
|
}));
|
|
});
|
|
|
|
this.initTable();
|
|
}
|
|
|
|
initTable() {
|
|
this.initTableSize();
|
|
this.initTableContentAndStyles();
|
|
}
|
|
|
|
initTableSize() {
|
|
const size = {
|
|
col: this.store.getState()?.colState,
|
|
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` }));
|
|
});
|
|
|
|
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` }));
|
|
});
|
|
}
|
|
|
|
initTableContentAndStyles() {
|
|
const tableState = this.store.getState();
|
|
const tableContent = tableState?.dataState;
|
|
const tableStyles = tableState?.stylesState;
|
|
|
|
Object.keys(tableContent).forEach(cellId => {
|
|
const $cell = this.$root.find(`[data-id="${cellId}"]`);
|
|
const styles = tableStyles[cellId];
|
|
|
|
$cell.text = parse(tableContent[cellId]) || '';
|
|
$cell.setData('value', tableContent[cellId]);
|
|
$cell.css(styles);
|
|
});
|
|
}
|
|
|
|
emitSelectCallback() {
|
|
this.$emit('table:select-cell', this.selection.current.data.value);
|
|
|
|
const styles = this.selection.current?.getStyles(Object.keys(initialStyleState) as (keyof Partial<CSSStyleDeclaration>)[]);
|
|
this.$dispatch(changeCurrentStyles(styles));
|
|
}
|
|
|
|
async resizeTable(event: MouseEvent) {
|
|
try {
|
|
const resizeData = await resizeHandler(this.$root, event);
|
|
this.$dispatch(actions.tableResize({ resizeData }));
|
|
} catch (e) {
|
|
console.warn('Resize error', e.message);
|
|
}
|
|
}
|
|
|
|
updateCurrentTextInStore(text: string) {
|
|
this.$dispatch(actions.changeText({
|
|
text,
|
|
id: this.selection.current.data.id,
|
|
}));
|
|
}
|
|
|
|
onMousedown(event: MouseEvent) {
|
|
selectHandler(event, this.selection, this.emitSelectCallback.bind(this));
|
|
this.resizeTable(event);
|
|
}
|
|
|
|
onKeydown(event: KeyboardEvent) {
|
|
selectHandler(event, this.selection, this.emitSelectCallback.bind(this));
|
|
}
|
|
|
|
onInput(event: InputEvent) {
|
|
this.updateCurrentTextInStore((event.target as HTMLElement).textContent.trim());
|
|
}
|
|
}
|