【问题标题】:Prevent contenteditable adding <div> on ENTER - Chrome防止 contenteditable 在 ENTER 上添加 <div> - Chrome
【发布时间】:2013-09-04 07:55:21
【问题描述】:

我有一个contenteditable 元素,每当我输入一些内容并点击ENTER 时,它都会创建一个新的&lt;div&gt; 并将新的行文本放入其中。我有点不喜欢这个。

是否有可能防止这种情况发生,或者至少只是用&lt;br&gt; 替换它?

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

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

【问题讨论】:

  • firefox 添加了
    ,chrome - 没有,但是在修复您的样式后,额外的 div 不会破坏左侧填充。问题是你为什么不喜欢它?认为它是 br...jsfiddle.net/jDvau/1 您也可以使用 DOMSubtreeModified 事件来捕获这些 div 并将它们删除。
  • stackoverflow.com/questions/6024594/… 这可以帮助你,祝你好运!
  • 对我来说,Blake Plumb 的解决方案是最简单的,也是迄今为止最好的。
  • @svassr 这不是重点,使用它的不是你我,而是一个甚至可能不知道 shift 是什么的客户。
  • 确实它改变了一切。那就是说这是一种常见的行为,小帮助信息不会武装。 “授人以鱼,养其一日。授人以渔,养其一生。”

标签: javascript jquery google-chrome html contenteditable


【解决方案1】:

试试这个:

$('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;
    }
});

Click here for demo

【讨论】:

  • 但我发现这里有点不同。将光标放在空白行上(在“键入一些东西”的顶部),然后按 Enter。光标现在就在“类型”之前,而不是在新的空白行上。
  • 这在 IE11 中不起作用,因为它不支持 insertHTML。请参阅下面的答案!
  • 如果您将光标放在字符之间,例如。 'Ty[cursor]pe some stuff' 然后回车,你得到的 1 行太多了。
  • 答案不可接受。解决方案是只有一个
  • 返回
【解决方案2】:

将样式display:inline-block;添加到contenteditable,不会在Chrome中自动生成divpspan

【讨论】:

  • 这是一个很好的解决方案。 *[contenteditable="true"]{display: inline-block;}
  • 喜欢它,简单但有效
  • 在 IE11 中这会产生一个额外的&lt;p&gt;&lt;/p&gt; :(
  • 但是它会创建另一个非常烦人的Chrome bug(多么糟糕的浏览器)
  • Chrome 版本 63.0.3239.84 不再适用
【解决方案3】:

您只需更改 CSS 即可:

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

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

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

【讨论】:

  • 我使用inline-block时出现问题,执行execCommand("insertHTML", xxx)插入任何东西,插入元素末尾会添加一个“
    ”,在Chrome33中测试.
  • 不错的发现。遗憾的是,这不适用于 position: absolute 元素或作为具有 display: flex 的父级的直接子元素的元素。记住这一点,你可以破解它来工作。只要确保它不是 flex 元素的直接子元素。如果你需要它 position: absolute 只需给它一个额外的父级。
  • @ReinoutvanKempen 3 个月前开始使用 flex。我猜这个 hack 行不通
  • 这是一个非常棒的解决方案,它非常干净清晰,不会插入任何内容,甚至包括 br。尤其是这个没有js的解决方案。
  • 哇...这解决了 Chrome,但让 Firefox 在输入时开始添加 div,默认情况下不会。
【解决方案4】:

这适用于所有主流浏览器(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>

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

检查此答案以删除尾随 &lt;br&gt; https://stackoverflow.com/a/61237737/670839

【讨论】:

  • 什么鬼?真正对我有用的唯一解决方案怎么会在页面下方这么远?非常感谢。
  • 你让我很开心,这需要几个小时才能弄清楚 - 谢谢!
  • execCommand 已被贬低!不再推荐此功能。尽管某些浏览器可能仍支持它,但它可能已从相关网络标准中删除。
  • 这项功能目前适用于所有主流浏览器,并且可能会继续有效,因为没有人会从网络上删除内容。
【解决方案5】:
document.execCommand('defaultParagraphSeparator', false, 'p');

它会覆盖默认行为以使用段落。

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

<div>
    <br>
</div>

有了这个命令就可以了

<p>
    <br>
</p>

现在它更加线性化了,您只需要&lt;br&gt; 就很容易了。

【讨论】:

  • 当您按下回车键时,您将拥有跨浏览器的 p 和 br 而不是 div 和 br。试试看。
  • 谢谢!解释总是有帮助的
  • @jpaugh np,我进一步编辑了我的答案,以便更好地解释。
  • 这在 firefox 上不起作用(我只在 chrome 和 firefox 中测试过)
  • FireFox 已修复,现在尊重 defaultParagraphSeparator。恕我直言,这使此答案成为最佳答案,因为它使所有浏览器现在都保持一致并符合规范。如果您不希望 P 标签与内容可编辑中的前一个文本块有一个边距“间距”,那么您可以使用 css 来修改它。
【解决方案6】:

试试这个:

$('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/

【讨论】:

  • 很好,工作:) 我会等待更多的关注,然后再决定,谢谢。
  • 在 Firefox 上无法正常工作。它增加了一行。
  • 这使得input 在您按下回车时不会被触发。一个简单的解决方案:添加类似$(this).trigger('input')
  • insertHTML 解决方案在存在嵌套的 contenteditable 元素时会做一些奇怪的事情,您的解决方案绕过了这一点,但还有更多问题,我将其添加为新的可能解决方案。
  • 不适用于 Chrome。第一次在字符串末尾按 enter 时,它会添加一个空格。第二次它仍然有效。
【解决方案7】:

使用 shift+enter 而不是 enter 只需将单个 &lt;br&gt; 标签放入或将您的文本包装在 &lt;p&gt; 标签中.

【讨论】:

  • +1 谢谢,这很容易知道,但是如果您有一个正在写书的客户,那将是一个痛苦的 ***跨度>
  • 如果您要粘贴内容,这将无济于事
【解决方案8】:

当您按下 entercontenteditable 的行为方式取决于浏览器,&lt;div&gt; 发生在 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);
            }
        }
    });
}

