Javascript 需要按两次Enter键才能添加范围
我刚刚学习了如何使用选择和范围,并建立了一个更好的方法,在contenteditable divs中按enter键。按下enter键时,将调用event.preventDefault,程序将在contenteditable通常会添加div的位置插入。但是,我需要按两次enter键才能发生任何事情。另一个奇怪的事实是:当那一行没有文本时,这种情况就不会发生。我对选择和范围还不熟悉,我相信这是新手犯的错误。代码如下:Javascript 需要按两次Enter键才能添加范围,javascript,html,range,selection,contenteditable,Javascript,Html,Range,Selection,Contenteditable,我刚刚学习了如何使用选择和范围,并建立了一个更好的方法,在contenteditable divs中按enter键。按下enter键时,将调用event.preventDefault,程序将在contenteditable通常会添加div的位置插入。但是,我需要按两次enter键才能发生任何事情。另一个奇怪的事实是:当那一行没有文本时,这种情况就不会发生。我对选择和范围还不熟悉,我相信这是新手犯的错误。代码如下: function keyExamine(e) { var doc = d
function keyExamine(e) {
var doc = document.getElementById('cmd');
e.keyCode = e.keyCode || e.which;
if (e.keyCode == 13) {
if (e.ctrlKey) {
alert(doc.innerHTML);
} else {
e.preventDefault();
initiateCommand(doc.innerHTML);
var dv = doc.ownerDocument.defaultView;
var sel = dv.getSelection();
var range = sel.getRangeAt(0);
var enterNode = document.createElement('br');
range.insertNode(enterNode);
range.setStartAfter(enterNode);
range.setEndAfter(enterNode);
sel.removeAllRanges();
sel.addRange(range);
document.getElementById('maxback').innerText = doc.innerText.replace(/(\r\n\t|\n|\r\t)/gm,"").length;
}
} else if (e.keyCode == 38) {
e.preventDefault();
} else if (e.keyCode == 37 || e.keyCode == 8 || e.keyCode == 46) {
var ml = Number(document.getElementById('maxback').innerText);
if (getCaretPosition(doc) <= ml) {
e.preventDefault();
}
} else {
var ml = Number(document.getElementById('maxback').innerText);
if (getCaretPosition(doc) < ml) {
e.preventDefault();
}
}
}
function getCaretPosition(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;
}
我有以下HTML:
<p id='maxback' style='display: none'>0</p>
<p contenteditable="true" onkeydown="keyExamine(event)" id="cmd"></p>
有一种方法可以解决所有问题,同时避免许多陷阱。您可以插入包含换行符的文本节点,然后将所有选择折叠到其末尾 这种方法与平台和浏览器无关,理论上可以追溯到IE9 主要的缺点是什么?它依赖于未定义的行为,故意将折叠索引设置为超出节点长度。所有浏览器都会在插入节点后正确设置选择,即使是在第一次按Enter键时也是如此 函数handleKeyevent{ const editor=document.getElementById'cmd' 如果event.key=='Enter'{ const node=document.createTextNode'\n' 常量范围=window.getSelection.getRangeAt0 range.insertNodenode const selection=document.getSelection 如果选择{ 选择2.collapsenode } event.preventDefault } }
期待浏览器供应商在使用索引1调用collapse时也将此作为默认行为。希望有一天会发生这种情况。:顺便说一句,请注意log语句和first ENTER press vs second上反映的不同值。不知道这是什么意思,但很有趣。如果我们检查cmd元素,我们实际上会发现keysecast正在可靠地插入br标记!但事实上,第一个回车符并不显示新行。奇怪的它实际上添加了br?古怪的让我试试链接帖子中提到的技巧。好吧,现在我很困惑。我做了这个把戏,它成功了。除了第一次按enter键!好的,让我们来看一下spitball,控制台日志显示,当该行上有文本时,引用表示一个文本节点。将插入br标记,但不显示换行符。如果它是一个空行,它将显示我认为我们想要的预期pcmd节点。因此,换句话说,如果行上有文本,选择器似乎找到了错误的结果。一次按enter键会附加一个br标记,因此我猜下次选择器运行时,第二次按enter键会让它找到我们预期的目标参考,然后我们就得到了换行符。如果ref是错误的,即sel变量,这就解释了为什么将范围添加到文本节点而不是pcmd元素并不能得到我们想要的结果。不知道为什么会这样。很高兴这个把戏奏效了!