【发布时间】:2015-12-18 02:58:02
【问题描述】:
我有一个带有 contenteditable 属性的 div。用户需要能够在光标所在的位置键入和插入多个选择菜单。我设法获得了光标位置并插入了第一个选择菜单,但它只适用于第一个文本节点。
这就是我获得光标位置的方式:
function getCaretCharacterOffsetWithin(element) {
var caretOffset = 0;
var doc = element.ownerDocument || element.document;
var win = doc.defaultView || doc.parentWindow;
var sel;
if (typeof win.getSelection != "undefined") {
sel = win.getSelection();
if (sel.rangeCount > 0) {
var range = win.getSelection().getRangeAt(0);
var preCaretRange = range.cloneRange();
preCaretRange.selectNodeContents(element);
preCaretRange.setEnd(range.endContainer, range.endOffset);
caretOffset = preCaretRange.toString().length;
}
} else if ( (sel = doc.selection) && sel.type != "Control") {
var textRange = sel.createRange();
var preCaretTextRange = doc.body.createTextRange();
preCaretTextRange.moveToElementText(element);
preCaretTextRange.setEndPoint("EndToEnd", textRange);
caretOffset = preCaretTextRange.text.length;
}
return caretOffset;
}
然后我在每次用户输入或点击时更新它。
function updatePos() {
var el = document.getElementById("msg");
pos = getCaretCharacterOffsetWithin(el);
}
document.body.onkeyup = updatePos;
document.body.onmouseup = updatePos;
下面是我如何处理添加选择的按钮。我不确定如何在文本节点之后插入元素,所以我插入了一个 br 标记并稍后将其删除。必须有更清洁的方法,对吧?
$('#btn').click(function(){
var selectList = document.createElement('select');
var msg = $('#msg');
$(msg).html(function(){
var first = $(msg).html().substring(0, pos);
var last = $(msg).html().substring(pos);
return first + '<br>' + last;
});
$(msg).contents().filter('br').after(selectList);
$(msg).contents().filter('br').remove();
$(msg).focus();
})
我想问题是我使用子字符串来拆分文本并能够在其中插入选择,并且一旦有另一个选择标签,子字符串就无法越过第一个文本节点。所以也许我应该用不同的方法重做整个事情,但我完全被困住了。
这是 jsfiddle:https://jsfiddle.net/8a63sosr/
谢谢!
【问题讨论】:
标签: javascript jquery