首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在可编辑元素(div)中设置插入符号(光标)的位置?

如何在可编辑元素(div)中设置插入符号(光标)的位置?
EN

Stack Overflow用户
提问于 2011-06-06 15:50:33
回答 11查看 195.6K关注 0票数 245

我有一个简单的HTML示例:

代码语言:javascript
复制
<div id="editable" contenteditable="true">
  text text text<br>
  text text text<br>
  text text text<br>
</div>
<button id="button">focus</button>

我想要简单的事情-当我点击按钮时,我想把插入符号(光标)放在可编辑div中的特定位置。在网上搜索,我有这个JS附加到按钮点击,但它不工作(FF,Chrome):

代码语言:javascript
复制
var range = document.createRange();
var myDiv = document.getElementById("editable");
range.setStart(myDiv, 5);
range.setEnd(myDiv, 5);

可以像这样手动设置插入符号的位置吗?

EN

回答 11

Stack Overflow用户

回答已采纳

发布于 2011-06-06 16:33:00

在大多数浏览器中,您需要RangeSelection对象。您可以将每个选择边界指定为节点和该节点内的偏移。例如,要将插入符号设置为第二行文本的第五个字符,请执行以下操作:

代码语言:javascript
复制
function setCaret() {
    var el = document.getElementById("editable")
    var range = document.createRange()
    var sel = window.getSelection()
    
    range.setStart(el.childNodes[2], 5)
    range.collapse(true)
    
    sel.removeAllRanges()
    sel.addRange(range)
}
代码语言:javascript
复制
<div id="editable" contenteditable="true">
  text text text<br>text text text<br>text text text<br>
</div>

<button id="button" onclick="setCaret()">focus</button>

IE <9的工作方式完全不同。如果你需要支持这些浏览器,你需要不同的代码。

jsFiddle示例:http://jsfiddle.net/timdown/vXnCM/

票数 323
EN

Stack Overflow用户

发布于 2020-07-03 00:26:41

我重构了@Liam的答案。我把它放在一个带有静态方法的类中,我让它的函数接收一个元素而不是#id,并做了一些其他的小调整。

此代码特别适用于修复您可能使用<div contenteditable="true">创建的富文本框中的光标。在达到下面的代码之前,我被困在这里好几天了。

编辑:他的答案和这个答案都有一个错误,涉及到按enter键。由于enter不算字符,因此在按enter后光标位置会变得混乱。如果我能够修复代码,我会更新我的答案。

edit2:省去了很多麻烦,并确保你的<div contenteditable=true>display: inline-block。这修复了一些与Chrome在按enter键时使用<div>而不是<br>相关的错误。

如何使用

代码语言:javascript
复制
let richText = document.getElementById('rich-text');
let offset = Cursor.getCurrentCursorPosition(richText);
// insert code here that does stuff to the innerHTML, such as adding/removing <span> tags
Cursor.setCurrentCursorPosition(offset, richText);
richText.focus();

代码

代码语言:javascript
复制
// Credit to Liam (Stack Overflow)
// https://stackoverflow.com/a/41034697/3480193
class Cursor {
    static getCurrentCursorPosition(parentElement) {
        var selection = window.getSelection(),
            charCount = -1,
            node;
        
        if (selection.focusNode) {
            if (Cursor._isChildOf(selection.focusNode, parentElement)) {
                node = selection.focusNode; 
                charCount = selection.focusOffset;
                
                while (node) {
                    if (node === parentElement) {
                        break;
                    }

                    if (node.previousSibling) {
                        node = node.previousSibling;
                        charCount += node.textContent.length;
                    } else {
                        node = node.parentNode;
                        if (node === null) {
                            break;
                        }
                    }
                }
            }
        }
        
        return charCount;
    }
    
    static setCurrentCursorPosition(chars, element) {
        if (chars >= 0) {
            var selection = window.getSelection();
            
            let range = Cursor._createRange(element, { count: chars });

            if (range) {
                range.collapse(false);
                selection.removeAllRanges();
                selection.addRange(range);
            }
        }
    }
    
    static _createRange(node, chars, range) {
        if (!range) {
            range = document.createRange()
            range.selectNode(node);
            range.setStart(node, 0);
        }

        if (chars.count === 0) {
            range.setEnd(node, chars.count);
        } else if (node && chars.count >0) {
            if (node.nodeType === Node.TEXT_NODE) {
                if (node.textContent.length < chars.count) {
                    chars.count -= node.textContent.length;
                } else {
                    range.setEnd(node, chars.count);
                    chars.count = 0;
                }
            } else {
                for (var lp = 0; lp < node.childNodes.length; lp++) {
                    range = Cursor._createRange(node.childNodes[lp], chars, range);

                    if (chars.count === 0) {
                    break;
                    }
                }
            }
        } 

        return range;
    }
    
    static _isChildOf(node, parentElement) {
        while (node !== null) {
            if (node === parentElement) {
                return true;
            }
            node = node.parentNode;
        }

        return false;
    }
}
票数 10
EN

Stack Overflow用户

发布于 2018-10-09 15:52:55

我正在写一个语法高亮笔(和基本的代码编辑器),我需要知道如何自动键入单引号字符并将插入符号移回(就像现在的许多代码编辑器一样)。

这是我的解决方案的一小段,感谢这个帖子、MDN文档和许多moz控制台观看的帮助。

代码语言:javascript
复制
//onKeyPress event

if (evt.key === "\"") {
    let sel = window.getSelection();
    let offset = sel.focusOffset;
    let focus = sel.focusNode;

    focus.textContent += "\""; //setting div's innerText directly creates new
    //nodes, which invalidate our selections, so we modify the focusNode directly

    let range = document.createRange();
    range.selectNode(focus);
    range.setStart(focus, offset);

    range.collapse(true);
    sel.removeAllRanges();
    sel.addRange(range);
}

//end onKeyPress event

这是在一个可编辑的div元素中

我把这个留在这里作为感谢,因为我意识到已经有了一个公认的答案。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6249095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档