add navigation select

This commit is contained in:
Sergey Krylov 2022-06-27 12:05:54 +05:00
parent 011508b72e
commit 3870d7dfd0
5 changed files with 107 additions and 19 deletions

View File

@ -12,7 +12,7 @@ export class Table extends ExcelComponent {
constructor($root: any) {
super($root, {
name: 'Table',
listeners: ['mousedown'],
listeners: ['mousedown', 'keydown'],
});
}
@ -35,4 +35,8 @@ export class Table extends ExcelComponent {
selectHandler(event, this.selection);
resizeHandler(this.$root, event);
}
onKeydown(event: KeyboardEvent) {
selectHandler(event, this.selection);
}
}

View File

@ -1,9 +1,10 @@
import { $, Dom } from '../../core/dom';
import { getParamsFromCellId } from './table.functions';
export class TableSelection {
static selectedClassName = 'selected';
private group: Dom[];
private current: Dom;
public current: Dom;
constructor() {
this.group = [];
@ -15,16 +16,30 @@ export class TableSelection {
this.group = [$el];
this.current = $el;
$el.addClass(TableSelection.selectedClassName);
$el.focus();
}
selectByCellId(cellID: { col: number, row: number }) {
let { col, row } = cellID;
if (col <= 0) col = 0;
if (row <= 0) row = 0;
this.clearSelection();
this.current = $(`[data-id="${row}:${col}"]`);
this.current.focus();
this.current.addClass(TableSelection.selectedClassName);
}
clearSelection() {
this.group.forEach(el => el.removeClass(TableSelection.selectedClassName));
this.group.forEach(el => el?.removeClass(TableSelection.selectedClassName));
this.current?.removeClass(TableSelection.selectedClassName);
this.group = [];
}
selectGroup($el: Dom) {
const startCellParams = this.getParamsFromCellId(this.current.data.id);
const selectedCellParams = this.getParamsFromCellId($el.data.id);
const startCellParams = getParamsFromCellId(this.current.data.id);
const selectedCellParams = getParamsFromCellId($el.data.id);
const startCol = Math.min(startCellParams.col, selectedCellParams.col);
const endCol = Math.max(startCellParams.col, selectedCellParams.col);
@ -42,11 +57,4 @@ export class TableSelection {
}
}
}
getParamsFromCellId(cellId: string) {
const row = +cellId.split(':')[0];
const col = +cellId.split(':')[1];
return { col, row };
}
}

View File

@ -1,10 +1,75 @@
import { $ } from '../../../core/dom';
import { isCell } from '../table.functions';
import { getParamsFromCellId, isCell } from '../table.functions';
import { TableSelection } from '../TableSelection';
export function selectHandler(event: MouseEvent, selection: TableSelection) {
if (isCell(event)) {
if (event.shiftKey) selection.selectGroup($(event.target as HTMLElement));
else selection.select($(event.target as HTMLElement));
export function selectHandler(event: MouseEvent | KeyboardEvent, selection: TableSelection) {
switch (event.type) {
case 'mousedown': {
onMouseDownHandler();
break;
}
case 'keydown': {
onKeyDownHandler();
break;
}
default: break;
}
function onMouseDownHandler() {
if (isCell(event)) {
if (event.shiftKey) selection.selectGroup($(event.target as HTMLElement));
else selection.select($(event.target as HTMLElement));
}
}
function onKeyDownHandler() {
const { key } = event as KeyboardEvent;
const handleKeys = [
'ArrowDown',
'ArrowUp',
'ArrowRight',
'ArrowLeft',
'Enter',
'Tab',
];
if (!selection?.current || !handleKeys.includes(key)) return;
const currentCellId = selection.current?.data?.id;
let { row, col } = getParamsFromCellId(currentCellId);
switch (key) {
case 'ArrowDown': {
row++;
break;
}
case 'ArrowUp': {
row--;
break;
}
case 'ArrowRight': {
col++;
break;
}
case 'ArrowLeft': {
col--;
break;
}
case 'Enter': {
if (event.shiftKey) return;
event.preventDefault();
row++;
break;
}
case 'Tab': {
event.preventDefault();
col++;
break;
}
default: break;
}
selection.selectByCellId({ row, col });
}
}

View File

@ -3,3 +3,10 @@ import { $ } from '../../core/dom';
export function isCell(event: Event): boolean {
return $(event.target as HTMLElement).data.type === 'cell';
}
export function getParamsFromCellId(cellId: string) {
const row = +cellId.split(':')[0];
const col = +cellId.split(':')[1];
return { col, row };
}

View File

@ -53,6 +53,10 @@ export class Dom implements DomClass {
this.$el.removeEventListener(eventType, callback);
}
focus() {
this.$el.focus();
}
get data() {
return this.$el.dataset;
}
@ -80,11 +84,11 @@ export class Dom implements DomClass {
}
addClass(className: string) {
this.$el.classList.add(className);
this.$el?.classList.add(className);
}
removeClass(className: string) {
this.$el.classList.remove(className);
this.$el?.classList.remove(className);
}
}