159

我有一个contenteditable元素,每当我输入一些东西并点击ENTER它时,它都会创建一个新元素<div>并将新行文本放在那里。我有点不喜欢这个。

是否有可能防止这种情况发生,或者至少只是用 替换它<br>

这是演示http://jsfiddle.net/jDvau/

注意:这在 Firefox 中不是问题。

4

24 回答 24

172

试试这个:

$('div[contenteditable]').keydown(function(e) {
    // trap the return key being pressed
    if (e.keyCode === 13) {
        // insert 2 br tags (if only one br tag is inserted the cursor won't go to the next line)
        document.execCommand('insertHTML', false, '<br/>');
        // prevent the default behaviour of return key pressed
        return false;
    }
});

点击这里进行演示

于 2013-12-05T11:16:28.333 回答
57

将样式添加display:inline-block;contenteditable,它不会生成divp并且会span在 Chrome 中自动生成。

于 2014-07-11T03:02:01.690 回答
53

您只需更改 CSS 即可:

div{
    background: skyblue;
    padding:10px;
    display: inline-block;
}

pre{
    white-space: pre-wrap;
    background: #EEE;
}

http://jsfiddle.net/ayiem999/HW43Q/

于 2013-12-12T01:28:36.977 回答
30

这适用于所有主要浏览器(Chrome、Firefox、Safari、Edge)

document.addEventListener('keydown', event => {
  if (event.key === 'Enter') {
    document.execCommand('insertLineBreak')
    event.preventDefault()
  }
})
<div class="element" contenteditable="true">Sample text</div>
<p class="element" contenteditable="true">Sample text</p>

有一个不便之处。完成编辑后,元素<br>内部可能包含一个结尾。但是如果需要,您可以添加代码来减少它。

检查此答案以删除尾随<br> https://stackoverflow.com/a/61237737/670839

于 2020-04-15T19:48:34.103 回答
24
document.execCommand('defaultParagraphSeparator', false, 'p');

它会覆盖默认行为以改为具有段落。

在 chrome 上,输入的默认行为是:

<div>
    <br>
</div>

有了这个命令,它将是

<p>
    <br>
</p>

现在它的线性度更高,只需<br>您需要即可轻松拥有。

于 2016-02-25T17:39:42.270 回答
23

试试这个:

$('div[contenteditable="true"]').keypress(function(event) {

    if (event.which != 13)
        return true;

    var docFragment = document.createDocumentFragment();

    //add a new line
    var newEle = document.createTextNode('\n');
    docFragment.appendChild(newEle);

    //add the br, or p, or something else
    newEle = document.createElement('br');
    docFragment.appendChild(newEle);

    //make the br replace selection
    var range = window.getSelection().getRangeAt(0);
    range.deleteContents();
    range.insertNode(docFragment);

    //create a new range
    range = document.createRange();
    range.setStartAfter(newEle);
    range.collapse(true);

    //make the cursor there
    var sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);

    return false;
});

http://jsfiddle.net/rooseve/jDvau/3/

于 2013-12-05T10:57:08.773 回答
13

使用shift+enter而不是enter只放入单个<br>标签或将文本包装在<p>标签中。

于 2013-12-06T20:03:22.503 回答
7

在 W3C Editor's Draft 中,有一些关于将状态添加到ContentEditable的信息,并防止浏览器在按下 Enter 时添加新元素,您可以使用plaintext-only.

<div contentEditable="plaintext-only"></div>
于 2019-12-03T10:37:39.567 回答
6

contenteditable按下时的行为方式enter取决于浏览器,<div>发生在 webkit(chrome、safari)和 IE 上。

几个月前我为此苦苦挣扎,并以这种方式纠正了它:

//I recommand you trigger this in case of focus on your contenteditable
if( navigator.userAgent.indexOf("msie") > 0 || navigator.userAgent.indexOf("webkit") > 0 ) {
    //Add <br> to the end of the field for chrome and safari to allow further insertion
    if(navigator.userAgent.indexOf("webkit") > 0)
    {
        if ( !this.lastChild || this.lastChild.nodeName.toLowerCase() != "br" ) {
            $(this).html( $(this).html()+'<br />' );
        }
    }

    $(this).keypress( function(e) {
        if( ( e.keyCode || e.witch ) == 13 ) {
            e.preventDefault();

            if( navigator.userAgent.indexOf("msie") > 0 ) {
                insertHtml('<br />');
            }
            else {
              var selection = window.getSelection(),
              range = selection.getRangeAt(0),
              br = document.createElement('br');

              range.deleteContents();
              range.insertNode(br);
              range.setStartAfter(br);
              range.setEndAfter(br);
              range.collapse(false);

              selection.removeAllRanges();
              selection.addRange(range);
            }
        }
    });
}

