Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you keep the tab level in a textarea when pressing enter?

When the user presses enter I want the cursor to move to a new line, but if they are currently indented by two tabs, then the cursor should stay indented two tabs.

I have already implemented the ignore tab event to stop the focus moving within the page, so I'm now just looking for the logic to keep the tab level on new line.

if(e.keyCode === 13){

    //Logic here
}
like image 508
JMac Avatar asked Feb 11 '14 23:02

JMac


2 Answers

http://jsfiddle.net/DVKbn/

$("textarea").keydown(function(e){
    if(e.keyCode == 13){

        // assuming 'this' is textarea

        var cursorPos = this.selectionStart;
        var curentLine = this.value.substr(0, this.selectionStart).split("\n").pop();
        var indent = curentLine.match(/^\s*/)[0];
        var value = this.value;
        var textBefore = value.substring(0,  cursorPos );
        var textAfter  = value.substring( cursorPos, value.length );

        e.preventDefault(); // avoid creating a new line since we do it ourself
        this.value = textBefore + "\n" + indent + textAfter;
        setCaretPosition(this, cursorPos + indent.length + 1); // +1 is for the \n
    }
});

function setCaretPosition(ctrl, pos)
{

    if(ctrl.setSelectionRange)
    {
        ctrl.focus();
        ctrl.setSelectionRange(pos,pos);
    }
    else if (ctrl.createTextRange) {
        var range = ctrl.createTextRange();
        range.collapse(true);
        range.moveEnd('character', pos);
        range.moveStart('character', pos);
        range.select();
    }
}
like image 112
Endless Avatar answered Sep 22 '22 17:09

Endless


I improved the answer by Endless by using execCommand 'insertText' instead of modifying textarea.value.

Advantages:

  • Maintains undo-redo history of the <textarea>.
  • Maintains native behavior where any selected text is deleted.
  • Does not lag when value is 4000+ characters.
  • Shorter, simpler code.

Disadvantages:

  • Currently not supported by Firefox. (Use solution by Endless as fallback.)

$('textarea').on('keydown', function(e) {
    if (e.which == 13) { // [ENTER] key
      event.preventDefault()  // We will add newline ourselves.

      var start = this.selectionStart;
      var currentLine = this.value.slice(0, start).split('\n').pop();
      var newlineIndent = '\n' + currentLine.match(/^\s*/)[0];

      if (!document.execCommand('insertText', false, newlineIndent)) {
          // Add fallback for Firefox browser:
          // Modify this.value and update cursor position as per solution by Endless.
      }
    }
  

});
<textarea style="width:99%;height:99px;">        I am indented by 8 spaces.
	I am indented by a tab.</textarea>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
like image 30
Leftium Avatar answered Sep 24 '22 17:09

Leftium