【问题标题】:contenteditable div: IE8 not happy with backspace remove of HTML elementcontenteditable div:IE8 对 HTML 元素的退格删除不满意
【发布时间】:2012-04-16 13:15:35
【问题描述】:

我正在使用 contenteditable div 结合 rangy Javascript 库在光标位置插入 HTML。

div 的内容通常如下所示:

<div contenteditable="true">
    "Hello "
    <button contenteditable="false" data-id="147">@John Smith</button>
    " "
</div>

用户在按下“@”时会得到建议,然后在被选中时作为按钮插入(ala Google Plus)。我还在此按钮后插入了&amp;nbsp;

当您按退格键(在第一次删除 &amp;nbsp; 之后)时,Chrome/Safari/Firefox 中的按钮会被删除,但在 IE8 中不会。在 IE8 中,光标只是跳过按钮而不删除它。在 IE8 中更奇怪的是,如果您将 &amp;nbsp; 留在按钮旁边 - 而是将光标放在按钮旁边 - 它会删除退格键上的按钮。所以当光标右侧有一个&amp;nbsp; 时会很高兴。

有谁知道我需要什么才能让 IE8 独立运行。在退格键上删除按钮而不需要光标右侧的&amp;nbsp;? (有关这种奇怪行为的一些信息也可能有所帮助)

附:其他版本的IE我没测试过

【问题讨论】:

  • 为什么按钮上有 contenteditable=false?
  • 这样当您点击退格键或点击删除时(这目前在 Chrome/Safari/Firefox 中有效),它会(一次性)从 DOM 中删除它。如果 contenteditable=true 则按钮的文本变为可编辑的,这不是我的用例。
  • 酷我不知道。 (我之前没有在 contEd 中处理过输入)。如何处理退格键并检查选择范围内第一个节点的上一个节点?
  • 我不确定如何检查选择范围内第一个节点的前一个兄弟节点。我知道你可以删除一个范围的内容。指针?
  • 这是你的意思吗:stackoverflow.com/questions/2177958/…

标签: javascript html internet-explorer-8 contenteditable rangy


【解决方案1】:

我的建议是首先检查插入符号是否位于不可编辑节点之后,如果是,则创建一个范围,该范围紧随不可编辑元素之后开始并在插入符号位置结束。检查此范围内的文本是否为空。如果是,则意味着插入符号直接放在不可编辑元素之后,因此在这种情况下删除该元素。最后,将插入符号放在不可编辑的位置。

现场演示:http://jsfiddle.net/timdown/vu3ub/

代码:

document.onkeypress = function(e) {
    e = e || window.event;
    var keyCode = e.which || e.keyCode;
    if (keyCode !== 8) {
        return;
    }

    var sel = rangy.getSelection();
    if (sel.rangeCount === 0) {
        return;
    }

    var selRange = sel.getRangeAt(0);
    if (!selRange.collapsed) {
        return;
    }

    var nonEditable = document.getElementById("nonEditable");
    if (!nonEditable) {
        return;
    }

    // Check the caret is located after the non-editable element
    var range = rangy.createRange();
    range.collapseAfter(nonEditable);

    if (selRange.compareBoundaryPoints(range.START_TO_END, range) == -1) {
        return;
    }

    // Check whether there is any text between the caret and the
    // non-editable element. If not, delete the element and move
    // the caret to where it had been
    range.setEnd(selRange.startContainer, selRange.startOffset);
    if (range.toString() === "") {
        selRange.collapseBefore(nonEditable);
        nonEditable.parentNode.removeChild(nonEditable);
        sel.setSingleRange(selRange);

        // Prevent the default browser behaviour
        return false;
    }
};

【讨论】:

  • 太棒了!非常感谢您提供如此彻底的答案。我稍微调整了一下——我没有使用 document.getElementById("nonEditable") 而是使用了 selRange.startContainer.previousSibling (因为我不知道我需要在退格键上删除哪个节点)。
  • 非常感谢蒂姆的出色回答。这对我今天非常有帮助。
【解决方案2】:

我制作了一个 jsfiddle,其中包含如何查看选择范围并使用 startContainer 的 previousSibling 属性来查找按钮的快速示例: jsfiddle

将光标放在aaa 上,它会显示按钮是prev 兄弟。把它放在 ccc 中,bbb 就会显示出来。

因此,您可以处理 div 的 keydown 事件,检查 key 是否为退格键 + previousSibling 是您的按钮,然后使用 jQuery 将其删除。

previousSibling 如果是文本节点则为 null,仅供参考。

【讨论】:

  • 非常酷。我想我可以将前一个兄弟与范围偏移结合使用作为解决方案。我会报告进展情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-11
  • 2020-11-27
  • 1970-01-01
  • 2019-12-12
  • 2020-11-17
  • 1970-01-01
相关资源
最近更新 更多