From a4188c84e5f02439514ca929e24b45f0ea529e5f Mon Sep 17 00:00:00 2001 From: Shivam Daksh Date: Sun, 20 Oct 2024 19:09:43 +0530 Subject: [PATCH 01/15] refactor the handlekeydown code --- lib/KTable/index.vue | 238 +++++++++++++++++++++++-------------------- 1 file changed, 125 insertions(+), 113 deletions(-) diff --git a/lib/KTable/index.vue b/lib/KTable/index.vue index c3d743863..dd6ac3ad0 100644 --- a/lib/KTable/index.vue +++ b/lib/KTable/index.vue @@ -298,152 +298,164 @@ const totalRows = this.rows.length; const totalCols = this.headers.length; + let { nextRowIndex, nextColIndex } = this.getNextIndexes( + key, + rowIndex, + colIndex, + totalRows, + totalCols + ); + + if (key === 'Enter' && rowIndex === -1 && this.sortable) { + this.handleSort(colIndex); + } else if (key === 'Tab') { + if (this.handleTabKey(event, rowIndex, colIndex)) { + return; + } + } + + this.focusCell(nextRowIndex, nextColIndex); + this.focusedRowIndex = nextRowIndex === -1 ? null : nextRowIndex; + this.focusedColIndex = nextColIndex; + + this.highlightHeader(nextColIndex); + + event.preventDefault(); + }, + + getNextIndexes(key, rowIndex, colIndex, totalRows, totalCols) { + const lastRowIndex = totalRows - 1; + const lastColIndex = totalCols - 1; let nextRowIndex = rowIndex; let nextColIndex = colIndex; switch (key) { case 'ArrowUp': - if (rowIndex === -1) { - nextRowIndex = totalRows - 1; - } else { - nextRowIndex = rowIndex - 1; - } + nextRowIndex = rowIndex === -1 ? lastRowIndex : rowIndex - 1; break; case 'ArrowDown': - if (rowIndex === -1) { - nextRowIndex = 0; - } else if (rowIndex === totalRows - 1) { - nextRowIndex = -1; - } else { - nextRowIndex = (rowIndex + 1) % totalRows; - } + nextRowIndex = rowIndex === -1 ? 0 : rowIndex === lastRowIndex ? -1 : rowIndex + 1; break; case 'ArrowLeft': if (rowIndex === -1) { - if (colIndex > 0) { - nextColIndex = colIndex - 1; - } else { - nextColIndex = totalCols - 1; - nextRowIndex = totalRows - 1; - } - } else if (colIndex > 0) { - nextColIndex = colIndex - 1; + nextColIndex = colIndex > 0 ? colIndex - 1 : lastColIndex; + nextRowIndex = colIndex === 0 ? lastRowIndex : -1; } else { - nextColIndex = totalCols - 1; - nextRowIndex = rowIndex > 0 ? rowIndex - 1 : -1; + nextColIndex = colIndex > 0 ? colIndex - 1 : lastColIndex; + nextRowIndex = colIndex === 0 ? (rowIndex > 0 ? rowIndex - 1 : -1) : rowIndex; } break; case 'ArrowRight': - if (colIndex === totalCols - 1) { - if (rowIndex === totalRows - 1) { - nextColIndex = 0; - nextRowIndex = -1; - } else { - nextColIndex = 0; - nextRowIndex = rowIndex + 1; - } + if (colIndex === lastColIndex) { + nextColIndex = 0; + nextRowIndex = rowIndex === lastRowIndex ? -1 : rowIndex + 1; } else { nextColIndex = colIndex + 1; } break; - case 'Enter': - if (rowIndex === -1 && this.sortable) { - this.handleSort(colIndex); - } - break; - case 'Tab': { - // Identify all focusable elements inside the current cell - const currentCell = this.getCell(rowIndex, colIndex); + } + return { nextRowIndex, nextColIndex }; + }, + + handleTabKey(event, rowIndex, colIndex) { + const currentCell = this.getCell(rowIndex, colIndex); - // Collect focusable elements using native DOM methods - const focusableElements = []; + if (!currentCell) return false; - if (currentCell) { - const buttons = currentCell.getElementsByTagName('button'); - const links = currentCell.getElementsByTagName('a'); - const inputs = currentCell.getElementsByTagName('input'); - const selects = currentCell.getElementsByTagName('select'); - const textareas = currentCell.getElementsByTagName('textarea'); + const focusableElements = this.getFocusableElements(currentCell); + const focusedElementIndex = focusableElements.indexOf(document.activeElement); - focusableElements.push(...buttons, ...links, ...inputs, ...selects, ...textareas); + if (focusableElements.length > 0) { + if (!event.shiftKey) { + if (focusedElementIndex < focusableElements.length - 1) { + focusableElements[focusedElementIndex + 1].focus(); + event.preventDefault(); + return true; } + } else { + if (focusedElementIndex > 0) { + focusableElements[focusedElementIndex - 1].focus(); + event.preventDefault(); + return true; + } + } + } - const focusedElementIndex = focusableElements.indexOf(document.activeElement); - if (focusableElements.length > 0) { - if (!event.shiftKey) { - // if navigating between more focusable elements within the cell - if (focusedElementIndex < focusableElements.length - 1) { - focusableElements[focusedElementIndex + 1].focus(); - event.preventDefault(); - return; - } else { - if (colIndex < totalCols - 1) { - nextColIndex = colIndex + 1; - } else if (rowIndex < totalRows - 1) { - nextColIndex = 0; - nextRowIndex = rowIndex + 1; - } else { - // Allow default behavior when reaching the last cell - return; - } - } - } else { - if (focusedElementIndex < focusableElements.length - 1) { - // if navigating between more focusable elements within the cell - focusableElements[focusedElementIndex + 1].focus(); - event.preventDefault(); - return; - } else { - if (colIndex > 0) { - nextColIndex = colIndex - 1; - } else if (rowIndex > 0) { - nextColIndex = totalCols - 1; - nextRowIndex = rowIndex - 1; - } else { - // Allow default behavior when reaching the first cell - return; - } - } - } + const totalRows = this.rows.length; + const totalCols = this.headers.length; + let nextRowIndex = rowIndex; + let nextColIndex = colIndex; + + if (!event.shiftKey) { + // Mimic ArrowRight key + if (colIndex === totalCols - 1) { + nextColIndex = 0; + nextRowIndex = rowIndex === totalRows - 1 ? -1 : rowIndex + 1; + } else { + nextColIndex = colIndex + 1; + } + } else { + // Mimic ArrowLeft key + if (colIndex === 0) { + if (rowIndex === -1) { + // Move to the last cell if the first cell is focused + nextColIndex = totalCols - 1; + nextRowIndex = totalRows - 1; } else { - if (!event.shiftKey) { - if (colIndex < totalCols - 1) { - nextColIndex = colIndex + 1; - } else if (rowIndex < totalRows - 1) { - nextColIndex = 0; - nextRowIndex = rowIndex + 1; - } else { - // Allow default behavior when reaching the last cell - return; - } - } else { - if (colIndex > 0) { - nextColIndex = colIndex - 1; - } else if (rowIndex > 0) { - nextColIndex = totalCols - 1; - nextRowIndex = rowIndex - 1; - } else { - // Allow default behavior when reaching the first cell - return; - } - } + nextColIndex = totalCols - 1; + nextRowIndex = rowIndex > 0 ? rowIndex - 1 : -1; } - - break; + } else { + nextColIndex = colIndex - 1; } + } - default: - return; + this.focusCell(nextRowIndex, nextColIndex); + event.preventDefault(); + return true; + }, + + moveToNextCell(rowIndex, colIndex) { + const totalRows = this.rows.length; + const totalCols = this.headers.length; + + let nextRowIndex = rowIndex; + let nextColIndex = colIndex; + + if (colIndex < totalCols - 1) { + nextColIndex = colIndex + 1; + } else if (rowIndex < totalRows - 1) { + nextColIndex = 0; + nextRowIndex = rowIndex + 1; } this.focusCell(nextRowIndex, nextColIndex); - this.focusedRowIndex = nextRowIndex === -1 ? null : nextRowIndex; - this.focusedColIndex = nextColIndex; + }, - this.highlightHeader(nextColIndex); + moveToPreviousCell(rowIndex, colIndex) { + const totalRows = this.rows.length; + const totalCols = this.headers.length; - event.preventDefault(); + let nextRowIndex = rowIndex; + let nextColIndex = colIndex; + + if (colIndex > 0) { + nextColIndex = colIndex - 1; + } else if (rowIndex > 0) { + nextColIndex = totalCols - 1; + nextRowIndex = rowIndex - 1; + } + + this.focusCell(nextRowIndex, nextColIndex); + }, + + getFocusableElements(cell) { + const focusableSelectors = ['button', 'a', 'input', 'select', 'textarea']; + return focusableSelectors.flatMap(selector => + Array.from(cell.getElementsByTagName(selector)) + ); }, + //My code ends here getCell(rowIndex, colIndex) { if (rowIndex === -1) { return this.$refs[`header-${colIndex}`][0]; From 1bb147164bcebae3cd869958be30d645276adab0 Mon Sep 17 00:00:00 2001 From: Shivam Daksh Date: Mon, 21 Oct 2024 15:21:39 +0530 Subject: [PATCH 02/15] lint fix by commenting the unused code --- lib/KTable/index.vue | 66 ++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/lib/KTable/index.vue b/lib/KTable/index.vue index dd6ac3ad0..417427f39 100644 --- a/lib/KTable/index.vue +++ b/lib/KTable/index.vue @@ -415,39 +415,39 @@ return true; }, - moveToNextCell(rowIndex, colIndex) { - const totalRows = this.rows.length; - const totalCols = this.headers.length; - - let nextRowIndex = rowIndex; - let nextColIndex = colIndex; - - if (colIndex < totalCols - 1) { - nextColIndex = colIndex + 1; - } else if (rowIndex < totalRows - 1) { - nextColIndex = 0; - nextRowIndex = rowIndex + 1; - } - - this.focusCell(nextRowIndex, nextColIndex); - }, - - moveToPreviousCell(rowIndex, colIndex) { - const totalRows = this.rows.length; - const totalCols = this.headers.length; - - let nextRowIndex = rowIndex; - let nextColIndex = colIndex; - - if (colIndex > 0) { - nextColIndex = colIndex - 1; - } else if (rowIndex > 0) { - nextColIndex = totalCols - 1; - nextRowIndex = rowIndex - 1; - } - - this.focusCell(nextRowIndex, nextColIndex); - }, + // moveToNextCell(rowIndex, colIndex) { + // const totalRows = this.rows.length; + // const totalCols = this.headers.length; + + // let nextRowIndex = rowIndex; + // let nextColIndex = colIndex; + + // if (colIndex < totalCols - 1) { + // nextColIndex = colIndex + 1; + // } else if (rowIndex < totalRows - 1) { + // nextColIndex = 0; + // nextRowIndex = rowIndex + 1; + // } + + // this.focusCell(nextRowIndex, nextColIndex); + // }, + + // moveToPreviousCell(rowIndex, colIndex) { + // const totalRows = this.rows.length; + // const totalCols = this.headers.length; + + // let nextRowIndex = rowIndex; + // let nextColIndex = colIndex; + + // if (colIndex > 0) { + // nextColIndex = colIndex - 1; + // } else if (rowIndex > 0) { + // nextColIndex = totalCols - 1; + // nextRowIndex = rowIndex - 1; + // } + + // this.focusCell(nextRowIndex, nextColIndex); + // }, getFocusableElements(cell) { const focusableSelectors = ['button', 'a', 'input', 'select', 'textarea']; From 75f07a2233b9d7c6d4cf57f65846aa0206e77f27 Mon Sep 17 00:00:00 2001 From: Shivam Daksh Date: Wed, 23 Oct 2024 07:10:34 +0530 Subject: [PATCH 03/15] row highlight fix when tab key pressed --- lib/KTable/index.vue | 37 +++---------------------------------- 1 file changed, 3 insertions(+), 34 deletions(-) diff --git a/lib/KTable/index.vue b/lib/KTable/index.vue index 417427f39..93ac7b3a4 100644 --- a/lib/KTable/index.vue +++ b/lib/KTable/index.vue @@ -411,44 +411,13 @@ } this.focusCell(nextRowIndex, nextColIndex); + this.focusedRowIndex = nextRowIndex === -1 ? null : nextRowIndex; + this.focusedColIndex = nextColIndex; + this.highlightHeader(nextColIndex); event.preventDefault(); return true; }, - // moveToNextCell(rowIndex, colIndex) { - // const totalRows = this.rows.length; - // const totalCols = this.headers.length; - - // let nextRowIndex = rowIndex; - // let nextColIndex = colIndex; - - // if (colIndex < totalCols - 1) { - // nextColIndex = colIndex + 1; - // } else if (rowIndex < totalRows - 1) { - // nextColIndex = 0; - // nextRowIndex = rowIndex + 1; - // } - - // this.focusCell(nextRowIndex, nextColIndex); - // }, - - // moveToPreviousCell(rowIndex, colIndex) { - // const totalRows = this.rows.length; - // const totalCols = this.headers.length; - - // let nextRowIndex = rowIndex; - // let nextColIndex = colIndex; - - // if (colIndex > 0) { - // nextColIndex = colIndex - 1; - // } else if (rowIndex > 0) { - // nextColIndex = totalCols - 1; - // nextRowIndex = rowIndex - 1; - // } - - // this.focusCell(nextRowIndex, nextColIndex); - // }, - getFocusableElements(cell) { const focusableSelectors = ['button', 'a', 'input', 'select', 'textarea']; return focusableSelectors.flatMap(selector => From 6163a15f7762e84d64d77f5e6ed59a32f75ec27a Mon Sep 17 00:00:00 2001 From: Shivam Daksh Date: Fri, 25 Oct 2024 10:53:25 +0530 Subject: [PATCH 04/15] Fix the infinite loop of Tab key over table cells --- lib/KTable/index.vue | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/lib/KTable/index.vue b/lib/KTable/index.vue index 93ac7b3a4..ba0bfb32f 100644 --- a/lib/KTable/index.vue +++ b/lib/KTable/index.vue @@ -309,9 +309,11 @@ if (key === 'Enter' && rowIndex === -1 && this.sortable) { this.handleSort(colIndex); } else if (key === 'Tab') { - if (this.handleTabKey(event, rowIndex, colIndex)) { - return; - } + this.handleTabKey(event, rowIndex, colIndex); + return; + // if (this.handleTabKey(event, rowIndex, colIndex)) { + // return; + // } } this.focusCell(nextRowIndex, nextColIndex); @@ -387,26 +389,22 @@ let nextColIndex = colIndex; if (!event.shiftKey) { - // Mimic ArrowRight key - if (colIndex === totalCols - 1) { + if (colIndex < totalCols - 1) { + nextColIndex = colIndex + 1; + } else if (rowIndex < totalRows - 1) { nextColIndex = 0; - nextRowIndex = rowIndex === totalRows - 1 ? -1 : rowIndex + 1; + nextRowIndex = rowIndex + 1; } else { - nextColIndex = colIndex + 1; + return; } } else { - // Mimic ArrowLeft key - if (colIndex === 0) { - if (rowIndex === -1) { - // Move to the last cell if the first cell is focused - nextColIndex = totalCols - 1; - nextRowIndex = totalRows - 1; - } else { - nextColIndex = totalCols - 1; - nextRowIndex = rowIndex > 0 ? rowIndex - 1 : -1; - } - } else { + if (colIndex > 0) { nextColIndex = colIndex - 1; + } else if (rowIndex > 0) { + nextColIndex = totalCols - 1; + nextRowIndex = rowIndex - 1; + } else { + return; } } From c518276a8120ff531822a1076588720ca5c45e7e Mon Sep 17 00:00:00 2001 From: Shivam Daksh Date: Sun, 27 Oct 2024 16:00:22 +0530 Subject: [PATCH 05/15] adding the lost comments during refactoring --- lib/KTable/index.vue | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/KTable/index.vue b/lib/KTable/index.vue index ba0bfb32f..08dbef2ad 100644 --- a/lib/KTable/index.vue +++ b/lib/KTable/index.vue @@ -360,15 +360,18 @@ }, handleTabKey(event, rowIndex, colIndex) { + // Identify all focusable elements inside the current cell const currentCell = this.getCell(rowIndex, colIndex); if (!currentCell) return false; + // Collect focusable elements using getFocusableElements(currentCell) const focusableElements = this.getFocusableElements(currentCell); const focusedElementIndex = focusableElements.indexOf(document.activeElement); if (focusableElements.length > 0) { if (!event.shiftKey) { + // if navigating between more focusable elements within the cell if (focusedElementIndex < focusableElements.length - 1) { focusableElements[focusedElementIndex + 1].focus(); event.preventDefault(); @@ -381,6 +384,7 @@ return true; } } + // Allow default behavior when reaching the last cell } const totalRows = this.rows.length; @@ -395,6 +399,7 @@ nextColIndex = 0; nextRowIndex = rowIndex + 1; } else { + // Allow default behavior when reaching the last cell return; } } else { @@ -404,6 +409,7 @@ nextColIndex = totalCols - 1; nextRowIndex = rowIndex - 1; } else { + // Allow default behavior when reaching the last cell return; } } @@ -422,7 +428,7 @@ Array.from(cell.getElementsByTagName(selector)) ); }, - //My code ends here + getCell(rowIndex, colIndex) { if (rowIndex === -1) { return this.$refs[`header-${colIndex}`][0]; From b6f712e67f591660bdf08a423952f3dae5087188 Mon Sep 17 00:00:00 2001 From: Shivam Daksh Date: Sat, 16 Nov 2024 22:53:44 +0530 Subject: [PATCH 06/15] fixing the tab and shift+tab key functionality --- lib/KTable/index.vue | 143 ++++++++++++++++++++----------------------- 1 file changed, 67 insertions(+), 76 deletions(-) diff --git a/lib/KTable/index.vue b/lib/KTable/index.vue index 08dbef2ad..980a6a2f8 100644 --- a/lib/KTable/index.vue +++ b/lib/KTable/index.vue @@ -294,38 +294,32 @@ * - header highlight */ handleKeydown(event, rowIndex, colIndex) { - const key = event.key; - const totalRows = this.rows.length; - const totalCols = this.headers.length; - - let { nextRowIndex, nextColIndex } = this.getNextIndexes( - key, - rowIndex, - colIndex, - totalRows, - totalCols - ); - - if (key === 'Enter' && rowIndex === -1 && this.sortable) { + switch (event.key) { + case 'Enter': + this.handleEnterKey(colIndex); + break; + case 'Tab': + this.handleTabKey(event, rowIndex, colIndex); + break; + case 'ArrowUp': + case 'ArrowDown': + case 'ArrowLeft': + case 'ArrowRight': + this.handleArrowKeys(event.key, rowIndex, colIndex); + break; + default: + break; + } + }, + handleEnterKey(colIndex) { + if (this.sortable) { this.handleSort(colIndex); - } else if (key === 'Tab') { - this.handleTabKey(event, rowIndex, colIndex); - return; - // if (this.handleTabKey(event, rowIndex, colIndex)) { - // return; - // } } - - this.focusCell(nextRowIndex, nextColIndex); - this.focusedRowIndex = nextRowIndex === -1 ? null : nextRowIndex; - this.focusedColIndex = nextColIndex; - - this.highlightHeader(nextColIndex); - - event.preventDefault(); }, - getNextIndexes(key, rowIndex, colIndex, totalRows, totalCols) { + handleArrowKeys(key, rowIndex, colIndex) { + const totalRows = this.rows.length; + const totalCols = this.headers.length; const lastRowIndex = totalRows - 1; const lastColIndex = totalCols - 1; let nextRowIndex = rowIndex; @@ -356,79 +350,76 @@ } break; } - return { nextRowIndex, nextColIndex }; + this.focusCell(nextRowIndex, nextColIndex); + event.preventDefault(); }, - handleTabKey(event, rowIndex, colIndex) { - // Identify all focusable elements inside the current cell - const currentCell = this.getCell(rowIndex, colIndex); + handleEnterKey(colIndex) { + if (this.sortable) { + this.handleSort(colIndex); + } + }, - if (!currentCell) return false; + handleTabKey(event, rowIndex, colIndex) { + const totalRows = this.rows.length; + const totalCols = this.headers.length; + let nextRowIndex = rowIndex; + let nextColIndex = colIndex; - // Collect focusable elements using getFocusableElements(currentCell) + const currentCell = this.getCell(rowIndex, colIndex); const focusableElements = this.getFocusableElements(currentCell); const focusedElementIndex = focusableElements.indexOf(document.activeElement); if (focusableElements.length > 0) { if (!event.shiftKey) { - // if navigating between more focusable elements within the cell if (focusedElementIndex < focusableElements.length - 1) { focusableElements[focusedElementIndex + 1].focus(); event.preventDefault(); - return true; + return; + } else { + if (colIndex < totalCols - 1) { + nextColIndex = colIndex + 1; + } else if (rowIndex < totalRows - 1) { + nextColIndex = 0; + nextRowIndex = rowIndex + 1; + } else { + return; // Allow default tab behavior + } } } else { if (focusedElementIndex > 0) { focusableElements[focusedElementIndex - 1].focus(); event.preventDefault(); - return true; + return; + } else { + if (colIndex > 0) { + nextColIndex = colIndex - 1; + } else if (rowIndex > 0) { + nextColIndex = totalCols - 1; + nextRowIndex = rowIndex - 1; + } else { + return; // Allow default shift+tab behavior + } } } - // Allow default behavior when reaching the last cell - } - - const totalRows = this.rows.length; - const totalCols = this.headers.length; - let nextRowIndex = rowIndex; - let nextColIndex = colIndex; - - if (!event.shiftKey) { - if (colIndex < totalCols - 1) { - nextColIndex = colIndex + 1; - } else if (rowIndex < totalRows - 1) { - nextColIndex = 0; - nextRowIndex = rowIndex + 1; - } else { - // Allow default behavior when reaching the last cell - return; - } - } else { - if (colIndex > 0) { - nextColIndex = colIndex - 1; - } else if (rowIndex > 0) { - nextColIndex = totalCols - 1; - nextRowIndex = rowIndex - 1; - } else { - // Allow default behavior when reaching the last cell - return; - } + this.focusCell(nextRowIndex, nextColIndex); + event.preventDefault(); } - - this.focusCell(nextRowIndex, nextColIndex); - this.focusedRowIndex = nextRowIndex === -1 ? null : nextRowIndex; - this.focusedColIndex = nextColIndex; - this.highlightHeader(nextColIndex); - event.preventDefault(); - return true; }, getFocusableElements(cell) { - const focusableSelectors = ['button', 'a', 'input', 'select', 'textarea']; - return focusableSelectors.flatMap(selector => - Array.from(cell.getElementsByTagName(selector)) - ); + if (!cell) return []; + const selectors = 'button, a, input, select, textarea'; + return Array.from(cell.querySelectorAll(selectors)); }, + // focusCell(rowIndex, colIndex) { + // const cell = this.getCell(rowIndex, colIndex); + // if (cell) { + // cell.focus(); + // } + // }, + getCell(rowIndex, colIndex) { if (rowIndex === -1) { return this.$refs[`header-${colIndex}`][0]; From 0708628d051cb06b09e8f3b67000e23a7ddc231d Mon Sep 17 00:00:00 2001 From: Shivam Daksh Date: Sun, 17 Nov 2024 16:02:46 +0530 Subject: [PATCH 07/15] highlight rows and columns --- lib/KTable/index.vue | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/lib/KTable/index.vue b/lib/KTable/index.vue index 980a6a2f8..22c688d3d 100644 --- a/lib/KTable/index.vue +++ b/lib/KTable/index.vue @@ -295,27 +295,22 @@ */ handleKeydown(event, rowIndex, colIndex) { switch (event.key) { - case 'Enter': - this.handleEnterKey(colIndex); - break; - case 'Tab': - this.handleTabKey(event, rowIndex, colIndex); - break; case 'ArrowUp': case 'ArrowDown': case 'ArrowLeft': case 'ArrowRight': this.handleArrowKeys(event.key, rowIndex, colIndex); break; + case 'Enter': + this.handleEnterKey(colIndex); + break; + case 'Tab': + this.handleTabKey(event, rowIndex, colIndex); + break; default: break; } }, - handleEnterKey(colIndex) { - if (this.sortable) { - this.handleSort(colIndex); - } - }, handleArrowKeys(key, rowIndex, colIndex) { const totalRows = this.rows.length; @@ -351,6 +346,10 @@ break; } this.focusCell(nextRowIndex, nextColIndex); + this.focusedRowIndex = nextRowIndex === -1 ? null : nextRowIndex; + this.focusedColIndex = nextColIndex; + + this.highlightHeader(nextColIndex); event.preventDefault(); }, @@ -403,6 +402,10 @@ } } this.focusCell(nextRowIndex, nextColIndex); + this.focusedRowIndex = nextRowIndex === -1 ? null : nextRowIndex; + this.focusedColIndex = nextColIndex; + + this.highlightHeader(nextColIndex); event.preventDefault(); } }, From fff71d4a55805baf624aa41e078d2ca2bf256e71 Mon Sep 17 00:00:00 2001 From: Shivam Daksh Date: Sun, 17 Nov 2024 17:30:24 +0530 Subject: [PATCH 08/15] tab and shift+tab working but first cell of table not getting focused --- lib/KTable/index.vue | 95 ++++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 42 deletions(-) diff --git a/lib/KTable/index.vue b/lib/KTable/index.vue index 22c688d3d..8d75525b3 100644 --- a/lib/KTable/index.vue +++ b/lib/KTable/index.vue @@ -348,7 +348,6 @@ this.focusCell(nextRowIndex, nextColIndex); this.focusedRowIndex = nextRowIndex === -1 ? null : nextRowIndex; this.focusedColIndex = nextColIndex; - this.highlightHeader(nextColIndex); event.preventDefault(); }, @@ -367,48 +366,67 @@ const currentCell = this.getCell(rowIndex, colIndex); const focusableElements = this.getFocusableElements(currentCell); - const focusedElementIndex = focusableElements.indexOf(document.activeElement); - - if (focusableElements.length > 0) { - if (!event.shiftKey) { - if (focusedElementIndex < focusableElements.length - 1) { - focusableElements[focusedElementIndex + 1].focus(); - event.preventDefault(); - return; + const focusedElement = document.activeElement; + + // Include the cell itself as the first focusable element + const cellAndFocusableElements = [currentCell, ...focusableElements]; + const focusedIndex = cellAndFocusableElements.indexOf(focusedElement); + + if (!event.shiftKey) { + // Tab key navigation + if (focusedIndex < cellAndFocusableElements.length - 1) { + // Move to the next focusable element within the cell + cellAndFocusableElements[focusedIndex + 1].focus(); + event.preventDefault(); + return; + } else { + // Move to the first focusable element of the next cell + if (colIndex < totalCols - 1) { + nextColIndex = colIndex + 1; + } else if (rowIndex < totalRows - 1) { + nextColIndex = 0; + nextRowIndex = rowIndex + 1; } else { - if (colIndex < totalCols - 1) { - nextColIndex = colIndex + 1; - } else if (rowIndex < totalRows - 1) { - nextColIndex = 0; - nextRowIndex = rowIndex + 1; - } else { - return; // Allow default tab behavior - } + return; // Allow default Tab behavior when reaching the end } + const nextCell = this.getCell(nextRowIndex, nextColIndex); + const nextFocusableElements = this.getFocusableElements(nextCell); + const nextCellAndFocusableElements = [nextCell, ...nextFocusableElements]; + nextCellAndFocusableElements[0].focus(); + this.updateFocusState(nextRowIndex, nextColIndex); + event.preventDefault(); + } + } else { + // Shift+Tab key navigation + if (focusedIndex > 0) { + // Move to the previous focusable element within the cell + cellAndFocusableElements[focusedIndex - 1].focus(); + event.preventDefault(); + return; } else { - if (focusedElementIndex > 0) { - focusableElements[focusedElementIndex - 1].focus(); - event.preventDefault(); - return; + // Move to the last focusable element of the previous cell + if (colIndex > 0) { + nextColIndex = colIndex - 1; + } else if (rowIndex > 0) { + nextColIndex = totalCols - 1; + nextRowIndex = rowIndex - 1; } else { - if (colIndex > 0) { - nextColIndex = colIndex - 1; - } else if (rowIndex > 0) { - nextColIndex = totalCols - 1; - nextRowIndex = rowIndex - 1; - } else { - return; // Allow default shift+tab behavior - } + return; // Allow default Shift+Tab behavior when at the beginning } + const prevCell = this.getCell(nextRowIndex, nextColIndex); + const prevFocusableElements = this.getFocusableElements(prevCell); + const prevCellAndFocusableElements = [prevCell, ...prevFocusableElements]; + prevCellAndFocusableElements[prevCellAndFocusableElements.length - 1].focus(); + this.updateFocusState(nextRowIndex, nextColIndex); + event.preventDefault(); } - this.focusCell(nextRowIndex, nextColIndex); - this.focusedRowIndex = nextRowIndex === -1 ? null : nextRowIndex; - this.focusedColIndex = nextColIndex; - - this.highlightHeader(nextColIndex); - event.preventDefault(); } }, + updateFocusState(rowIndex, colIndex) { + this.focusedRowIndex = rowIndex === -1 ? null : rowIndex; + this.focusedColIndex = colIndex; + this.highlightHeader(colIndex); + }, getFocusableElements(cell) { if (!cell) return []; @@ -416,13 +434,6 @@ return Array.from(cell.querySelectorAll(selectors)); }, - // focusCell(rowIndex, colIndex) { - // const cell = this.getCell(rowIndex, colIndex); - // if (cell) { - // cell.focus(); - // } - // }, - getCell(rowIndex, colIndex) { if (rowIndex === -1) { return this.$refs[`header-${colIndex}`][0]; From 59e33b920483487e76cf4f56d0272f34bceffe09 Mon Sep 17 00:00:00 2001 From: Shivam Daksh Date: Wed, 20 Nov 2024 13:51:16 +0530 Subject: [PATCH 09/15] sort the columns only from header row --- lib/KTable/index.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/KTable/index.vue b/lib/KTable/index.vue index f7b1e16c2..ec1d19bb6 100644 --- a/lib/KTable/index.vue +++ b/lib/KTable/index.vue @@ -302,7 +302,7 @@ this.handleArrowKeys(event.key, rowIndex, colIndex); break; case 'Enter': - this.handleEnterKey(colIndex); + this.handleEnterKey(rowIndex, colIndex); break; case 'Tab': this.handleTabKey(event, rowIndex, colIndex); @@ -352,8 +352,8 @@ event.preventDefault(); }, - handleEnterKey(colIndex) { - if (this.sortable) { + handleEnterKey(rowIndex, colIndex) { + if (rowIndex === -1 && this.sortable) { this.handleSort(colIndex); } }, From 0f5bd96be60598c13d075f262426f0d5a9f6e6cd Mon Sep 17 00:00:00 2001 From: Shivam Daksh Date: Wed, 20 Nov 2024 13:55:32 +0530 Subject: [PATCH 10/15] utilize updateFocusState function in arrow keys handling --- lib/KTable/index.vue | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/KTable/index.vue b/lib/KTable/index.vue index ec1d19bb6..e22618c9a 100644 --- a/lib/KTable/index.vue +++ b/lib/KTable/index.vue @@ -346,9 +346,7 @@ break; } this.focusCell(nextRowIndex, nextColIndex); - this.focusedRowIndex = nextRowIndex === -1 ? null : nextRowIndex; - this.focusedColIndex = nextColIndex; - this.highlightHeader(nextColIndex); + this.updateFocusState(rowIndex, colIndex); event.preventDefault(); }, From 354df746696c2ad0dd2a6d0cfd37ebb2fcda24ef Mon Sep 17 00:00:00 2001 From: Shivam Daksh Date: Wed, 20 Nov 2024 14:20:42 +0530 Subject: [PATCH 11/15] change parameter name of updateFocusState function --- lib/KTable/index.vue | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/KTable/index.vue b/lib/KTable/index.vue index e22618c9a..e5d1a5298 100644 --- a/lib/KTable/index.vue +++ b/lib/KTable/index.vue @@ -346,7 +346,7 @@ break; } this.focusCell(nextRowIndex, nextColIndex); - this.updateFocusState(rowIndex, colIndex); + this.updateFocusState(nextRowIndex, nextColIndex); event.preventDefault(); }, @@ -420,10 +420,10 @@ } } }, - updateFocusState(rowIndex, colIndex) { - this.focusedRowIndex = rowIndex === -1 ? null : rowIndex; - this.focusedColIndex = colIndex; - this.highlightHeader(colIndex); + updateFocusState(nextRowIndex, nextColIndex) { + this.focusedRowIndex = nextRowIndex === -1 ? null : nextRowIndex; + this.focusedColIndex = nextColIndex; + this.highlightHeader(nextColIndex); }, getFocusableElements(cell) { From 021bf2844eb296d87365e56b6f64b3ea2f29a52a Mon Sep 17 00:00:00 2001 From: Shivam Daksh Date: Wed, 20 Nov 2024 14:50:26 +0530 Subject: [PATCH 12/15] modify the shift+tab conditions --- lib/KTable/index.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/KTable/index.vue b/lib/KTable/index.vue index e5d1a5298..12aaa46b5 100644 --- a/lib/KTable/index.vue +++ b/lib/KTable/index.vue @@ -345,7 +345,6 @@ } break; } - this.focusCell(nextRowIndex, nextColIndex); this.updateFocusState(nextRowIndex, nextColIndex); event.preventDefault(); }, @@ -396,9 +395,9 @@ } } else { // Shift+Tab key navigation - if (focusedIndex > 0) { + if (focusedIndex < cellAndFocusableElements.length - 1) { // Move to the previous focusable element within the cell - cellAndFocusableElements[focusedIndex - 1].focus(); + cellAndFocusableElements[focusedIndex + 1].focus(); event.preventDefault(); return; } else { @@ -424,6 +423,7 @@ this.focusedRowIndex = nextRowIndex === -1 ? null : nextRowIndex; this.focusedColIndex = nextColIndex; this.highlightHeader(nextColIndex); + this.focusCell(nextRowIndex, nextColIndex); }, getFocusableElements(cell) { From c153871966a86ddce6495817afe04d4dac56e611 Mon Sep 17 00:00:00 2001 From: Shivam Daksh Date: Sat, 23 Nov 2024 18:15:55 +0530 Subject: [PATCH 13/15] replace ternary if-else for readability --- lib/KTable/index.vue | 48 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/lib/KTable/index.vue b/lib/KTable/index.vue index 12aaa46b5..01214ac4d 100644 --- a/lib/KTable/index.vue +++ b/lib/KTable/index.vue @@ -322,24 +322,58 @@ switch (key) { case 'ArrowUp': - nextRowIndex = rowIndex === -1 ? lastRowIndex : rowIndex - 1; + if (rowIndex === -1) { + nextRowIndex = lastRowIndex; + } else { + nextRowIndex = rowIndex - 1; + } break; case 'ArrowDown': - nextRowIndex = rowIndex === -1 ? 0 : rowIndex === lastRowIndex ? -1 : rowIndex + 1; + if (rowIndex === -1) { + nextRowIndex = 0; + } else if (rowIndex === lastRowIndex) { + nextRowIndex = -1; + } else { + nextRowIndex = rowIndex + 1; + } break; case 'ArrowLeft': if (rowIndex === -1) { - nextColIndex = colIndex > 0 ? colIndex - 1 : lastColIndex; - nextRowIndex = colIndex === 0 ? lastRowIndex : -1; + if (colIndex > 0) { + nextColIndex = colIndex - 1; + } else { + nextColIndex = lastColIndex; + } + if (colIndex === 0) { + nextRowIndex = lastRowIndex; + } else { + nextRowIndex = -1; + } } else { - nextColIndex = colIndex > 0 ? colIndex - 1 : lastColIndex; - nextRowIndex = colIndex === 0 ? (rowIndex > 0 ? rowIndex - 1 : -1) : rowIndex; + if (colIndex > 0) { + nextColIndex = colIndex - 1; + } else { + nextColIndex = lastColIndex; + } + if (colIndex === 0) { + if (rowIndex > 0) { + nextRowIndex = rowIndex - 1; + } else { + nextRowIndex = -1; + } + } else { + nextRowIndex = rowIndex; + } } break; case 'ArrowRight': if (colIndex === lastColIndex) { nextColIndex = 0; - nextRowIndex = rowIndex === lastRowIndex ? -1 : rowIndex + 1; + if (rowIndex === lastRowIndex) { + nextRowIndex = -1; + } else { + nextRowIndex = rowIndex + 1; + } } else { nextColIndex = colIndex + 1; } From e84bb622faec167280df25db9e8fca03d4b5d2ef Mon Sep 17 00:00:00 2001 From: Shivam Daksh Date: Sat, 23 Nov 2024 18:17:58 +0530 Subject: [PATCH 14/15] change tab behavior comment --- lib/KTable/index.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/KTable/index.vue b/lib/KTable/index.vue index 01214ac4d..a522d8a8d 100644 --- a/lib/KTable/index.vue +++ b/lib/KTable/index.vue @@ -411,7 +411,7 @@ event.preventDefault(); return; } else { - // Move to the first focusable element of the next cell + // Move to the next cell if (colIndex < totalCols - 1) { nextColIndex = colIndex + 1; } else if (rowIndex < totalRows - 1) { From ed52699043b67b9a5acb600775fa1e46fa1b4cce Mon Sep 17 00:00:00 2001 From: Shivam Daksh Date: Sat, 23 Nov 2024 18:19:47 +0530 Subject: [PATCH 15/15] remove redundant code from tab functionality --- lib/KTable/index.vue | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/KTable/index.vue b/lib/KTable/index.vue index a522d8a8d..73c38166b 100644 --- a/lib/KTable/index.vue +++ b/lib/KTable/index.vue @@ -420,10 +420,6 @@ } else { return; // Allow default Tab behavior when reaching the end } - const nextCell = this.getCell(nextRowIndex, nextColIndex); - const nextFocusableElements = this.getFocusableElements(nextCell); - const nextCellAndFocusableElements = [nextCell, ...nextFocusableElements]; - nextCellAndFocusableElements[0].focus(); this.updateFocusState(nextRowIndex, nextColIndex); event.preventDefault(); } @@ -444,10 +440,6 @@ } else { return; // Allow default Shift+Tab behavior when at the beginning } - const prevCell = this.getCell(nextRowIndex, nextColIndex); - const prevFocusableElements = this.getFocusableElements(prevCell); - const prevCellAndFocusableElements = [prevCell, ...prevFocusableElements]; - prevCellAndFocusableElements[prevCellAndFocusableElements.length - 1].focus(); this.updateFocusState(nextRowIndex, nextColIndex); event.preventDefault(); }