Javascript 在内容可编辑div中的光标处插入文本

Javascript 在内容可编辑div中的光标处插入文本,javascript,contenteditable,Javascript,Contenteditable,我有一个contenteditable div,需要在插入符号位置插入文本 通过document.selection.createRange().text=“banana” 在Firefox/Chrome中是否有类似的实现方法 (我知道存在一个解决方案,但它不能在contenteditable div中使用,而且看起来很笨拙) 谢谢大家! 以下函数将在插入符号位置插入文本并删除现有选择。它适用于所有主流桌面浏览器: function insertTextAtCaret(text) { v

我有一个contenteditable div,需要在插入符号位置插入文本

通过
document.selection.createRange().text=“banana”

在Firefox/Chrome中是否有类似的实现方法

(我知道存在一个解决方案,但它不能在contenteditable div中使用,而且看起来很笨拙)


谢谢大家!

以下函数将在插入符号位置插入文本并删除现有选择。它适用于所有主流桌面浏览器:

function insertTextAtCaret(text) {
    var sel, range;
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);
            range.deleteContents();
            range.insertNode( document.createTextNode(text) );
        }
    } else if (document.selection && document.selection.createRange) {
        document.selection.createRange().text = text;
    }
}
更新

根据注释,下面是一些用于保存和恢复选择的代码。在显示上下文菜单之前,应将
saveSelection
的返回值存储在变量中,然后将该变量传递到
restoreSelection
中,以便在隐藏上下文菜单后插入文本之前恢复选择

function saveSelection() {
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            return sel.getRangeAt(0);
        }
    } else if (document.selection && document.selection.createRange) {
        return document.selection.createRange();
    }
    return null;
}

function restoreSelection(range) {
    if (range) {
        if (window.getSelection) {
            sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
        } else if (document.selection && range.select) {
            range.select();
        }
    }
}

使用jquery只是一种更简单的方法:

复制div的全部内容

var oldhtml=$('#elementID').html()

var tobejoined='hii'

//具有新html的元素将是

$('#elementID').html(oldhtml+tobejoined)

