处理contentEditable DIV上的换行符

时间:2011-05-16 20:54:49

标签: jquery contenteditable sanitization

我在SAFARI / CHROME上遇到contenteditable换行问题。当我在contentEditable <div>上按“return”,而不是创建<br>(如Firefox)时,他们会创建一个新的<div>

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

看起来像(在contentEditable DIV上):

Something
Something

但是在消毒后(删除<div>),我得到了这个:

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中)我必须按两次“返回”键才能获得新行...

有什么想法吗?

编辑:使用我找到的代码(在此问题的底部)工作正常,但“确保<br>元素始终是lastChild的函数...”关于如何解决这个问题的想法?

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

编辑3:好的,我将document.createChild("br");更改为document.createElement("br");,我认为我在FF / Safari / Chrome中运行了...所有返回{{1对于新行......

现在的问题是,当我在有序或无序列表中时,我需要获得一个没有<br>的新行......

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

8 个答案:

答案 0 :(得分:28)

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

这不是一个完美的黑客,但它的工作原理:它会在你的BR之后添加一个空格,以便正确显示。 但是,您将看到只添加空格“”不会改变任何内容,它可以与其他字母一起使用。浏览器不会显示它,可能是因为它就像是一个html页面内的空白区域,它根本没有任何意义。为了摆脱这个错误,我创建了一个包含&nbsp;标记的jQuery 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;
  }

   }
});

答案 1 :(得分:13)

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

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

JSFiddle demo here

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

允许HTML / CSS是危险的,因此请确保您格外小心。

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

答案 2 :(得分:9)

您只需使用以下命令即可 document.execCommand('insertHTML',false,'<br>');

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

更简单的方法。

仅限CSS。

对您来说,应用display:inline-block规则符合要求 这将只添加 br

答案 3 :(得分:2)

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

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

答案 4 :(得分:1)

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

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

答案 5 :(得分:0)

答案 6 :(得分:0)

您可以使用:

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

完整参考是here

答案 7 :(得分:0)

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

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

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