javascript 将插入符号位置设置为 contentEditable 元素内的空节点
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4063144/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Setting the caret position to an empty node inside a contentEditable element
提问by Mike
My task is to set a text caret to appear inside an empty span node within a contentEditablediv.
我的任务是将文本插入符号设置为出现在contentEditablediv内的空跨度节点内。
The following gives me no problems on Firefox 3.6:
以下在 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>
... but on Webkit and IE, the focus is set to the penultimatespan. No idea why. It works if I put a space inside the last span, but then I get a one-character range selection.
...但在 Webkit 和 IE 上,焦点设置为倒数第二个跨度。不知道为什么。如果我在最后一个跨度内放置一个空格,它会起作用,但随后我会得到一个字符范围选择。
Having said that, it's acceptable to have whitespace in the last node if the caret is at the very start.
话虽如此,如果插入符号在最开始,则在最后一个节点中有空格是可以接受的。
Any help with this would be greatly appreciated. Thank you in advance.
对此的任何帮助将不胜感激。先感谢您。
采纳答案by bobince
IE's selection/range model is based around indexes into text content, disregarding element boundaries. I believe it may be impossible to set the input focus inside an inline element with no text in it. Certainly with your example I cannot set focus inside the last element by clicking or arrow keys.
IE 的选择/范围模型基于文本内容的索引,不考虑元素边界。我相信在没有文本的内联元素中设置输入焦点可能是不可能的。当然,对于您的示例,我无法通过单击或箭头键在最后一个元素内设置焦点。
It almost works if you set each span to display: block, though there's still some highly strange behaviour, dependent on the existence of whitespace in the parent. Hacking the display to look inline with tricks like float, inline-block and absolute position make IE treat each element as a separate editing box. Relative-positioned block elements next to each other work, but that's probably impractical.
如果您将每个跨度设置为display: block,它几乎可以工作,尽管仍然存在一些非常奇怪的行为,这取决于父项中空格的存在。使用浮动、内联块和绝对位置等技巧使显示看起来内联,使 IE 将每个元素视为一个单独的编辑框。彼此相邻的相对定位块元素可以工作,但这可能不切实际。
If it makes you feel any better, IE9 finally fixes this unpleasantness and adopts the standard range model. (Hooray!)
如果它让您感觉更好,IE9 终于修复了这个不愉快,并采用了标准范围模型。(万岁!)
it's acceptable to have whitespace in the last node if the caret is at the very start.
如果插入符号在最开始,则在最后一个节点中有空格是可以接受的。
I'd probably do that, then, unless an IE selection expert can think of anything better. (Calling Tim Down!)
那么我可能会这样做,除非 IE 选择专家能想到更好的方法。(打电话给蒂姆!)
回答by shay levi
Set the element's innerHTMLto a zero-width character:
将元素设置innerHTML为零宽度字符:
('element').innerHTML = 'ÈB';
Now the carret can go there.
现在carret可以去那里了。
回答by bwindels
I found a workaround for Webkit, don't know if anybody found this before but instead of programmatically appending a zero-width space, you can do the same thing with the css3 content property in the after psuedo-selector of the elements you want to put the caret in. This has the advantage that the extra characters don't show up in the DOM and the user can't navigate the caret between it. So basically it doesn't need cleaning up.
我找到了 Webkit 的解决方法,不知道之前是否有人发现过这个方法,但您可以在要添加的元素的伪选择器之后的 css3 内容属性中使用 css3 内容属性执行相同的操作,而不是以编程方式添加零宽度空间将插入符号放入。这样做的优点是额外的字符不会出现在 DOM 中,并且用户无法在它之间导航插入符号。所以基本上不需要清理。
For this to work for any child element of your content editable element it would be something like this:
为了使其适用于您的内容可编辑元素的任何子元素,它应该是这样的:
#mycontenteditableelement *:after {
content: '0B';
}
I didn't check completely, but I suspect this is a full workaround.
我没有完全检查,但我怀疑这是一个完整的解决方法。
回答by arxpoetica
Applying a minimum height and minimum width to elements inside contenteditable with inline-block can do somegood, though the impact has unintended side effects:
使用 inline-block 对 contenteditable 中的元素应用最小高度和最小宽度可以做一些好事,尽管这种影响会产生意想不到的副作用:
#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 */
}
You'll find there are still issues, but if you're willing to sacrifice some problems for a smaller set of others, this can so some good.
你会发现仍然存在问题,但如果你愿意为一小部分其他问题牺牲一些问题,这可能会很好。
回答by jsbisht
For me setting it content of contenteditable div to <br>works. I tried setting it to nbsp;but that creates extra character space in the div before i start editing.
对我来说,将 contenteditable div 的内容设置为<br>有效。我尝试将其设置为,nbsp;但这会在我开始编辑之前在 div 中创建额外的字符空间。
Hope this helps.
希望这可以帮助。

