【问题标题】:Dealing with line Breaks on contentEditable DIV处理 contentEditable DIV 上的换行符
【发布时间】:2011-08-26 18:27:54
【问题描述】:

我对 SAFARI/CHROME 上的 contenteditable 换行有疑问。当我在 contentEditable <div> 上按“返回”时,他们没有创建 <br>(如 Firefox),而是创建了一个新的 <div>

<div>Something</div>
<div>Something</div>

看起来像(在 contentEditable DIV 上):

Something
Something

但是在清理之后(删除&lt;div&gt;),我得到了这个:

SomethingSomething

在 Firefox 中,contenteditable 是:

Something
<br>
Something

而且消毒后看起来一样:

Something
Something

有什么解决方案可以跨浏览器“规范化”这个吗?

我在Make a <br> instead of <div></div> by pressing Enter on a contenteditable找到了这个代码

$(function(){

  $("#editable")

  // make sure br is always the lastChild of contenteditable
  .live("keyup mouseup", function(){
    if (!this.lastChild || this.lastChild.nodeName.toLowerCase() != "br") {
      this.appendChild(document.createChild("br"));
     }
  })

  // use br instead of div div
  .live("keypress", function(e){
    if (e.which == 13) {
      if (window.getSelection) {
        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);
        return false;
      }
    }
  });
});

这可行,但(在 SAFARI 和 CHROME 中)我必须按两次“返回”键才能换行...

有什么想法吗?

编辑:除了“确保&lt;br&gt; 元素始终是lastChild ...如何解决这个问题?

编辑 2: 我在控制台上收到此错误:Uncaught TypeError: Object #&lt;HTMLDocument&gt; has no method 'createChild'

编辑 3: 好的,我将 document.createChild("br"); 更改为 document.createElement("br"); 并且我认为我可以在 FF/Safari/Chrome 中使用它...全部返回 &lt;br&gt; 换行。 ..

现在的问题是,当我在有序或无序列表中时,我需要在没有&lt;br&gt;...的情况下换行...

编辑4:如果有人对上次编辑的解决方案感兴趣:Avoid createElement function if it's inside a <LI> element (contentEditable)