我希望它会有所帮助,如果它不像需要的那么清楚,请原谅我的英语。

编辑:更正已删除的 jQuery 函数jQuery.browser

于 2013-12-06T13:50:11.840 回答
6

您可以<p>为每一行使用单独的标签,而不是使用<br>标签,并获得更好的开箱即用的浏览器兼容性。

为此,<p>在 contenteditable div 中放置一个带有一些默认文本的标签。

例如,而不是:

<div contenteditable></div>

采用:

<div contenteditable>
   <p>Replace this text with something awesome!</p>
</div>

jsfiddle

在 Chrome、Firefox 和 Edge 中进行了测试,第二个在每个中的工作方式相同。

然而,第一个在 Chrome 中创建 div,在 Firefox 中创建换行符,在 Edge 中创建 div ,并且光标回到当前 div 的开头而不是移动到下一个。

在 Chrome、Firefox 和 Edge 中测试。

于 2016-12-17T03:42:06.420 回答
5

我喜欢使用 Mousetrap 来处理热键:https ://craig.is/killing/mice

然后,我只是拦截 enter 事件,执行命令insertLineBreak

Mousetrap.bindGlobal('enter', (e)=>{
  window.document.execCommand('insertLineBreak', false, null);
  e.preventDefault();
});

所有命令:https ://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand

它使用 Chrome 75 和以下可编辑元素工作:

<pre contenteditable="true"></pre>

也可以使用insertHTML

window.document.execCommand('insertHTML', false, "\n");
于 2019-07-05T02:44:13.257 回答
4

我会使用样式(Css)来解决这个问题。

div[contenteditable=true] > div {
  padding: 0;
} 

Firefox 确实添加了块元素 break
,而 Chrome 将每个部分包装在一个标签中。您的 css 为 div 提供了10px的填充以及背景颜色。

div{
  background: skyblue;
  padding:10px;
}

或者,您可以在 jQuery 中复制相同的所需效果:

var style = $('<style>p[contenteditable=true] > div { padding: 0;}</style>');
$('html > head').append(style);

这是你的小提琴的一个叉子http://jsfiddle.net/R4Jdz/7/

于 2013-12-11T16:04:49.653 回答
4

当您有嵌套元素时,inserHTML命令解决方案会做一些奇怪的事情。contenteditable

我从这里的多个答案中获得了一些想法,这似乎适合我现在的需求:

element.addEventListener('keydown', function onKeyDown(e) {

    // Only listen for plain returns, without any modifier keys
    if (e.which != 13 || e.shiftKey || e.ctrlKey || e.altKey) {
        return;
    }

    let doc_fragment = document.createDocumentFragment();

    // Create a new break element
    let new_ele = document.createElement('br');
    doc_fragment.appendChild(new_ele);

    // Get the current selection, and make sure the content is removed (if any)
    let range = window.getSelection().getRangeAt(0);
    range.deleteContents();

    // See if the selection container has any next siblings
    // If not: add another break, otherwise the cursor won't move
    if (!hasNextSibling(range.endContainer)) {
        let extra_break = document.createElement('br');
        doc_fragment.appendChild(extra_break);
    }

    range.insertNode(doc_fragment);

    //create a new range
    range = document.createRange();
    range.setStartAfter(new_ele);
    range.collapse(true);

    //make the caret there
    let sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);

    e.stopPropagation();
    e.preventDefault();

    return false;
});

// See if the given node has a next sibling.
// Either any element or a non-empty node
function hasNextSibling(node) {

    if (node.nextElementSibling) {
        return true;
    }

    while (node.nextSibling) {
        node = node.nextSibling;

        if (node.length > 0) {
            return true;
        }
    }

    return false;
}
于 2018-07-31T12:07:30.217 回答
3

您可以用标签包装您的段落,<p>例如它将出现在新行而不是 div 示例:
<div contenteditable="true"><p>Line</p></div>
插入新字符串后:
<div contenteditable="true"><p>Line</p><p>New Line</p></div>

于 2013-12-12T08:20:12.940 回答
2

将阻止默认值添加到 div

document.body.div.onkeydown = function(e) {
    if ( e.keycode == 13 ){
        e.preventDefault();
            //add a <br>
        div = document.getElementById("myDiv");
        div.innerHTML += "<br>";
    }
}
于 2013-12-05T11:00:07.447 回答
2

尝试使用ckeditor。它还在 SOF 中提供类似这样的格式。

https://github.com/galetahub/ckeditor

于 2013-12-05T11:12:59.520 回答
2

首先,我们需要捕获用户输入的每个键以查看是否按下了输入,然后我们阻止<div>创建并创建自己的<br>标签。

