Skip to content

Commit

Permalink
WIP: Cell selection seems to work correctly now
Browse files Browse the repository at this point in the history
This is down to re-implementing fromCoords (that maps row/col to a DOM node)
and CellRef (that finds the row/col of a DOM node).

Still remaining:

- Remove all the ABS DEBUG logging
- Make the logic that styles cells in the rectangle aware of rowspans and colspans
- Make the selection expand to cover all rows/cols of a merged cell when the user
  drags over it (even if the user did not otherwise drag into those rows/cols)
  • Loading branch information
alaricsp committed Sep 19, 2024
1 parent fd3e27b commit 69d1a02
Showing 1 changed file with 83 additions and 25 deletions.
108 changes: 83 additions & 25 deletions lib/importer/assets/js/selectable_table.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,23 +80,73 @@ window.addEventListener("load", function() {
let CellRef = class {
constructor(element) {
this.node = element.closest("td, th");
this.table = this.node.closest("table");

// Find column, by counting left and adding up colspans
this.col = 1;
let nodeWalker = this.node;
while(nodeWalker.previousElementSibling) {
if(nodeWalker.colspan) {
this.col += nodeWalker.colspan;
} else {
this.col ++;
}
nodeWalker = nodeWalker.previousElementSibling
}
console.log("ABS DEBUG CellRef", this.node);

// Find the cell, by walking down the table from the top left

// We need to scan every row above the cell, in order to find cells that
// rowspan down to later rows, as any rowspans that encroach on the row
// of our target cell to the left of it will create virtual cells
// without a corresponding <td>, and we need to account for them in
// calculating the column index.

// 0,0 (1,0) | 2,0
// +------
// (0,1) (1,1) | 2,1

// ...if the node selected is 2,1 then it's actually the first <td> on
// that <tr>, but it's column index 2 nonetheless due to the two cells
// from 0,0 which has colspan=2 rowspan=2.

const rowspans = new Map(); // Column index -> row index where current rowspan for that colum ends
for(let rowIdx=0;rowIdx<this.table.rows.length;rowIdx++) {
const row = this.table.rows[rowIdx];
console.log("ABS DEBUG CellRef row", rowIdx, row.cells, rowspans);
let colLogicalIdx = 0; // Actual column index, accounting for virtual cells
for(let colIdx=0;colIdx<row.cells.length;colIdx++) {
console.log("ABS DEBUG CellRef cell", colIdx, colLogicalIdx);
// advance colLogicalIdx, taking note of rowspans that are adding extra cells to this row
while(true) {
const rowspanUntil = rowspans.get(colLogicalIdx) || -1;
console.log("ABS DEBUG CellRef rowspan check", colLogicalIdx, rowspanUntil, rowIdx);
if(rowspanUntil >= rowIdx) { // ABS FIXME this bit is wrong and I need to work out how to distinguish colspan entries arising from actual <td>s on this row from those included from rowspans above this row
console.log("ABS DEBUG CellRef skipping rowspan inclusion");
colLogicalIdx++;
} else {
break;
}
}
console.log("ABS DEBUG CellRef cell adjusted", colIdx, colLogicalIdx);

const currentCell = row.cells[colIdx];
const colspan = currentCell.colSpan || 1;
const rowspan = currentCell.rowSpan || 1;

if(currentCell == this.node) {
// Found it!
this.col = colLogicalIdx;
this.row = rowIdx;
console.log("ABS DEBUG CellRef found it", this.col, this.row, this.node.textContent);
return;
}

this.table = this.node.closest("table");
// Record rowspan ending rows for every column we touch
for(let i=0;i<colspan;i++) {
if(rowspan > 1) {
console.log("ABS DEBUG CellRef set rowspans", colLogicalIdx+i, rowIdx+rowspan-1);
rowspans.set(colLogicalIdx+i, rowIdx+rowspan-1);
} else {
console.log("ABS DEBUG CellRef clear rowspans", colLogicalIdx+i, rowIdx+rowspan-1);
rowspans.set(colLogicalIdx+i, -1);
}
}

// Find row, by counting down from the top
this.row = this.node.parentElement.rowIndex;
// Advance logical index, although it may be advanced more on the next loop iteration
colLogicalIdx+=colspan;
}
}
};

get left() { return CellRef.fromCoords(this.table, this.row + 0, this.col - 1); }
Expand Down Expand Up @@ -154,20 +204,28 @@ window.addEventListener("load", function() {
// coordinates
while(true) {
const currentCell = currentRow.cells[colIdx];
const colspan = currentCell.colspan || 1;
const rowspan = currentCell.rowspan || 1;
console.log("ABS DEBUG fromCoords cell", rowIdx, colIdx, colLogicalIdx, currentCell, colspan, rowspan);
const colspan = currentCell.colSpan || 1;
const rowspan = currentCell.rowSpan || 1;
console.log("ABS DEBUG fromCoords cell", rowIdx, colIdx, colLogicalIdx, currentCell.textContent, colspan, rowspan);
if(rowIdx <= row && colLogicalIdx <= col &&
(rowIdx+rowspan) >= row && (colLogicalIdx+colspan) >= col) {
console.log("ABS DEBUG fromCoords done");
(rowIdx+rowspan-1) >= row && (colLogicalIdx+colspan-1) >= col) {
console.log("ABS DEBUG fromCoords done", col, row, currentCell.textContent);
currentCell.textContent = currentCell.textContent + " (" + col + "," + row + ")";
// We have found a cell that is, or encompasses, our target coords
return new CellRef(currentCell);
}

// Record rowspan ending rows for every column we touch
for(let i=0;i<colspan;i++) {
console.log("ABS DEBUG fromCoords set rowspans", colLogicalIdx+i, rowIdx+rowspan-1);
rowspans.set(colLogicalIdx+i, rowIdx+rowspan-1);
if(rowspan>1) {
for(let i=0;i<colspan;i++) {
console.log("ABS DEBUG fromCoords set rowspans", colLogicalIdx+i, rowIdx+rowspan-1);
rowspans.set(colLogicalIdx+i, rowIdx+rowspan-1);
}
} else {
for(let i=0;i<colspan;i++) {
console.log("ABS DEBUG CellRef clear rowspans", colLogicalIdx+i, rowIdx+rowspan-1);
rowspans.set(colLogicalIdx+i, -1);
}
}

// Move to the next cell
Expand All @@ -176,7 +234,6 @@ window.addEventListener("load", function() {
// or advanced past the cell of interest so no further cells on this
// row can be the one we want, or influence our search for it via
// rowspans affecting later rows
console.log("ABS DEBUG fromCoords step row");
colIdx = 0;
colLogicalIdx = 0;
rowIdx++;
Expand All @@ -186,17 +243,18 @@ window.addEventListener("load", function() {
return null;
}
currentRow = table.rows[rowIdx];
console.log("ABS DEBUG fromCoords step row", rowIdx, rowspans);
} else {
// Ok, there are more cells in this row
colIdx++;
colLogicalIdx++;
colLogicalIdx+=colspan;
}

console.log("ABS DEBUG fromCoords result of step", rowIdx, colIdx, colLogicalIdx);

// Account for rowspan inclusions from higher rows, that take up
// logical column indexes in this row without an actual <td>
while(rowspans.get(colLogicalIdx) > rowIdx) {
while(rowspans.get(colLogicalIdx) >= rowIdx) {
console.log("ABS DEBUG fromCoords skip rowspan cell", colLogicalIdx, rowspans.get(colLogicalIdx));
colLogicalIdx++;
}
Expand Down

0 comments on commit 69d1a02

Please sign in to comment.