【问题标题】:Insert html when the caret was in a content editable div当插入符号位于内容可编辑的 div 中时插入 html
【发布时间】:2011-10-07 06:46:01
【问题描述】:

我想在内容可编辑的 div 中插入一些 html。

当编辑内容时,用户点击一个图标,弹出一个对话框,他在对话框中输入 url 和锚文本。这会导致可编辑的 div 失去焦点,并且链接被插入到 div 的开头,而不是插入符号所在的位置。我尝试了很多东西,但我被卡住了。

我的可编辑内容 div 的“rte” id

对话框中按钮的“link_add” id

$('#link_add').click(function (e)
{       
    $('#rte').focus();                  
    document.execCommand('insertHTML', false, 'html content test');         
    close_modal ();
    e.preventDefault();

});

我还尝试了set execcommand just for a div 的解决方案,使用:

function execCommandOnElement(el, commandName, value)

但这会清空 div 并粘贴新内容。

【问题讨论】:

  • 没有。如何以及如何在该位置插入内容?

标签: jquery html contenteditable


【解决方案1】:

我认为这是一个“内联”对话框(例如,很像 StackOverflow 的链接对话框),它移动焦点并因此移动选择。解决方案似乎是保存并恢复选择。调用 getSelection() 以获取对选择的引用并保存 anchorNodeanchorOffsetfocusNodefocusOffset 属性,然后使用 collapse(anchorNode, anchorOffset)extend(focusNode, focusOffset) 来恢复选择分区。 (如果你对这两个节点都不感兴趣,你可以collapse(focusNode, focusOffset)。)

【讨论】:

  • 谢谢尼尔。我需要在对话框中使用 2 个字段,而不仅仅是选择文本并输入一个 url。如果我不选择任何内容,您的解决方案是否仍然有效?
  • 如果未选择任何内容,则 anchorNode == focusNode 和 anchorOffset == focusOffset。
  • 这是一个很好的解决方案,除了 IE
  • 其实它在IE 9中也行不通,因为它没有实现Selection对象的extend()方法。
【解决方案2】:

您需要保存并恢复选择。如果在可编辑元素失去焦点时选择折叠(即只是一个插入符号),则 IE 会丢失它。请注意,IE

var saveSelection, restoreSelection;
if (window.getSelection) {
    // IE 9 and non-IE
    saveSelection = function() {
        var sel = window.getSelection(), ranges = [];
        if (sel.rangeCount) {
            for (var i = 0, len = sel.rangeCount; i < len; ++i) {
                ranges.push(sel.getRangeAt(i));
            }
        }
        return ranges;
    };

    restoreSelection = function(savedSelection) {
        var sel = window.getSelection();
        sel.removeAllRanges();
        for (var i = 0, len = savedSelection.length; i < len; ++i) {
            sel.addRange(savedSelection[i]);
        }
    };
} else if (document.selection && document.selection.createRange) {
    // IE <= 8
    saveSelection = function() {
        var sel = document.selection;
        return (sel.type != "None") ? sel.createRange() : null;
    };

    restoreSelection = function(savedSelection) {
        if (savedSelection) {
            savedSelection.select();
        }
    };
}

在打开对话框之前:

var savedSel = saveSelection();

关闭对话框后:

restoreSelection(savedSel);

或者,如果您要进行大量选择/范围操作,您可以使用我的 Rangy 库中的 selection save/restore module,但这对于仅此一种用途来说太过分了。

【讨论】:

  • 谢谢蒂姆。我更多地使用 Div 来插入元素而不是选择它们并修改它们(粗体等)
  • @Tim,您是否通过运行 execCommand insertHTML 对此进行了测试?
  • @Blowsie:我不确定我是否在撰写本文时对其进行了测试。我可以看到它很可能会破裂。如果它不起作用,那么我会删除它,虽然我不确定接受的答案会做得更好。
  • @Tim,找到问题的根源并实际解决它而不是删除它会很好,它的 execCommand insertHTML 肯定会破坏它。
  • @Blowsie:是的,这真的行不通。如何最好地保存和恢复选择实际上取决于您在做什么。对于您的示例,我建议使用基于字符索引的方法,例如 stackoverflow.com/a/5596688/96100(虽然这需要我的 Rangy 库,但可以简单地更改为不需要它。请参阅 jsFiddle:jsfiddle.net/Y8pJ7/8
【解决方案3】:

上面的建议可能无法正常工作,原因有两个: 首先,需要使用window.getSelection().getRangeAt(i).cloneRange(), 还有第二个, - 选择和范围是实时数据,并会随着用户相关操作自动刷新,例如新的选择和焦点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-24
    • 2011-04-27
    • 2020-07-24
    • 2014-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多