【问题标题】:Javascript - Get element behind caret in child elements of [contenteditable]Javascript - 在 [contenteditable] 的子元素中获取插入符号后面的元素
【发布时间】:2016-02-29 22:16:12
【问题描述】:

我正在用 Javascript 构建一个简单易用的文本编辑器,基本上是一个所见即所得的编辑器。我将在主包装器 (.wrapper) 中使用 contenteditable 属性。当您在 .wrapper 中按 Enter 键时,带有唯一 id 的新 <p> 元素将附加到包装器中。

我需要一种方法来获取当前选中的 .wrapper 的哪个子元素(即,被聚焦或在其中包含插入符号/文本标记)。

我搜索了几天没有任何结果,我尝试使用document.elementFromPoint(),但没有任何正确的结果。

当使用$(":focus") 时,我得到整个.wrapper 而不是特定的子元素。

编辑:

示例 HTML 结构:

<div class="container t-wrapper" contenteditable>
</div>

示例 Javascript 代码:

$(document).ready(function() {
    $currentElement = $("[contenteditable]");

    $(".t-wrapper").each(function() {
        var id = generateIdentifier(6); // Ignore this

        /* This creates the initial <p> child element, where you start typing. */
        $(this).html('<p class="t-empty t-first" id="' + id + '"></p>');

        $(this).on("mouseup", function() {
            /* $currentElement = whatever element the caret is inside. */
        });

        $(this).on("keyup", function() {
            /* $currentElement = whatever element the caret is inside. */
        });
    ));
});

编辑 2:

我设法让它在mouseup 事件中正常工作,因为您实际上是在点击某些东西。但是在使用键盘移动插入符号时,我需要它来工作。或者,我需要一些方法来获取插入符号的位置(以像素为单位),然后使用document.elementFromPoint() 来获取特定元素。

【问题讨论】:

  • 您是否尝试过仅在选定节点上使用 contenteditable?例如,您可以将新的p 设置为contenteditable="true",同时对所有其他元素禁用它。导航节点树(单击或箭头键)时,您可以将contenteditable 属性移动到下一个元素。这似乎至少使子节点可以使用:focus 搜索。
  • 一段代码,好吗?
  • @freestock.tk 添加了一些基本示例代码。
  • 非常感谢。如果我发现了新的东西,我会告诉你的。
  • @E.Sundin 我尝试了你的建议,但是到处更改 contenteditable 只会把事情搞砸

标签: javascript jquery html css contenteditable


【解决方案1】:

:focus 不会选择您的元素,因为它们不可聚焦。

您可以通过在 HTML 中添加 tabindex="-1" 或在 JS 中添加 tabIndex = -1 来使它们具有焦点。

var generateIdentifier = Math.random;
var currentElement = document.querySelector("[contenteditable]");
[].forEach.call(document.querySelectorAll(".t-wrapper"), function(el) {
  var first = document.createElement('p');
  first.className = "t-empty t-first";
  first.id = generateIdentifier(6);
  first.textContent = 'Press enter to create new paragraphs';
  first.tabIndex = -1;
  el.appendChild(first);
});
.container > :focus {
  border: 1px solid blue;
}
&lt;div class="container t-wrapper" contenteditable&gt;&lt;/div&gt;

似乎如果将它添加到第一段,新的段落会自动获得它。但如果你想确定的话,我想你可以使用突变观察者或 keyup 事件监听器来检测没有tabindex 的段落,并添加它:

el.addEventListener("keyup", function(e) {
  var newChild = el.querySelector('p:not([tabindex])');
  if(newChild) newChild.tabIndex = -1;
});

【讨论】:

  • 感谢您的回复!我一定会对此进行测试。您首先提到了tabindex="1",但在代码中您将索引指定为-1。这是为什么?错字?
  • @DanielPox 我的意思是-1。当您按下 Tab 键时,焦点会根据tabindex 转到下一个可聚焦元素。 tabindex = -1 使元素可聚焦但不可通过 tab 键迭代。如果您希望它们可迭代,请使用正数。
  • 该死,Chrome 不会在你写这些段落时考虑它们的焦点,即使它们是可聚焦的。
【解决方案2】:

document.activeElement 将返回当前焦点元素。

【讨论】:

  • 这和写$(":focus")一样,这标志着整个.wrapper,因为我猜那是带有contenteditable属性的元素。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-14
  • 2017-04-22
  • 2011-06-16
  • 1970-01-01
  • 2011-08-22
  • 2011-06-17
  • 1970-01-01
相关资源
最近更新 更多