多行 contenteditable div 中的选项卡

tabs in multiple lines of contenteditable div

在下面的示例中,请将光标放在任意行的开头并按Tab
这工作正常
如果一次选择多行我想要相同的,如果按下 Shift+Tab
也删除一个选项卡 可能我需要一组选定的行,但不知道如何获取它们
请帮助

$('#wrap').on('keydown', function(e){
    if(e.keyCode === 9){
        e.preventDefault();
        var range = window.getSelection().getRangeAt(0);
        var tab = document.createTextNode("\u00a0");
        range.insertNode(tab);
        range.setStartAfter(tab);
    }
});
.wrap{padding:0 14px 9px 14px; white-space:pre-wrap; background:orange; outline:none;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='wrap' id='wrap' contenteditable>
lorem ipsum
dolor sit
amet
</div>

考虑以下因素。

$('#wrap').on('keydown', function(e) {
  if (e.keyCode === 9) {
    e.preventDefault();
    var sel = window.getSelection();
    if (sel.getRangeAt && sel.rangeCount) {
      var range = window.getSelection().getRangeAt(0);
      var tab = document.createTextNode("\t");
      if (range.collapsed) {
        range.insertNode(tab);
        range.setStartAfter(tab);
      } else {
        var content = range.toString(),
          count = (content.match(/\n/g) || []).length,
          start = 0,
          end = content.indexOf("\n");
        range.deleteContents();
        var newContent = document.createDocumentFragment();
        for (var i = 0; i <= count; i++) {
          newContent.append("\t" + content.substring(start, end));
          if (i != count) {
            newContent.append("\n");
          }
          start = end + 1;
          end = content.indexOf("\n", start);
          if (end == -1) {
            end = content.length;
          }
        }
        range.insertNode(newContent);
      }
    }
  }
});
.wrap {
  padding: 0 14px 9px 14px;
  white-space: pre-wrap;
  background: orange;
  outline: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='wrap' id='wrap' contenteditable>
lorem ipsum
dolor sit
amet
</div>

在这里您可以看到我们检查选择的位置。如果它只是单行,没有选择或折叠,那么我们只需在该行的前面添加一个制表符 (\t)。如果是多行,那么我们需要在选区的每一行加上一个制表符。

这意味着我们需要定义一行,所以从行的开始到行的结束(EOL),通常是Return回车(\r)和换行(\n), 有时只是新行。如果我们寻找换行符,我们确保可以找到每一行。

所以如果选择是:

lorem ipsum\r\n
dolor sit

您需要以下输出:

\tlorem ipsum\r\n
\tdolor sit

首先我们找到所有的行并得到一个count,这样我们就可以遍历每个行并附加制表符。我们收集每一行,修改它,并将其放入一个文档片段中,以便稍后输入。根据需要,我们添加新行字符。

如果您想使用数组,那么 .split("\n") 将是一个很好的方法。

$('#wrap').on('keydown', function(e) {
  if (e.keyCode === 9) {
    e.preventDefault();
    var range = window.getSelection().getRangeAt(0);
    var content = range.toString().split("\n");
    range.deleteContents();
    var newContent = document.createDocumentFragment();
    $.each(content, function(i, line) {
      newContent.append("\t" + line);
      if (i != (content.length - 1)) {
        newContent.append("\r\n");
      }
    });
    range.insertNode(newContent);
  }
});
.wrap {
  padding: 0 14px 9px 14px;
  white-space: pre-wrap;
  background: orange;
  outline: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='wrap' id='wrap' contenteditable>
lorem ipsum
dolor sit
amet
</div>