簡體   English   中英

在內容可編輯的 div 中的光標處插入文本

[英]Insert text at cursor in a content editable div

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

這可以通過document.selection.createRange().text = "banana"在 IE 中輕松完成

在 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();
        }
    }
}
  1. 使用window.getSelection()獲取選擇對象。
  2. 使用Selection.getRangeAt(0).insertNode()添加一個文本節點。
  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"); }; }

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

我已經使用下一個代碼在聊天消息中插入圖標

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

在此處輸入圖像描述

可以使用以下代碼處理粘貼純文本。

const editorEle = document.getElementById('editor');

// Handle the `paste` event
editorEle.addEventListener('paste', function (e) {
    // Prevent the default action
    e.preventDefault();

    // Get the copied text from the clipboard
    const text = e.clipboardData
        ? (e.originalEvent || e).clipboardData.getData('text/plain')
        : // For IE
        window.clipboardData
        ? window.clipboardData.getData('Text')
        : '';

    if (document.queryCommandSupported('insertText')) {
        document.execCommand('insertText', false, text);
    } else {
        // Insert text at the current position of caret
        const range = document.getSelection().getRangeAt(0);
        range.deleteContents();

        const textNode = document.createTextNode(text);
        range.insertNode(textNode);
        range.selectNodeContents(textNode);
        range.collapse(false);

        const selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);
    }
});

如果您正在使用富編輯器(如 DraftJs)但無法訪問他們的 API(例如從擴展修改),這些是我找到的解決方案:

  • 調度beforeinput事件,這是推薦的方式,大多數編輯器都支持
target.dispatchEvent(new InputEvent("beforeinput", {
    inputType: "insertText",
    data: text,
    bubbles: true,
    cancelable: true
}))
  • 調度paste事件
const data = new DataTransfer();
data.setData(
    'text/plain',
    text
);
target.dispatchEvent(new ClipboardEvent("paste", {
    dataType: "text/plain",
    data: text,
    bubbles: true,
    clipboardData: data,
    cancelable: true
}));

最后一個使用 2 種不同的方法:


如果要替換所有現有文本,則必須先選擇它

function selectTargetText(target) {
    const selection = window.getSelection();
    const range = document.createRange();
    range.selectNodeContents(target);
    selection.removeAllRanges();
    selection.addRange(range);
}

selectTargetText(target)

// wait for selection before dispatching the `beforeinput` event
document.addEventListener("selectionchange",()=>{
    target.dispatchEvent(new InputEvent("beforeinput", {
        inputType: "insertText",
        data: text,
        bubbles: true,
        cancelable: true
    }))
},{once: true})

只是使用 jquery 的一種更簡單的方法:

復制 div 的全部內容

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

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

//element with new html would be

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

簡單的!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM