Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/453.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 需要按两次Enter键才能添加范围_Javascript_Html_Range_Selection_Contenteditable - Fatal编程技术网

Javascript 需要按两次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

我刚刚学习了如何使用选择和范围,并建立了一个更好的方法,在contenteditable divs中按enter键。按下enter键时,将调用event.preventDefault,程序将在contenteditable通常会添加div的位置插入。但是,我需要按两次enter键才能发生任何事情。另一个奇怪的事实是:当那一行没有文本时,这种情况就不会发生。我对选择和范围还不熟悉,我相信这是新手犯的错误。代码如下:

 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元素并不能得到我们想要的结果。不知道为什么会这样。很高兴这个把戏奏效了!