关于javascript:在内容可编辑div中的光标处插入文本

Insert text at cursor in a content editable div

我有一个内容可编辑的div,需要在插入符号的位置插入文本,

这可以通过 document.selection.createRange().text ="banana"

在IE中轻松完成

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

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

谢谢!


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

1
2
3
4
5
6
7
8
9
10
11
12
13
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以恢复选择。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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();
        }
    }
}


UPD:由于?2020解决方案已过时(尽管它仍然可以工作)

1
2
3
4
5
//
// const editable = document.getElementById('myeditable')
// editable.focus()
// document.execCommand('insertHTML', false, 'Banana')
document.execCommand('insertText', false, 'banana')


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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");
        };
    }

  • 我已使用下一个代码在聊天消息msg

    中插入图标

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    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()                
        }
    }

    enter image description here


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

    复制div的全部内容

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

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

    //element with new html would be

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

    简单!