addEventListener指定的html表列事件传播/委托

时间:2017-02-02 02:01:45

标签: javascript html-table multiple-columns addeventlistener

我有一个包含10列的表,我希望通过使用特定的addEventListener语句将一个或多个事件侦听器添加到第5到第8列(因此请不要使用element.onclick等内联事件)。 该表是动态的,实际上我在编程时不知道该表在运行时将有多少条记录,因为它只会在那一刻被数据填充。

我已经知道如何“瞄准”一个表或一个表行或一个指定的表单元格来向它们添加事件监听器但不幸的是我不明白如何将它们添加到某些列或一系列的列一次(“一次”表示循环遍历每一行以获取每个行的所需单元格的for循环。)

修改

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

如果我想在行中添加一个事件监听器,我首先得到行对象,然后我将eventlistener添加到它一次:由于事件传播/委托,所有td元素都会受到影响。是否可以对列进行相同的操作?

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>

3 个答案:

答案 0 :(得分:0)

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

// 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

答案 1 :(得分:0)

在某些用例中,您可以使用事件委派,然后遍历TR的子节点,从那里找到列的索引,您可以轻松地触发特定于每列的函数,并将其委派给在表中任何动态创建的单元格都可以使用事件监听器。

这对于简单的表来说没问题,但如果涉及了rowpans则可能不行 - 对于像这样的表,类或属性可能是更好的选择。

&#13;
&#13;
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;
}
&#13;
<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>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

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

使用 var col = window.event.target.cellIndex; var row = window.event.target.parentNode.rowIndex; 可以获得作为行/记录索引的单击单元格的行索引(从0到n,其中n是表行数 - 1)。

实施例

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>
myBooks: [
{
  book: ObjectId: hj123bkj123,
  progress: 12%
},
{
  book: ObjectId: hj123bkj124,
  progress: 32%
},
...
]