Home > database >  tabs in multiple lines of contenteditable div
tabs in multiple lines of contenteditable div

Time:06-03

in the example below pls place cursor at the start of any line and pressTab key
this works fine
I want the same if multiple lines are selected at once and also delete one tab if Shift Tab is pressed
Probably I need an array of selected lines but have no idea how to get them
Please help

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

CodePudding user response:

Consider the following.

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

Here you can see where we examine the Selection. If it is just a Single line, nothing selected or Collapsed, then we just add a Tab character (\t) at the front of that line. If it is multiple lines, then we need to add a Tab character to each line in the selection.

This means we need to define a Line, so from the Start of the line to the End of Line (EOL), usually Return Carriage (\r) and New Line (\n), sometimes just the New Line. If we look for the New Line character, we ensure each line can be found.

So if the selection is:

lorem ipsum\r\n
dolor sit

You want the following output:

\tlorem ipsum\r\n
\tdolor sit

First we find all the Lines and get a count, so that we can iterate each and append the Tab character. We collect each line, modify it, and place it into a Document Fragment for entering later. As needed, we add the New Line character back.

If you want to use an Array, then .split("\n") would be a good way to do this.

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

  • Related