addEventListener 到指定的 html table 列事件 propagation/delegation

addEventListener to specified html table column event propagation/delegation

我有一个包含 10 列的 table,我想通过专门使用 addEventListener 语句向第 5 列到第 8 列添加一个或多个事件侦听器(所以请不要使用 [= 这样的内联事件18=]). table 是动态的,实际上我在编程时不知道 table 在运行时会有多少条记录,因为它只会在那个时刻由数据填充。

我已经知道如何 "aim" 到 table 或 table 行或指定的 table 单元格以向它们添加事件侦听器但不幸的是我不明白如何将它们一次添加到某些列或一系列列("at once" 表示循环遍历每一行以获得每一行的所需单元格)。

编辑

table 只是一个普通的 table,如下例所示,它通过从 csv 文件加载数据记录或通过放置在 table 本身。由于在需要时由 js 动态添加(或删除)的 contenteditable 属性,也可以将数据编辑到 table 本身。

如果我想向一行添加一个事件监听器,我首先获取行对象,然后我将事件监听器添加到它一次:由于事件 propagation/delegation。可以对列做同样的事情吗?

myRow.addEventListener(input, myfunc, false);

换句话说,是否可以这样做:

myCol5.addEventListener(input, myfunc, false);
myCol6.addEventListener(mouseover, myfunc, false);
myCol7.addEventListener(click, myfunc, false);
myCol8.addEventListener(input, myfunc, false);

table, td, th
{
  border: 1px solid black;
  border-collapse: collapse;
}
<table>
  <tr>
    <th>Company</th>
    <th>Contact</th>
    <th>Country</th>
  </tr>
  <tr>
    <td>Alfreds Futterkiste</td>
    <td>Maria Anders</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td>Centro comercial Moctezuma</td>
    <td>Francisco Chang</td>
    <td>Mexico</td>
  </tr>
  <tr>
    <td>Ernst Handel</td>
    <td>Roland Mendel</td>
    <td>Austria</td>
  </tr>
  <tr>
    <td>Island Trading</td>
    <td>Helen Bennett</td>
    <td>UK</td>
  </tr>
  <tr>
    <td>Laughing Bacchus Winecellars</td>
    <td>Yoshi Tannamuri</td>
    <td>Canada</td>
  </tr>
  <tr>
    <td>Magazzini Alimentari Riuniti</td>
    <td>Giovanni Rovelli</td>
    <td>Italy</td>
  </tr>
</table>

利用用户 haxxton 关于添加 类 的想法,您可以使用事件委托来侦听 table 单元格上符合列要求的事件。

// sort of like jQuery's .closest
const findClosest = (element, selector, context) => {
  context = context || element.document || element.ownerDocument
  while (element !== context) {
    if (element.matches(selector)) {
      return element
    }
    element = element.parentNode
  }
  return null
}

document.querySelector('table > tbody').addEventListener('click', function(e) {
  const td = findClosest(e.target, 'td.handleClick', this)
  if (td) {
    console.log('Got a click on', td)
  }
}, false)
<!-- adding classes for columns 1 and 3 -->
<table border="1" cellpadding="10">
<tbody>
  <tr>
    <td class="handleClick">
      <span>ONE</span>
    </td>
    <td>TWO</td>
    <td class="handleClick">THREE</td>
  </tr>
  <tr>
    <td class="handleClick">ONE</td>
    <td>TWO</td>
    <td class="handleClick">THREE</td>
  </tr>
</tbody>
</table>

有关该方法的详细信息,请参阅 Element.matches

在某些用例中,您可以使用事件委托,然后遍历 TR 的子项以从那里找到列的索引,您可以轻松触发特定于每个列的函数,因为它已委托给 table 任何动态创建的单元格都将准备好事件侦听器。

这对于简单的 tables 没问题,但如果涉及行跨度,则可能无法正常工作 - 类 或属性可能是 tables 的更好选择。

document.getElementById('myTable').addEventListener('click', function(e){
  var elem = e.target;
  var tr = closestTag(elem, "TR"); // Find which TR was clicked
  var td = (elem.tagName == "TD") ? elem : closestTag(elem, "TD"); // Find the TD that was clicked
  if(tr && td){
    var column =  TdIndex(e.target, tr); // Figure out which column was clicked 
    console.log("Column Clicked", column);   
  }
});

function closestTag(elem, tag){ // Moves up the DOM tree till it finds <tag> || <body> 
   while(elem.parentNode.tagName != tag && elem.tagName != 'BODY'){
     elem = elem.parentNode;
   }
   return (elem.tagName == 'BODY') ? false : elem.parentNode; 
}

function TdIndex(elem, tr){ // Returns the index of a TD contained in a TR
  for(var i=0; i < tr.children.length; i++){
    if(tr.children[i] == elem) return i;
  }
  return false;
}
<table id="myTable">
  <tr>
    <th>Company</th>
    <th>Contact</th>
    <th>Country</th>
  </tr>
  <tr>
    <td>Alfreds Futterkiste</td>
    <td>Maria Anders</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td>Centro comercial Moctezuma</td>
    <td>Francisco Chang</td>
    <td>Mexico</td>
  </tr>
  <tr>
    <td>Ernst Handel</td>
    <td>Roland Mendel</td>
    <td>Austria</td>
  </tr>
  <tr>
    <td>Island Trading</td>
    <td>Helen Bennett</td>
    <td>UK</td>
  </tr>
  <tr>
    <td>Laughing Bacchus Winecellars</td>
    <td>Yoshi Tannamuri</td>
    <td>Canada</td>
  </tr>
  <tr>
    <td>Magazzini Alimentari Riuniti</td>
    <td>Giovanni Rovelli</td>
    <td>Italy</td>
  </tr>
</table>

使用 window.event.target.cellIndex 可以获得作为列索引的单击单元格的单元格索引(从 0 到 n,其中 n 是 table 列的数量 - 1)。

使用 window.event.target.parentNode.rowIndex 可以获得被单击单元格的行索引(从 0 到 n,其中 n 是 table 行的数量 - 1),即 row/record指数.

示例:

  var col = window.event.target.cellIndex;
  var row = window.event.target.parentNode.rowIndex;

工作示例:

document.getElementById('myTbl').addEventListener('click', function(){myFunction(event)}, false);

function myFunction()
{
  var col = window.event.target.cellIndex;
  var row = window.event.target.parentNode.rowIndex;
  alert('Col index is: ' + col + '\nRow index is: ' + row);
  
  // At this point it is easy to do something like:
  // if(col > 5 && col < 8)
  {
    //Execute this stuff 
  }
}
table, td {
    border: 1px solid black;
}
<p>Click on each td element to alert its position in the table row.</p>

<table id="myTbl">
  <tr>
    <td>Click to show cellIndex</td>
    <td>Click to show cellIndex</td>
    <td>Click to show cellIndex</td>
    <td>Click to show cellIndex</td>
  </tr>
  <tr>
    <td>Click to show cellIndex</td>
    <td>Click to show cellIndex</td>
    <td>Click to show cellIndex</td>
    <td>Click to show cellIndex</td>
  </tr>
  <tr>
    <td>Click to show cellIndex</td>
    <td>Click to show cellIndex</td>
    <td>Click to show cellIndex</td>
    <td>Click to show cellIndex</td>
  </tr>
  <tr>
    <td>Click to show cellIndex</td>
    <td>Click to show cellIndex</td>
    <td>Click to show cellIndex</td>
    <td>Click to show cellIndex</td>
  </tr>
</table>