keydown on a table inside a contentEditable div

2019-06-08 17:32发布

问题:

I have a div in my dom which is contentEditable and that div contains a table inside it.

<div contentEditable>

   <table id="editableTable">
      <tr>
         <td> My content </td>
     </tr>
  </table>
</div>

I can edit the value of td.

But however when I attach a keydown event listner on that table (or td), the event is not triggered. The keydown is triggered on the contentEditable div only.

How to listen to the keydown event on the table(or td) but not on the contentEditable div?

回答1:

Only elements that can receive focus (such as inputs and contenteditable elements) fire key events. This does not include elements within contenteditable elements.

You can use the selection object to check where the caret is and therefore whether the key event originated from somewhere inside the table. The following will work in all major browsers except IE <= 8:

function isOrIsDescendantOf(node, ancestorNode) {
  while (node) {
    if (node == ancestorNode) {
      return true;
    }
    node = node.parentNode;
  }
  return false;
}

function caretIsInside(node) {
  if (window.getSelection) {
    var sel = window.getSelection();
    if (sel.focusNode) {
      return isOrIsDescendantOf(sel.focusNode, node);
    }
  }
  return false;
}
  
window.onload = function() {
  document.getElementById("editor").addEventListener("keydown", function() {
    var table = document.getElementById("editableTable");
    document.getElementById("info").innerHTML = "keydown came from table: " + caretIsInside(table);
  }, false);
};
table * {
  color: blue;
  font-weight: bold;
}
<div contenteditable="true" id="editor">
  <p>Non-table content. Type in here</p>

   <table id="editableTable">
      <tr>
         <td>Table content. Type in here</td>
     </tr>
  </table>
</div>
<div id="info"></div>