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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2920150/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 02:29:39  来源:igfitidea点击:

Insert text at cursor in a content editable div

javascriptcontenteditable

提问by user314362

I have a contenteditable div where I need to insert text at the caret position,

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

This can be easily done in IE by document.selection.createRange().text = "banana"

这可以通过以下方式在 IE 中轻松完成 document.selection.createRange().text = "banana"

Is there a similar way of implementing this in Firefox/Chrome?

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

(I know a solution exists here, but it can't be used in contenteditable div, and looks clumsy)

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

Thank you!

谢谢!

回答by Tim Down

The following function will insert text at the caret position and delete the existing selection. It works in all the mainstream desktop browsers:

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

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;
    }
}

UPDATE

更新

Based on comment, here's some code for saving and restoring the selection. Before displaying your context menu, you should store the return value of saveSelectionin a variable and then pass that variable into restoreSelectionto restore the selection after hiding the context menu and before inserting text.

根据评论,这里有一些用于保存和恢复选择的代码。在显示上下文菜单之前,您应该将 的返回值存储saveSelection在一个变量中,然后将该变量传递restoreSelection给in 以在隐藏上下文菜单后和插入文本之前恢复选择。

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();
        }
    }
}

回答by Martin Wantke

  1. Get a Selection Object with window.getSelection().
  2. Use Selection.getRangeAt(0).insertNode()to add a textnode.
  3. If necessary, move the cursor position behind the added text with Selection.modify(). (Not standardized, but this feature is supported in Firefox, Chrome and Safari)

    function insertTextAtCursor(text)
    {
        let selection = window.getSelection();
        let range = selection.getRangeAt(0);
        range.deleteContents();
        let node = document.createTextNode(text);
        range.insertNode(node);
    
        for(let position = 0; position != text.length; position++)
        {
            selection.modify("move", "right", "character");
        };
    }
    
  1. 使用 获取选择对象window.getSelection()
  2. 使用Selection.getRangeAt(0).insertNode()添加textnode。
  3. 如有必要,使用 将光标位置移动到添加的文本后面Selection.modify()。(未标准化,但 Firefox、Chrome 和 Safari 支持此功能)

    function insertTextAtCursor(text)
    {
        let selection = window.getSelection();
        let range = selection.getRangeAt(0);
        range.deleteContents();
        let node = document.createTextNode(text);
        range.insertNode(node);
    
        for(let position = 0; position != text.length; position++)
        {
            selection.modify("move", "right", "character");
        };
    }
    

回答by alex_1948511

UPD: since ~2020 solution is obsoleted(despite it can workyet)

UPD:由于 ~2020 解决方案已过时(尽管它还可以工作

// <div contenteditable id="myeditable">
// const editable = document.getElementById('myeditable')
// editable.focus()
// document.execCommand('insertHTML', false, '<b>B</b>anana')
document.execCommand('insertText', false, 'banana')

回答by Sergey Kharchishin

I have used next code to insert icons in chat msg

我已经使用下一个代码在聊天消息中插入图标

<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>

enter image description here

在此处输入图片说明

回答by Alireza Mn

just an easier method with jquery:

只是一个更简单的jquery方法:

copy the entire content of the div

复制div的全部内容

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

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

var tobejoined='<span>hii</span>';

var tobejoined='<span>hii</span>';

//element with new html would be

//element with new html would be

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

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

simple!

简单的!