将插入符号位置设置为contentEditable元素内的空节点

时间:2010-10-31 12:51:32

标签: javascript text cross-browser contenteditable

我的任务是将文本插入符设置为显示在contentEditable div中的空span节点内。

以下内容在Firefox 3.6上没有任何问题:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <script type="text/javascript" src="js/jquery-1.4.3.min.js">
        </script>
        <style>
            #multiple {
                border: 1px solid #ccc;
                width: 800px;
                min-height: 20px;
                padding: 5px;
                outline: none;
            }
        </style>
        <script>
            $(document).ready(function(){

    var contentEditable = document.getElementById('multiple');
    var lastItem = contentEditable.getElementsByTagName('span').item(2);

                var selectElementText = function(el, win){
                    win = win || window;
                    var doc = win.document, sel, range;
                    if (win.getSelection && doc.createRange) {                    
                        range = doc.createRange();
                        range.selectNodeContents(el);
                        range.collapse(false);
                        sel = win.getSelection();
                        sel.removeAllRanges();
                        sel.addRange(range);
                    }
                    else 
                        if (doc.body.createTextRange) {
                            range = doc.body.createTextRange();
                            range.moveToElementText(el);
                            range.select();
                        }
                }

                contentEditable.focus();
                selectElementText(lastItem);
            });
        </script>
        <title>Range Selection Tasks (Make Me Want to Cry)</title>
    </head>
    <body>
        <div id="multiple" contentEditable="true">
            <span style="color:red">First</span><span style="color:green">Second</span><span style="color:blue"></span>
        </div>
    </body>
</html>

...但是在Webkit和IE上,焦点设置为倒数第二个范围。不知道为什么。如果我在最后一个跨度内放置一个空格,那么它可以工作,但我得到一个单字符范围选择。

话虽如此,如果插入符号一开始就在最后一个节点中有空格是可以接受的。

对此的任何帮助将不胜感激。提前谢谢。

6 个答案:

答案 0 :(得分:11)

将元素的innerHTML设置为零宽度字符:

('element').innerHTML = '&#200B';

现在carret可以去那里。

答案 1 :(得分:5)

IE的选择/范围模型基于文本内容的索引,忽略元素边界。我相信可能无法将输入焦点设置在没有文本的内联元素中。当然,在您的示例中,我无法通过单击或箭头键在最后一个元素内设置焦点。

如果将每个范围设置为display: block,它几​​乎可以工作,尽管仍然存在一些非常奇怪的行为,这取决于父级中是否存在空白。黑客将显示内容与浮点,内联块和绝对位置等技巧内联,使IE将每个元素视为一个单独的编辑框。相对定位的块元素彼此相邻,但这可能是不切实际的。

如果它让你感觉更好,IE9最终修复了这种不愉快并采用标准范围模型。 (万岁!)

  

如果插入符号一开始就在最后一个节点中有空格是可以接受的。

我可能会这样做,然后,除非IE选择专家能想到更好的东西。 (打电话给蒂姆!)

答案 2 :(得分:2)

我找到了一个Webkit的解决方法,不知道是否有人之前发现了这个,而不是以编程方式附加零宽度空间,你可以在元素的后psuedo-selector中使用css3内容属性做同样的事情你想把插入符号放入。这样做的好处是多余的字符不会出现在DOM中,用户无法在它之间导航插入符号。所以基本上它不需要清理。

为了使其适用于内容可编辑元素的任何子元素,它将是这样的:

#mycontenteditableelement *:after {
    content: '\200B';
}

我没有完全检查,但我怀疑这是一个完整的解决方法。

答案 3 :(得分:1)

聚会晚了一点,但是我使用了Unicode零宽度不间断空格(&#65279;)。然后,在用户输入发生后调用的事件上,删除零宽度无间断空格。

我在使用Unicode空间问题时遇到了很多问题,大多数是糟糕的UX。这样可以防止用户知道存在问题。

答案 4 :(得分:0)

将最小高度和最小宽度应用于内嵌块内部的元素可以某些好,但影响会产生意想不到的副作用:

#multiple * {
    min-height: 1em;
}
span, b, strong, i, em, a, etc {
    display: inline-block;
    min-width: 1em;
    background-color: hsla(0, 50%, 50%, .5); /* this is only a visual aid; discard @ will */
    vertical-align: middle; /* so elements w/ inline-block align w/ text correctly */ 
}

你会发现仍然存在问题,但是如果你愿意为一小部分其他人牺牲一些问题,这可能会有一些好处。

答案 5 :(得分:0)

对我来说,设置contenteditable div的内容为<br>。我尝试将其设置为nbsp;但在开始编辑之前在div中创建了额外的字符空间。

希望这有帮助。