6

我有一个设置了属性 contentEditable 的 div。

我遇到的问题是我输入的第一行没有被标签包裹,但后面的行会。

所以输入:

qwerty
zxcv
asdfg

结果是:

<div class="editable" contentEditable="true">
    qwerty
    <div>zxcv</div>
    <div>asdfg</div>
</div>

所以我需要这qwerty条线成为<div>qwerty</div>

4

8 回答 8

8

我在 Chrome 中遇到了问题,只是添加了一个 div。仅当您的 div 包含 br 标签时才有效:

<div class="editable" contentEditable="true">
  <div>
    <br>
  </div>
</div>

@nicholas_r 是对的,删除可编辑 div 中的最后一个字符也会删除开头添加的 div。您可以通过捕获最后一个“退格”来避免这种情况。使用 jquery 的简单解决方案:

$(".editable").on('keydown', function(event) {
  if (event.keyCode === 8 && $(this).html() == '<div><br></div>') {
    event.preventDefault();
  }
}
于 2014-07-18T14:22:48.313 回答
4

如果有帮助,运行以下命令将让您包装展开的 divs 。如果您在按键或类似的情况下触发它,即使用户从 div 中删除所有内容,它也会起作用。

 $(".editable").contents().filter(function() {
    return this.nodeType == 3;
 }).wrap('<div></div>');
于 2013-11-18T06:51:50.317 回答
2

如果你从一个内部包含 a 的元素开始,div如下所示:

<div class="editable" contentEditable="true"> <div></div> </div>

您键入的第一行最终将被包裹在div.

更新:

这是特定于浏览器的。虽然在发布问题时它在大多数浏览器中都可以使用,但在最新的浏览器版本中不一定可以使用。最好的判断方法是测试它。

于 2012-09-26T12:52:12.410 回答
1

我做了这样的事情,它非常适合确保在第一行文本上总是有一个 div 包装器。

这样,如果用户单击该字段及其空白(初始状态),它将在其中放置一个空格,以确保他们的光标位于新 div 内。

$editable.on('focus', function() {
  if ($(this).text().trim() === '') {
    console.log('editable is blank, insert a div');
    $(this).append($('<div>&nbsp;</div>'));  
  }
});

您可以在保存数据之前删除前导空格(如果重要)。

于 2015-01-24T01:01:54.530 回答
1

对于在 2017 年或之后遇到此问题的任何人,这些答案在 Chrome 中都不适合我,而那些试图提出智能解决方案的人并没有涵盖我的所有案例。

虽然只在 Chrome 中测试过,而且有点粗糙,但它涵盖了 3 个主要场景:

  1. 用户尝试删除空contenteditablediv 中的内容。
  2. 用户尝试使用或删除contenteditablediv中的所有内容。ctrl+a Deletectrl+a Backspace
  3. 用户尝试通过用他们选择的字母contenteditable替换完整选择来删除 div中的所有内容。ctrl-a

一个JSFiddle演示。

document.getElementById("editor").addEventListener("keydown", function(e){
  if(e.which == 8 && document.getElementById("editor").innerHTML=="<div><br></div>"){  // 8 is backspace
    e.preventDefault()
  }
  if (window.getSelection && e.which == 8 || e.which == 46 && window.getSelection){ // 8 is backspace, 46 is delete
    let selection = window.getSelection().toString();
    let editorText = document.getElementById("editor").innerText;

    if (editorText == selection){
      document.getElementById("editor").innerHTML="<div><br></div>"
      console.log("prevented a ctrl+a delete")
    }
  else if (window.getSelection){
    let selection = window.getSelection().toString();
    let editorText = document.getElementById("editor").innerText;

    if (editorText == selection){
      document.getElementById("editor").innerHTML="<div>"+e.which+"</div>";
      console.log("safely did a ctrl+a " + e.which)
    }
  }

  e.preventDefault()
  }
})
于 2017-02-04T14:41:01.580 回答
1

大多数这些解决方案在 2017 年的 Chrome(版本 61.x)中都不适用于我,而且Kasper 的回答对我来说似乎太混乱了。

据我所知,对事件的""<br>input事件的简单检查可以处理所有可能的情况,包括退格、删除和复制粘贴:

$("[contenteditable='true']")
  .on("input", function ()
  {
    var $editable = $(this);
    if ($editable.html().trim() === "" || $editable.html().trim() === "<br>")
      $editable.html($("<div><br></div>"));
  })
  .trigger("input");

请注意,我还会input在初始化时触发事件,以确保正确设置初始内容,但这可能是必要的,也可能不是必要的,具体取决于您的特定需求。

https://jsfiddle.net/25ujvrn0/

于 2017-10-05T15:54:16.220 回答
1

上下文
这是 OP 的解决方案,可确保内容可编辑 div 中的第一行始终被包装并修复常见错误,例如:

  • 擦除编辑器并立即键入后展开第一行。
  • 删除编辑器后添加换行符。
  • Kasper Fredenslund 提到的所有问题:
    • Ctrl + A + 德尔
    • Ctrl + A + 退格
    • Ctrl + A + 用户输入的任何内容

它使用事件侦听器来捕捉用户何时关注编辑器以及何时离开。有关更多上下文,请阅读代码中的注释。

下面的代码
是代码的完整工作小提琴。我的原始示例可以在这个JS Fiddle 页面上找到。

// On Dom Ready
document.getElementById('editor').addEventListener('focusin', checkEditor);
document.getElementById('editor').addEventListener('focusout', checkEditor);

function checkEditor() {
  // Get the DOM element that the user is in
  // Allows you to have multiple editos on one page
  // Next 3 lines of code from: https://stackoverflow.com/a/1553668/3193156
  var e = event || window.event;
  var elem = e.target || e.srcElement;
  if (elem.nodeType == 3) {
    elem = elem.parentNode;
  } // Defeat Safari bug
  // Grab the elements inner HTML
  var html = elem.innerHTML
    // If html is empty or does not start with a div see if we need to fix something
  if (html == '' || html.substr(0, 5) != '<div>') {
    notify('Running editor checks.');
    var index;
    // Catch bug where a line break is added after a user uses backspace to wipe the editor
    if (html.substr(0, 4) == '<br>') {
      notify('Removed line break.');
      index = html.indexOf('\n');
      // If there are any lines after this line break save them
      if (index > -1) {
        html = html.substr(html.indexOf('\n') + 1);
      } else {
        html = '';
      }
      elem.innerHTML = html;
      // If everything is ok return otherwise keep processing
      if (html != '' && html.substr(0, 5) == '<div>') {
        return;
      }
    }
    // Catch bug where first line after erasing editor does not get wrapped
    index = html.indexOf('\n');
    if (index > -1) {
      notify('Wrapped the fist line, did not check the rest.');
      html = html = '<div>' + html.substr(0, html.indexOf('\n') + 1) + '</div>' + html.substr(html.indexOf('\n') + 1);
      elem.innerHTML = html;
      return;
    } else {
      html = html.trim();
      if (html.length > 0) {
        notify('Wrapped the fist line');
        html = '<div>' + html.trim() + '</div>';
        elem.innerHTML = html;
        return;
      }
    }
    // If we made it here the editor shold be considered empty, reset it
    notify('Editor reset.');
    var div = document.createElement('DIV');
    div.innerHTML = '<br>';
    elem.appendChild(div);
  }
}

function notify(msg) {
  var div = document.createElement('DIV');
  div.innerHTML = msg;
  document.getElementById('messages').appendChild(div);
}
#editor {
  width: 90%;
  height: 200px;
  padding: 1rem;
  border: 1px solid #000;
}
<div id="editor" contenteditable="true">

</div>
<div id="messages">
</div>

To-Do / Missing
此解决方案回答了 OP,但不考虑以下用例:

  • 粘贴内容后检查结果;这需要逐行包装所有内容。
  • 检查第一行之后的任何其他行;不常见,但我相信您最终可能会在内容的末尾加上未换行的行,具体取决于浏览器。
于 2017-12-06T23:52:35.740 回答
0

简单<div></div>是行不通的。

如果您正在寻找 jQuery 解决方案,这里是代码:

$('.contenteditable').on 'focus', ->
  if $(@).text().trim() == ''
    $(@).append($('<div><br /></div>'))
于 2015-05-06T17:53:16.840 回答