简单

  • 使用
    window.getSelection()
    获取选择对象
  • 使用
    Selection.getRangeAt(0).insertNode()
    添加textnode
  • 如有必要,使用
    Selection.modify()
    将光标位置移动到添加的文本后面。(未标准化,但Firefox、Chrome和Safari支持此功能)


  • UPD:自2020年起,解决方案是(尽管它还可以)

    //
    //const editable=document.getElementById('myeditable')
    //可编辑。焦点()
    //document.execCommand('insertHTML',false,'Banana')
    document.execCommand('insertText',false,'banana')
    
    我用下一个代码在聊天信息中插入图标

    <div class="chat-msg-text" id="chat_message_text" contenteditable="true"></div>
    
    <script>
    var lastCaretPos = 0;
    var parentNode;
    var range;
    var selection;
    
    $(function(){
        $('#chat_message_text').focus();
    
        $('#chat_message_text').on('keyup mouseup',function (e){
            selection = window.getSelection();
            range = selection.getRangeAt(0);
            parentNode = range.commonAncestorContainer.parentNode;
        });
    })
    
    function insertTextAtCursor(text) { 
    
        if($(parentNode).parents().is('#chat_message_text') || $(parentNode).is('#chat_message_text') )
        {
            var span = document.createElement('span');              
            span.innerHTML=text;
    
            range.deleteContents();        
            range.insertNode(span);  
            //cursor at the last with this
            range.collapse(false);
            selection.removeAllRanges();
            selection.addRange(range);
    
        }
        else
        {
            msg_text = $("#chat_message_text").html()
            $("#chat_message_text").html(text+msg_text).focus()                 
        }
    }
    
    </script>
    
    
    var lastCaretPos=0;
    var父节点;
    var范围;
    var选择;
    $(函数(){
    $('chat#u message_text').focus();
    $('chat#message_text')。打开('keyup mouseup',函数(e){
    selection=window.getSelection();
    范围=选择。getRangeAt(0);
    parentNode=range.commonAncestorContainer.parentNode;
    });
    })
    函数insertTextAtCursor(文本){
    if($(parentNode).parents()是('#聊天室消息文本')|$(parentNode).is('#聊天室消息文本'))
    {
    var span=document.createElement('span');
    span.innerHTML=文本;
    range.deleteContents();
    range.insertNode(span);
    //光标位于最后一个位置
    范围。塌陷(假);
    selection.removeAllRanges();
    选择。添加范围(范围);
    }
    其他的
    {
    msg_text=$(“#聊天_消息_text”).html()
    $(“#聊天#消息_文本”).html(文本+消息_文本).focus()
    }
    }
    

    感谢您的帮助,我使用它作为在线代码编辑器的一部分,每当用户在对象名称后键入“.”时,会弹出一个上下文菜单,其中列出了它的方法(intellisense/code completion),当用户单击一个方法名称时,需要将文本粘贴在代码区div中的点后。但到目前为止,“方法名称”粘贴到上下文菜单中,而不是代码区域中。确定。在这种情况下,我建议在您将要显示关联菜单的位置存储一个表示所选内容的Range/TextRange的副本,然后在隐藏关联菜单后但插入文本之前从中还原所选内容。@mikel:不太可能:您只需使用第一个分支的精简版本<代码>函数insertTextAtCursor(text){var range,sel=rangy.getSelection();if(sel.rangeCount){range=sel.getRangeAt(0);range.insertNode(document.createTextNode(text));}}
    @zeel:我已经更新了你的小提琴,将光标移动到插入文本之后的位置:。在IE 9中似乎很好。@Fuxian:我希望如此,但我已经习惯了选择API,它对可编辑和不可编辑文本都是一样的。如果您对此感到担忧,那么可以在插入文本之前检查包含所选内容的元素是否可编辑。如果您需要,我可以提供相应的代码。如果您希望在光标处插入html,请参阅并不能解决最初的问题,它会在html内容后追加文本。关于
    execCommand
    :此功能已过时。尽管它在某些浏览器中仍然可以工作,但不鼓励使用它,因为它可以随时删除。尽量避免使用它。我真的希望当
    execCommand
    过时时,浏览器会考虑提出一个优雅的API来与可编辑内容交互。这并没有发生。这个解决方案比公认的答案有更好的表现,+1.1+表示“在用户键入时插入/替换某物”的最简单答案。如果我正确地读取了处的文档,就可以使用selection.collapseToEnd()而不使用for()循环。@Munneson:你试过了吗?仅当当前选择了某个对象时,才会执行此操作。未选择插入的节点,它将显示在选择的右侧。
    // <div contenteditable id="myeditable">
    // const editable = document.getElementById('myeditable')
    // editable.focus()
    // document.execCommand('insertHTML', false, '<b>B</b>anana')
    document.execCommand('insertText', false, 'banana')
    
    <div class="chat-msg-text" id="chat_message_text" contenteditable="true"></div>
    
    <script>
    var lastCaretPos = 0;
    var parentNode;
    var range;
    var selection;
    
    $(function(){
        $('#chat_message_text').focus();
    
        $('#chat_message_text').on('keyup mouseup',function (e){
            selection = window.getSelection();
            range = selection.getRangeAt(0);
            parentNode = range.commonAncestorContainer.parentNode;
        });
    })
    
    function insertTextAtCursor(text) { 
    
        if($(parentNode).parents().is('#chat_message_text') || $(parentNode).is('#chat_message_text') )
        {
            var span = document.createElement('span');              
            span.innerHTML=text;
    
            range.deleteContents();        
            range.insertNode(span);  
            //cursor at the last with this
            range.collapse(false);
            selection.removeAllRanges();
            selection.addRange(range);
    
        }
        else
        {
            msg_text = $("#chat_message_text").html()
            $("#chat_message_text").html(text+msg_text).focus()                 
        }
    }
    
    </script>