在有孩子的'contenteditable'div中设置Caret Position [英] Set Caret Position in 'contenteditable' div that has children

查看:114
本文介绍了在有孩子的'contenteditable'div中设置Caret Position的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的HTML结构:

 < div contenteditable =true>这是一些简单的,无聊的内容。< / div> 

我也有这个功能,允许我将插入位置设置为div中我想要的任何位置:

  //将插入符号移动到DOM元素中的特定点
函数SetCaretPosition(object,pos)
{
//获取关键数据
var el = object.get(0); //从jQuery对象中剥离内部对象
var range = document.createRange();
var sel = window.getSelection();

//设置DOM元素的范围
range.setStart(el.childNodes [0],pos);
range.collapse(true);

//设置选择点
sel.removeAllRanges();
sel.addRange(range);
}

此代码完全正常,直到我开始添加子标记(span,b,i,u,strike,sup,sub)到div例如

 < div contenteditable =true> 
这是一些< span class =fancy> plain< / span>,无聊的内容。
< / div>

当这些子标签最终带有自己的子标签时,事情会变得更复杂,例如

 < div contenteditable =true> 
这是一些< span class =fancy>< i> plain< / i>< / span> ;,无聊的内容。
< / div>

基本上,会发生什么,是 setStart 当我尝试 SetCaretPosition 到高于子标记开头的索引时,抛出 IndexSizeError setStart 只有在到达第一个子标签时才会有效。



我需要的是 SetCaretPosition 函数用于处理未知数量的这些子标记(以及可能是未知数量的嵌套子标记),以便设置位置的工作方式与没有标记时相同。 / p>

所以对于这两个:

 < div contenteditable =true >这是一些简单,无聊的内容。< / div> 

这个:

 < div contenteditable =true> 
这是< u>一些< / u> < span class =fancy>< i> plain< / i>< / span> ;,无聊的内容。
< / div>

SetCaretPosition(div,20); 将将插入符号放在b之前的无聊中。



我需要的代码是什么?非常感谢!

解决方案

所以,我遇到了同样的问题,并决定快速编写自己的例程,它遍历了所有的子节点递归并设置位置。
注意这是如何将DOM节点作为参数,而不是像原始帖子那样的jquery对象

  //移动插入DOM元素中的特定点
函数SetCaretPosition(el,pos){

//遍历所有子节点
for(var节点el.childNodes){
if(node.nodeType == 3){//我们有一个文本节点
if(node.length> = pos){
//最后添加我们的范围
var range = document.createRange(),
sel = window.getSelection();
range.setStart(node,pos);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
返回-1; //我们完成了
} else {
pos - = node.length;
}
} else {
pos = SetCaretPosition(node,pos);
if(pos == -1){
return -1; //无需完成for循环
}
}
}
返回pos; //因为递归而需要
}

我希望这对你有所帮助! / p>

I have an HTML structure like this:

<div contenteditable="true">This is some plain, boring content.</div>

I also have this function that allows me to set the caret position to anywhere I want within the div:

// Move caret to a specific point in a DOM element
function SetCaretPosition(object, pos)
{
    // Get key data
    var el = object.get(0); // Strip inner object from jQuery object
    var range = document.createRange();
    var sel = window.getSelection();

    // Set the range of the DOM element
    range.setStart(el.childNodes[0], pos);
    range.collapse(true);

    // Set the selection point
    sel.removeAllRanges();
    sel.addRange(range);
}

This code works completely fine until I start adding child tags (span, b, i, u, strike, sup, sub) to the div e.g.

<div contenteditable="true">
    This is some <span class="fancy">plain</span>, boring content.
</div>

Things get more complicated when these child tags end up with child tags of their own e.g.

<div contenteditable="true">
    This is some <span class="fancy"><i>plain</i></span>, boring content.
</div>

Essentially, what happens, is that setStart throws an IndexSizeError when I try to SetCaretPosition to an index higher than the start of a child tag. setStart only works until it reaches the first child tag.

What I need, is for the SetCaretPosition function to handle an unknown number of these child tags (and potentially an unknown number of nested child tags) so that setting the position works in the same way it would if there were no tags.

So for both this:

<div contenteditable="true">This is some plain, boring content.</div>

and this:

<div contenteditable="true">
    This is <u>some</u> <span class="fancy"><i>plain</i></span>, boring content.
</div>

SetCaretPosition(div, 20); would place the caret before the 'b' in 'boring'.

What is the code I need? Many thanks!

解决方案

So, I was experiencing the same issue and decided to write my own routine quickly, it walks through all the child nodes recursively and set the position. Note how this takes a DOM node as argument, not a jquery object as your original post does

// Move caret to a specific point in a DOM element
function SetCaretPosition(el, pos){

    // Loop through all child nodes
    for(var node of el.childNodes){
        if(node.nodeType == 3){ // we have a text node
            if(node.length >= pos){
                // finally add our range
                var range = document.createRange(),
                    sel = window.getSelection();
                range.setStart(node,pos);
                range.collapse(true);
                sel.removeAllRanges();
                sel.addRange(range);
                return -1; // we are done
            }else{
                pos -= node.length;
            }
        }else{
            pos = SetCaretPosition(node,pos);
            if(pos == -1){
                return -1; // no need to finish the for loop
            }
        }
    }
    return pos; // needed because of recursion stuff
}

I hope this'll help you!

这篇关于在有孩子的'contenteditable'div中设置Caret Position的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