Skip to content

Commit 3cd8ef4

Browse files
Fix table selection logic to handle reversed coordinates and add corresponding tests (#3228)
1 parent 77cb55a commit 3cd8ef4

File tree

2 files changed

+68
-13
lines changed

2 files changed

+68
-13
lines changed

packages/roosterjs-content-model-plugins/lib/announce/tableSelectionUtils.ts

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,13 @@ export function retrieveStringFromParsedTable(tsInfo: TableSelectionInfo): strin
1111
let result = '';
1212

1313
if (lastCo) {
14-
for (let r = firstCo.row; r <= lastCo.row; r++) {
15-
for (let c = firstCo.col; c <= lastCo.col; c++) {
14+
const firstCol = Math.min(firstCo.col, lastCo.col);
15+
const lastCol = Math.max(firstCo.col, lastCo.col);
16+
const firstRow = Math.min(firstCo.row, lastCo.row);
17+
const lastRow = Math.max(firstCo.row, lastCo.row);
18+
19+
for (let r = firstRow; r <= lastRow; r++) {
20+
for (let c = firstCol; c <= lastCol; c++) {
1621
const cell = parsedTable[r] && parsedTable[r][c];
1722
if (cell && typeof cell != 'string') {
1823
result += ' ' + cell.innerText + ',';
@@ -80,15 +85,4 @@ export function getIsSelectingOrUnselecting(
8085
// Same area but different positions
8186
return 'selecting';
8287
}
83-
84-
if (
85-
prevFirstColumn !== newFirstColumn ||
86-
prevFirstRow !== newFirstRow ||
87-
prevLastColumn !== newLastColumn ||
88-
prevLastRow !== newLastRow
89-
) {
90-
return 'selecting';
91-
}
92-
93-
return null;
9488
}

packages/roosterjs-content-model-plugins/test/announce/tableSelectionUtilsTest.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,5 +410,66 @@ describe('tableSelectionUtils', () => {
410410
const result = getIsSelectingOrUnselecting(null, newTableSelection);
411411
expect(result).toBe('selecting');
412412
});
413+
414+
it('should work with actual parsed table when lastCo is before firstCo', () => {
415+
// Create actual table cells with content
416+
const td1 = document.createElement('td');
417+
td1.innerText = 'A1';
418+
const td2 = document.createElement('td');
419+
td2.innerText = 'B1';
420+
const td3 = document.createElement('td');
421+
td3.innerText = 'C1';
422+
const td4 = document.createElement('td');
423+
td4.innerText = 'A2';
424+
const td5 = document.createElement('td');
425+
td5.innerText = 'B2';
426+
const td6 = document.createElement('td');
427+
td6.innerText = 'C2';
428+
const td7 = document.createElement('td');
429+
td7.innerText = 'A3';
430+
const td8 = document.createElement('td');
431+
td8.innerText = 'B3';
432+
const td9 = document.createElement('td');
433+
td9.innerText = 'C3';
434+
435+
const mockTableSelectionInfo: TableSelectionInfo = {
436+
parsedTable: [
437+
[td1, td2, td3],
438+
[td4, td5, td6],
439+
[td7, td8, td9],
440+
],
441+
firstCo: { row: 2, col: 2 }, // C3
442+
lastCo: { row: 0, col: 0 }, // A1 - lastCo before firstCo
443+
table: document.createElement('table'),
444+
startNode: td1,
445+
};
446+
447+
// Test that retrieveStringFromParsedTable works with reversed coordinates
448+
const extractedText = retrieveStringFromParsedTable(mockTableSelectionInfo);
449+
expect(extractedText).toBe(' A1, B1, C1, A2, B2, C2, A3, B3, C3,');
450+
451+
const prevTableSelection: TableSelection = {
452+
type: 'table',
453+
table: document.createElement('table'),
454+
firstRow: 2,
455+
firstColumn: 2,
456+
lastRow: 0,
457+
lastColumn: 0,
458+
tableSelectionInfo: mockTableSelectionInfo,
459+
}; // 3x3 selection with lastCo before firstCo (area = 9)
460+
461+
const newTableSelection: TableSelection = {
462+
type: 'table',
463+
table: document.createElement('table'),
464+
firstRow: 1,
465+
firstColumn: 1,
466+
lastRow: 1,
467+
lastColumn: 1,
468+
tableSelectionInfo: mockTableSelectionInfo,
469+
}; // Single cell selection (area = 1)
470+
471+
const result = getIsSelectingOrUnselecting(prevTableSelection, newTableSelection);
472+
expect(result).toBe('unselecting'); // Area decreased from 9 to 1
473+
});
413474
});
414475
});

0 commit comments

Comments
 (0)