使用数据集捕获儿童的所有事件

时间:2018-12-29 19:48:27

标签: javascript dom dom-events

我有一个带有孩子的包装器(DIV),包装器上有一个事件侦听器。我想处理键盘并通过包装上的 dataset 值单击事件。

在捕获包装器中所有针对孩子的事件。

简单的例子:

let wrap = document.getElementById("wrap");
let status = document.getElementById("status");
let keyact = {
    a: function(e) {
        status.textContent = "Do A " + e.key;
    },
    b: function(e) {
        status.textContent = "Do B " + e.key;
    },
};

function keycheck(e) {
    let t = e.target,
        d = t.dataset;
    status.textContent = "X trap";
    if (d.keyact && keyact[d.keyact])
        keyact[d.keyact](e);
    else
        status.textContent = "No trap";
}
function tabtrap(e) {
    if (e.target.className == "tab_trap")
        wrap.focus();
}
document.addEventListener('keydown', keycheck);
document.addEventListener('keyup', tabtrap);
status.textContent = "ready";
div, a {
  border  : 1px solid #eee;
  margin: 2px;
}
*:focus {
  border  : 1px solid red;
  outline : 0;
}
<div tabindex=0 class="tab_trap"></div>
<div id="wrap" data-keyact="a" tabindex=0>
  <ul>
    <li><a href="#">Dummy 1</a></li>
    <li><a href="#">Dummy 2</a></li>
    <li><a href="#">Dummy 3</a></li>
  </ul>
</div>
<div tabindex=0 class="tab_trap"></div>
<p id="status"></p>

如果用户在#wrap DIV处于焦点状态时按了一个键,则会处理keyact函数(因为它的 dataset -act值为{{1} }。

我希望在将焦点放在DIV包装器的任何子元素上时按下键时执行a。例如,“虚拟对象1” 设置每个子元素的数据集值。

如果将keyact.a()的值更改为data-keytrap,我希望执行b等。

1 个答案:

答案 0 :(得分:1)

如果我正确理解了您的问题,则您尝试基于keyact中显示的相应DOM属性调用#wrap中的函数。有很多方法可以实现,但是以下内容应满足您的要求(有关更多详细信息,请参见摘录中的注释):

let status = document.getElementById("status");
let keyact = {
    a: function(e) {
        status.textContent = "Do A " + e.key;
    },
    b: function(e) {
        status.textContent = "Do B " + e.key;
    },
};

// Query all nodes in document with data-keyact attribute
document.body.querySelectorAll('[data-keyact]').forEach(element => {

  // For this data-keyact node add keydown event handler
  element.addEventListener('keydown', function(event) {
  
    // When keydown event happens, access the "keyact" attribute value from #wrap
    const actionKey = element.dataset.keyact;
    
    // Access the keyact function by the aquired actionkey
    const actionFunction = keyact[actionKey];

    // Saftey check - make sure actionFunction is a function before attempting to call
    // it
    if(typeof actionFunction === 'function') {
    
      // Pass the keydown event to actionFunction
      actionFunction(event);
    }
    
    // This is important, we don't want the keydown behaviour to propagate
    // up to parent nodes with same attribute
    event.stopPropagation();
  });
  
  // For this #wrap decendant, add keyup event handler
  element.addEventListener('keyup', function(event) {
    
    // When keyup happens, refocus the element
    element.focus();
    
    // This is important, we don't want the keyup focus behavior to propagate
    // up to parent nodes with same attribute
    event.stopPropagation();
  });

});
div, a {
  border  : 1px solid #eee;
  margin: 2px;
}
*:focus {
  border  : 1px solid red;
  outline : 0;
}
<div tabindex=0 class="tab_trap"></div>
<div id="wrap" data-keyact="a" tabindex=0> (keyact a)
  <ul>
    <li><a data-keyact="b" href="#">Dummy 1 (keyact b)</a></li>
    <li><a href="#">Dummy 2</a></li>
    <li><a href="#">Dummy 3</a></li>
  </ul>
</div>
<div tabindex=0 class="tab_trap"></div>
<p id="status"></p>