【问题讨论】:

  • 你的消毒方法是什么样的?
  • @mdmullinax 它只是删除了所有
    ... 我正在使用 github.com/gbirke/Sanitize.js 问题是 Safari/Chrome,当我按下回车键时,它们只是创建一个新的 DIV 而不是制作
    像 Firefox
  • 也许你可以使用 $("div:empty").replaceWith("
    ");
  • 有没有发现对两个返回键的bug有用的东西?我遇到了同样的问题,我似乎唯一能做的就是破解(添加一个空文本并选择它,所以如果你继续写它会自动消失),我会在那个线程上发帖以防万一。它并不完美,但它确实有效。
  • Firefox 现在有一种混合方法:它将
    s 包装在
    s 中。这使它的行为类似于 Chrome,我猜是因为 react 完全删除了
    s,包括
    s.

标签: jquery contenteditable sanitization


【解决方案1】:

当您在内容可编辑的 div 中预填充数据并将其重新发送到服务器时,通常会出现此用例。

例如。 - 就像在社交媒体网站上编辑帖子一样,为了缓解这种情况,我为每个新行创建了新的 div。

let conD =data.postDescription.split('\n');
let conH = "";
conD.forEach((d)=>{
        conH +=`<div>${d}</div>`;
       });
$("#contentbox").html(conH);

【讨论】:

    【解决方案2】:

    你可以使用:

    document.execCommand("defaultParagraphSeparator", false, "br");
    

    完整的参考是here

    【讨论】:

      【解决方案3】:

      您可以简单地使用以下命令 document.execCommand('insertHTML',false,'&lt;br&gt;');

      此命令将阻止默认行为并添加您希望的标签。 就是这样,1行代码

      甚至更简单的方法。

      仅限 CSS。

      对你的 contenteditable 元素应用 display:inline-block 规则 这只会添加brs

      【讨论】:

      • 这种 css 方法太棒了!干杯@Karb
      • 这两种解决方案都不适合我。尝试使用“keypress”、“keydown”和“keyup”,并一次使用这两种解决方案。但 Firefox 仍在创建 DIVS :/
      【解决方案4】:

      听击键似乎需要做很多工作。像这样简单的事情是否可行:

      var html = $('.content').html().replace(/<div>/gi,'<br>').replace(/<\/div>/gi,'');
      

      JSFiddle 演示 here.

      此外,sanitize.js 似乎允许自定义配置。您是否尝试过将div 添加为允许的元素?

      允许 HTML/CSS 是危险的,因此请务必格外小心。

      编辑: 删除了服务器端 cmets。消毒发生在使用时——如果客户想在本地绕过它,可以自行承担风险。感谢Vincent McNabb 指出这一点。

      【讨论】:

      • 看起来清理是为了显示目的,而不是出于安全目的,在这种情况下,在客户端上进行清理是完全合理的。如果他们愿意,他们可以绕过它,而它所要做的就是让事情对他们来说看起来很丑。
      • 我相信在使用时出于安全目的进行了清理(例如,去除 HTML 输出的不安全标记)。您提出了一个很好的观点,如果客户想在本地绕过它,可以自行承担风险。
      【解决方案5】:

      您可能想查看 css white-space 属性。将样式设置为 white-space: pre-wrap 可以让您摆脱所有 javascript,因为它会更改空白的行为以显示而不是折叠。

      看到这个答案:HTML - Newline char in DIV content editable?

      【讨论】:

      • 无论white-space设置什么,这个问题仍然存在,这与contentEditable有关
      【解决方案6】:

      这种技术似乎可以避免第一次显示 BR 的 Chrome 错误(使用您提到的代码,您需要按两次 Enter 键)。

      这不是一个完美的技巧,但它确实有效:它在您的 BR 之后添加了一个空格,以便正确显示。 但是,您会看到仅添加空格“”不会改变任何内容,它适用于其他字母。浏览器不会显示它,可能是因为它就像一个 html 页面中的空白区域,它根本没有任何意义。为了摆脱这个错误,我使用 jQuery 创建了一个包含 &amp;nbsp; 标记的 div,然后我将 text() 属性放在 textnode 中,否则它不起作用。

      $editables = $('[contenteditable=true]');
      
      $editables.filter("p,span").on('keypress',function(e){
       if(e.keyCode==13){ //enter && shift
      
        e.preventDefault(); //Prevent default browser behavior
        if (window.getSelection) {
            var selection = window.getSelection(),
                range = selection.getRangeAt(0),
                br = document.createElement("br"),
                textNode = document.createTextNode("\u00a0"); //Passing " " directly will not end up being shown correctly
            range.deleteContents();//required or not?
            range.insertNode(br);
            range.collapse(false);
            range.insertNode(textNode);
            range.selectNodeContents(textNode);
      
            selection.removeAllRanges();
            selection.addRange(range);
            return false;
        }
      
         }
      });
      

      【讨论】:

      • 添加 range.deleteContents();在 selection.removeAllRanges(); 之前摆脱那些讨厌的  同时保持一切正常^^
      • 在“return false”之前添加 document.execCommand('delete') 可以解决问题,并且不会显示选定的空白选择。
      【解决方案7】:

      如果 br 是容器的最后一个(非空)子容器,Webkits 不会渲染它。对于 Safari,插入换行符的原生按键是 Ctrl + Return。如果你仔细观察,你会注意到 Safari 实际上插入了两个brs,而只渲染了一个;但是,如果有一些尾随文本,它将插入单个 br,或者一旦您输入一些文本(如果有双精度),它将删除双 brs。

      显然,Webkits 的解决方案似乎是像他们自己一样插入双 brs,然后让他们处理其余的事情。

      【讨论】:

        【解决方案8】:

        【讨论】:

          猜你喜欢
          相关资源
          最近更新 更多
          热门标签