有一个问题,当我们创建它时,我们的光标停留在同一位置,所以我们使用Selection API将光标放在最后。

不要忘记<br>在文本末尾添加标签,因为如果您不这样做,第一次输入将不会换行。

$('div[contenteditable]').on('keydown', function(e) {
    var key = e.keyCode,
        el  = $(this)[0];
    // If Enter    
    if (key === 13) {
        e.preventDefault(); // Prevent the <div /> creation.
        $(this).append('<br>'); // Add the <br at the end

        // Place selection at the end 
        // http://stackoverflow.com/questions/4233265/contenteditable-set-caret-at-the-end-of-the-text-cross-browser
        if (typeof window.getSelection != "undefined"
            && typeof document.createRange != "undefined") {
            var range = document.createRange();
            range.selectNodeContents(el);
            range.collapse(false);
            var sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
        } else if (typeof document.body.createTextRange != "undefined") {
            var textRange = document.body.createTextRange();
            textRange.moveToElementText(el);
            textRange.collapse(false);
            textRange.select();
        }
    }
});

小提琴

于 2013-12-12T01:25:39.987 回答
2

这是浏览器导向的 HTML5 编辑器。你可以用 换行你的文本<p>...</p>,然后只要你按 ENTER 就会得到<p></p>。此外,编辑器的工作方式是,每当您按 SHIFT+ENTER 时,它都会插入<br />.

<div contenteditable="true"><p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolor veniam asperiores laudantium repudiandae doloremque sed perferendis obcaecati delectus autem perspiciatis aut excepturi et nesciunt error ad incidunt impedit quia dolores rerum animi provident dolore corporis libero sunt enim. Ad magnam omnis quidem qui voluptas ut minima similique obcaecati doloremque atque!
<br /><br />
Type some stuff, hit ENTER a few times, then press the button.
</p>
</div>

检查这个:http: //jsfiddle.net/ZQztJ/

于 2013-12-12T03:52:14.760 回答
1
if (navigator.userAgent.toLowerCase().indexOf('msie') > -1) {
   var range = document.getSelection();
   range.pasteHTML(range.htmlText + '<br><br>');
}
else if(navigator.userAgent.toLocaleLowerCase().indexOf('trident') > -1)                           {
   var range = document.getSelection().getRangeAt(0); //get caret
   var nnode = document.createElement('br');
   var bnode = document.createTextNode('\u00A0'); //&nbsp;
   range.insertNode(nnode);
   this.appendChild(bnode);
   range.insertNode(nnode);                                
}
else
   document.execCommand('insertHTML', false, '<br><br>')

this实际上下文在哪里,这意味着document.getElementById('test');

于 2014-04-01T17:15:45.297 回答
0

另一种方法

$('button').click(function(){
    $('pre').text($('div')[0].outerHTML)
});

$("#content-edit").keydown(function(e) {
    if(e.which == 13) {
       $(this).find("div").prepend('<br />').contents().unwrap();
      }
});

http://jsfiddle.net/jDvau/11/

于 2013-12-12T06:11:01.770 回答
0

防止在每个输入键上的内容可编辑 Div 中创建新的 Div:我找到的解决方案非常简单:

var newdiv = document.createElement("div"); 
newdiv.innerHTML = "Your content of div goes here";
myEditablediv.appendChild(newdiv);

这 --- innerHTML 内容防止在每个输入键上的内容可编辑 Div 中创建新 Div。

于 2015-04-19T08:42:51.057 回答
0

我使用数百个<td>元素输入计算值,发现 Firefox<div></div><br />在输入时添加了一个不酷的。所以我用了这个onkeyup

$(document).on("keyup", '.first_td_col', function(e) {
    if (e.key === 'Enter' || e.keyCode === 13) {
       e.preventDefault();
       $(this).empty();

       return false;
    }
    // Do calculations if not enter
});

当然,这会清除 中的所有内容<td>,甚至是用户的输入。但是通过显示消息No enter please.,它解决了不必要的元素妨碍仅进行计算。

于 2021-03-14T15:18:21.977 回答
0

我们可以像这样清理 html


function cleanHtml(innerHTML: string) {
  return innerHTML.replaceAll('<div><br></div>', '<br>')
}

在 contentEditable 中这样做

const { innerHTML, innerText } = contentEl
          console.log({ innerHTML, innerText, cleanHtml: cleanHtml(innerHTML) })
于 2021-10-03T15:55:01.690 回答
-1

可以完全防止这种行为。

看到这个小提琴

$('<div class="temp-contenteditable-el" contenteditable="true"></div>').appendTo('body').focus().remove();
于 2014-10-29T13:01:46.610 回答