【问题标题】:Read HTML table with merged cells row for row, or column for column读取包含合并单元格的 HTML 表格,逐行或逐列
【发布时间】:2021-01-09 01:33:34
【问题描述】:

我有一张这样的桌子:

table {
  border-collapse: collapse;
}

td, th {
  border: 1px solid black;
  width: 3em;
  height: 3em;
  text-align: center;
}

.corner {
  border: none;
}
<table>
  <thead><tr><td class="corner"></td><th>A</th><th>B</th><th>C</th><th>D</th></tr></thead>
  <tr><th>1</th><td rowspan="3">A1:A3</td><td>B1</td><td>C1</td><td>D1</td></tr>
  <tr><th>2</th><td>B2</td><td>C2</td><td>D2</td></tr>
  <tr><th>3</th><td>B3</td><td>C3</td><td>D3</td></tr>
  <tr><th>4</th><td>A4</td><td>B4</td><td>C4</td><td>D4</td></tr>
  <tr><th>5</th><td rowspan="2">A5:A6</td><td>B5</td><td rowspan="2" colspan="2">C5:D6</td></tr>
  <tr><th>6</th><td>B6</td></tr>
</table>

如果我尝试使用 table.rows[row_index].cells[3] 读取 C 列,我会得到单元格 [C, C1, D2, D3, C4, C5:D6],但我想得到 [C, C1, C2, C3, C4, C5:D6]。同样,如果我尝试读取第 6 行,我只会得到 [6, B6],但我想得到 [6, A5:A6, B6, C5:D6]。一个二维数组(矩阵),其维度等于表格的维度,其中合并的单元格存在于多个索引处,这将是理想的。

我寻找一个 DOM API 来获取显示的单元格的起始行/列,但找不到任何有用的东西。 rowspancolspan 属性有访问器,默认为 1 并将属性解析为数字。使用table.rows[y].cells[x] 确实比直接查询元素更容易处理theadtbody 等不同部分。

我确实发现有a specification for how to place cells into slots,在浏览器内部使用。虽然它确实描述了如何确定我在寻找什么的基本事实,但它还处理了纠正 HTML 作者犯的错误以及我的用例的许多其他不必要的细节。

如何构造一个二维数组,其中每行/列对映射到那里显示的单元格?

【问题讨论】:

    标签: javascript dom html-table


    【解决方案1】:

    colspanrowspan 属性分别仅以 row.cellstable.rows 的迭代顺序跨越。因此,我们可以使用我们正在构建的数组来填充一行中的第一个可用空间。

    如果表格格式错误且缺少单元格或多余单元格,此方法不会用空值填充数组。

    function getTableSlots(table) {
      const slots = []
      for(const row of table.rows) {
        for(const cell of row.cells) {
          let x = cell.cellIndex, y = row.rowIndex
          while(slots[y] && slots[y][x]) x++
          for(let dx = 0; dx < cell.colSpan; dx++) {
            for(let dy = 0; dy < cell.rowSpan; dy++) {
              while(y+dy >= slots.length) slots.push([])
              slots[y+dy][x+dx] = cell
            }
          }
        }
      }
      return slots
    }
    
    const slots = getTableSlots(document.querySelector("table"))
    
    // Format for snippet console
    console.log(`[
      ${slots.map(row => {
        return JSON.stringify(row.map(cell => cell.textContent.padEnd(5)))
      }).join(",\n  ")}
    ]`)
    // For real console
    console.log(slots)
    table {
      border-collapse: collapse;
    }
    
    td, th {
      border: 1px solid black;
      width: 3em;
      height: 3em;
      text-align: center;
    }
    
    .corner {
      border: none;
    }
    <table>
      <thead><tr><td class="corner"></td><th>A</th><th>B</th><th>C</th><th>D</th></tr></thead>
      <tr><th>1</th><td rowspan="3">A1:A3</td><td>B1</td><td>C1</td><td>D1</td></tr>
      <tr><th>2</th><td>B2</td><td>C2</td><td>D2</td></tr>
      <tr><th>3</th><td>B3</td><td>C3</td><td>D3</td></tr>
      <tr><th>4</th><td>A4</td><td>B4</td><td>C4</td><td>D4</td></tr>
      <tr><th>5</th><td rowspan="2">A5:A6</td><td>B5</td><td rowspan="2" colspan="2">C5:D6</td></tr>
      <tr><th>6</th><td>B6</td></tr>
    </table>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多