我希望它会有所帮助,如果我的英语不够清楚,请原谅。

EDIT : 更正移除的jQuery函数jQuery.browser

【讨论】:

  • 只是让你知道,jQuery.browser 不再是 jQuery 的一部分。
  • 你说得对,我应该提到这一点并使用 navigator.userAgent.indexOf("msie") &gt; 0navigator.userAgent.indexOf("webkit") &gt; 0 之类的东西
  • if( ( e.keyCode || e.witch ) == 13 ) { ... } 必须是 if (e.keyCode === 13 || e.which === 13) { ... }
【解决方案9】:

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

为此,在 contenteditable div 中放置一个带有一些默认文本的 &lt;p&gt; 标记。

例如,而不是:

<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 中测试。

【讨论】:

  • 这其实是一个不错的解决方案
【解决方案10】:

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

<div contentEditable="plaintext-only"></div>

【讨论】:

  • 谢谢!这对我来说很好。它不添加 div 或 br。
  • 这就是我需要的!
  • 它仍处于早期阶段。截至 2021 年 12 月,只有 57% 的浏览器支持
【解决方案11】:

我喜欢使用 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");

【讨论】:

  • 我什么都没做……
【解决方案12】:

我会使用样式 (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/

【讨论】:

  • 这可能对某些人有所帮助,但我更担心不必要的标记,因为我将采用 contenteditable 的最终 HTML 并在其他地方使用它
【解决方案13】:

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

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

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;
}

【讨论】:

  • 男人。谢谢你的代码,它救了我!
【解决方案14】:

你可以用&lt;p&gt;标签包裹你的段落,例如它会出现在新行而不是div上 示例:
&lt;div contenteditable="true"&gt;&lt;p&gt;Line&lt;/p&gt;&lt;/div&gt;
插入新字符串后:
&lt;div contenteditable="true"&gt;&lt;p&gt;Line&lt;/p&gt;&lt;p&gt;New Line&lt;/p&gt;&lt;/div&gt;

【讨论】:

    【解决方案15】:

    为 div 添加一个阻止默认值

    document.body.div.onkeydown = function(e) {
        if ( e.keycode == 13 ){
            e.preventDefault();
                //add a <br>
            div = document.getElementById("myDiv");
            div.innerHTML += "<br>";
        }
    }
    

    【讨论】:

    • @connorspiracist 对不起它的document.body.div(你可能需要输入一些其他代码来指向正确的div 这只是一般的想法)
    【解决方案16】:

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

    https://github.com/galetahub/ckeditor

    【讨论】:

      【解决方案17】:

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

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

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

      $('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();
              }
          }
      });
      

      Fiddle

      【讨论】:

        【解决方案18】:

        这是面向浏览器的 HTML5 编辑器。你可以用&lt;p&gt;...&lt;/p&gt; 包裹你的文本,然后每当你按下回车键你就会得到&lt;p&gt;&lt;/p&gt;。此外,编辑器的工作方式是,每当您按 SHIFT+ENTER 时,它都会插入&lt;br /&gt;

        <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/

        【讨论】:

          【解决方案19】:
          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');

          【讨论】:

            【解决方案20】:

            另一种方法

            $('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/

            【讨论】:

            • 它不会让光标在您键入时向前移动。
            • 这很奇怪,我刚刚在 Chrome 和 IE 11 中尝试过,它工作正常。 Reference能告诉我你用的是什么浏览器吗?有关该行为的更多详细信息将有助于解决问题
            【解决方案21】:

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

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

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

            【讨论】:

              【解决方案22】:

              我使用数百个 &lt;td&gt; 元素输入计算值,发现 Firefox 在输入时添加了一个 &lt;div&gt;&lt;/div&gt;&lt;br /&gt;,这并不酷。所以我用了这个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
              });
              
              

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

              【讨论】:

                【解决方案23】:

                我们可以像这样清理 html

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

                在 contentEditable 中这样做

                const { innerHTML, innerText } = contentEl
                          console.log({ innerHTML, innerText, cleanHtml: cleanHtml(innerHTML) })
                

                【讨论】:

                  【解决方案24】:

                  可以完全阻止这种行为。

                  See this fiddle

                  $('<div class="temp-contenteditable-el" contenteditable="true"></div>').appendTo('body').focus().remove();
                  

                  【讨论】:

                    猜你喜欢
                    • 2011-04-15
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2014-07-21
                    • 2013-11-25
                    相关资源
                    最近更新 更多