add table resize

This commit is contained in:
Sergey Krylov 2022-06-21 20:01:51 +05:00
parent 9fd1eccd74
commit 2c80d20fb8
8 changed files with 138 additions and 15 deletions

View File

@ -13,18 +13,20 @@ module.exports = {
project: './tsconfig.json'
},
rules: {
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/lines-between-class-members": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unnecessary-type-assertion": "off",
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/restrict-template-expressions": "off",
"@typescript-eslint/lines-between-class-members": "off",
"@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/restrict-template-expressions": "off",
"arrow-parens": "off",
"class-methods-use-this": "off",
"func-names": "off",
"import/prefer-default-export": "off",
"no-console": "off",
"no-plusplus": "off",

View File

@ -1,10 +1,22 @@
import { ExcelComponent } from '../../core/ExcelComponent';
import { createTable } from './table.template';
import { resizeHandler } from './table.resize';
export class Table extends ExcelComponent {
static className = 'excel__table';
constructor($root: any) {
super($root, {
name: 'Table',
listeners: ['mousedown'],
});
}
toHTML(): string {
return createTable(50, 24);
}
onMousedown(event: MouseEvent) {
resizeHandler(this.$root, event);
}
}

View File

View File

@ -0,0 +1,77 @@
import { $, Dom } from '../../core/dom';
type CustomElementType = Element & { css: any };
export function resizeHandler($root: Dom, event: MouseEvent) {
const { target } = event;
if (!(target as HTMLElement).dataset.resize) return;
const $resizer = $(target as HTMLElement);
const $parent = $resizer.closest('[data-type="resizable"]');
const coords = $parent.getCoords();
const type = $resizer.data.resize;
const allCols = $root.findAll(`[data-col="${$parent.data.col}"]`);
let delta: number;
(Element.prototype as CustomElementType).css = function (styles: any) {
Object.keys(styles).forEach((key: any) => {
this.style[key] = styles[key];
});
};
$resizer.css({ opacity: 1 });
document.onmousemove = e => {
document.body.style.userSelect = 'none';
switch (type) {
case 'col': {
delta = e.pageX - coords.right;
$resizer.css({
right: `${-delta}px`,
bottom: '-100vh',
});
break;
}
case 'row': {
delta = e.pageY - coords.bottom;
$resizer.css({
bottom: `${-delta}px`,
right: '-100vw',
});
break;
}
default: break;
}
};
document.onmouseup = () => {
document.onmousemove = null;
document.onmouseup = null;
document.body.style.userSelect = null;
switch (type) {
case 'col': {
$parent.css({ width: `${coords.width + delta}px` });
allCols.forEach((el: CustomElementType) => el.css({ width: `${coords.width + delta}px` }));
break;
}
case 'row': {
$parent.css({ height: `${coords.height + (delta)}px` });
break;
}
default: break;
}
$resizer.css({ opacity: 0, bottom: 0, right: 0 });
};
}

View File

@ -3,22 +3,28 @@ const CODES = {
Z: 90,
};
function createCell(cellContent = '') {
function createCell(cellContent = '', index = 1) {
return `
<div class="cell" contenteditable>${cellContent}</div>
<div class="cell" contenteditable data-col="${index}">${cellContent}</div>
`;
}
function createCol(columnContent = '') {
function createCol(columnContent = '', index = 1) {
return `
<div class="column">${columnContent}</div>
<div class="column" data-type="resizable" data-col="${index}">
${columnContent}
<div class="col-resize" data-resize="col"></div>
</div>
`;
}
function createRow(dataContent = '', infoContent = '') {
function createRow(dataContent = '', infoContent = '', needResize = true) {
return `
<div class="row">
<div class="row-info">${infoContent}</div>
<div class="row" data-type="resizable">
<div class="row-info">
${infoContent}
${needResize ? '<div class="row-resize" data-resize="row"></div>' : ''}
</div>
<div class="row-data">${dataContent}</div>
</div>
`;
@ -31,13 +37,16 @@ export function createTable(rowsCount = 10, columnCount = 10) {
const cols = new Array(colsCount)
.fill('')
.map((el, index) => String.fromCharCode(CODES.A + index))
.map((el) => createCol(el))
.map((el, index) => createCol(el, index))
.join('');
rows.push(createRow(cols));
rows.push(createRow(cols, '', false));
for (let i = 0; i < rowsCount; i++) {
const cells = new Array(colsCount).fill(createCell()).join('');
const cells = new Array(colsCount)
.fill('')
.map((el, index) => createCell('', index))
.join('');
rows.push(createRow(cells, `${i + 1}`));
}

View File

@ -52,6 +52,28 @@ export class Dom implements DomClass {
off(eventType: string, callback: any) {
this.$el.removeEventListener(eventType, callback);
}
get data() {
return this.$el.dataset;
}
closest(selector: string) {
return $(this.$el.closest(selector) as HTMLElement);
}
getCoords() {
return this.$el.getBoundingClientRect();
}
findAll(selector: string) {
return this.$el.querySelectorAll(selector);
}
css(styles: any) {
Object.keys(styles).forEach((key: any) => {
this.$el.style[key] = styles[key];
});
}
}
export function $(selector: SelectorType) {

View File

@ -5,4 +5,5 @@ $formula-height: 24px;
$header-height: 34px;
$info-cell-width: 40px;
$row-height: 25px;
$toolbar-height: 40px;
$toolbar-height: 40px;
$primary-color: #3c74ff;

View File

@ -2,7 +2,7 @@
"compilerOptions": {
"outDir": "./dist/",
"noImplicitAny": true,
"target": "es3",
"target": "es5",
"allowJs": true,
"moduleResolution": "node",
"esModuleInterop": true,