简体   繁体   English

处理内容可编辑div中的插入位置

[英]Handle caret position in content editable div

I have this content editable div in HTML 我在HTML中有这个内容可编辑的div

<div contenteditable="true" id="TextOnlyPage"></div>

And heres my jquery code 继承我的jquery代码

var rxp = new RegExp("(([0-9]+\.?[0-9]+)|([0-9]+))", "gm");
$('#TextOnlyPage').keyup(function(e){
    if(e.keyCode == 13){
        e.preventDefault();
        $('#TextOnlyPage').children().each(function() {
            if ( $(this).is("div") ) {
                $(this).contents().unwrap();
            }});
        $('#TextOnlyPage').append("<br/>");
    }
        $('#TextOnlyPage').children().contents().unwrap();
        var $this = $(this);
        var content = $this.html();
        $this.html(content.replace(rxp, "<span class='highlight'>$1</span>"));});

Problem is the caret position, because when it apply span tags around numbers in string.replace method then cursor goes to the start of the content editable div . 问题是插入位置,因为当它在string.replace方法中的数字周围应用span标签时,光标将转到内容可编辑div的开头。 Also it can't goes to next line while I press enter key. 当我按下回车键时,它也不能进入下一行。

I know I can handle it through range and selection objects, but can't find a useful resource to understand how these objects works. 我知道我可以通过rangeselection对象来处理它,但找不到有用的资源来理解这些对象的工作原理。

Kindly either provide me solution for this problem and it will be better if the solution in angularjs, or provide me a resource where I can understand range and selection objects with working examples. 请为我提供这个问题的解决方案,如果是angularjs中的解决方案会更好,或者为我提供一个资源,我可以通过工作示例了解范围和选择对象。

I faced the same issue as you did a while ago, to undertand how range and selection works I recommend you to take a look at MDN docs Selection and Range 我遇到了你刚才所面临的同样的问题,为了确定rangeselection是如何工作的,我建议你去看看MDN docs Selection and Range

One reliable way of detecting change in a contentEditable div is the event input . 检测contentEditable div中的更改的一种可靠方法是事件input One issue I found when listenning for keyUp and preventing the default behavior for certain keyCode is that they are tons of them and it's very hard to cover all use cases. 我在听取keyUp并阻止某些keyCode的默认行为时发现的一个问题是它们很多,并且很难涵盖所有用例。

What I prefer to do is to let the normal event being processed, save the caret position, get the text value and replace the parts that needs to be highlighted and then set the caret position back. 我更喜欢做的是让正常事件被处理,保存插入位置,获取文本值并替换需要突出显示的部分,然后设置插入位置。

Here is a simple example 这是一个简单的例子

var contentEditable = document.querySelector('div[contenteditable]');
contentEditable.addEventListener('input', onInput);

var onInput = function(e) {

    // this function will be called after the current call-stack
    // is finished, at that time the user input will be inserted
    // in the content editable
    setTimeout(function() {

        // save the caret position

        var text = contentEditable.innerText;
        // perform all your replacement on `text`
        contentEditable.innerHTML = text;

        // set the caret position back
    }, 0);
}

I also wrote two handy method getCaretOffsetWithin and setCaretPositionWithin to help manipulate the caret when you want to perform some DOM manipulation and re-position the caret at its initial value after the processing. 我还写了两个方便的方法getCaretOffsetWithinsetCaretPositionWithin来帮助操作插入符号,当你想要执行一些DOM操作并在处理后将插入符重新定位到它的初始值。

You can check them on this gist contenteditable-utils.js 你可以在这个要点contenteditable-utils.js上查看它们

Here are some resources from MDN: Selection and Range . 以下是来自MDN的一些资源: 选择范围

I've created this JSFiddle to demonstrate re-positioning the caret . 我创建了这个JSFiddle来演示重新定位插入符号

It doesn't work for all cases (eg on enter, selecting a range with shift + arrow ...) but it should already give you some ideas. 它并不适用于所有情况(例如,在输入时,选择带有shift +箭头的范围......)但它应该已经给你一些想法。

Here's an example from MDN about creating selections: 以下是MDN关于创建选择的示例:

/* Select all STRONG elements in an HTML document */

var strongs = document.getElementsByTagName("strong");
var s = window.getSelection();

if(s.rangeCount > 0) s.removeAllRanges();

for(var i = 0; i < strongs.length; i++) {
    var range = document.createRange();
    range.selectNode(strongs[i]);
    s.addRange(range);
}

As a sidenote, working with contentEditable will bring up more troubles in the future, I suggest doing your best to find alternatives to it. 作为旁注,使用contentEditable会在未来带来更多麻烦,我建议尽力找到替代品。 Also, be sure to notice the limited browser support warnings in the links I provided. 另外,请务必注意我提供的链接中有限的浏览器支持警告。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM