admin管理员组

文章数量:1429336

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
}

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
}
Share Improve this question asked Feb 11, 2014 at 23:25 JMacJMac 5331 gold badge6 silver badges17 bronze badges 1
  • 2 You'll have to maintain a form class-local variable that holds the current tab level, and then append tabs or spaces to the end of the textarea text as required to maintain that tab level. You'll also need to hook shift-tab so that the user can reduce the tab level if he wants to. – Robert Harvey Commented Feb 11, 2014 at 23:27
Add a ment  | 

3 Answers 3

Reset to default 5

http://jsfiddle/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();
    }
}

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./ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Must say solutions based on one key press are obscure because people also like pasting text. Use input event instead. You can make it in jQuery like so:

$('textarea').on('input', function(e) {
var el = $(this);
var cur = $(this).prop('selectionStart'); // retrieve current caret position before setting value
var text = $(this).val();
var newText = text.replace(/^(.+)\t+/mg, '$1'); // remove intermediate tabs
newText = newText.replace(/^([^\t]*)$/mg, '\t\t$1'); // add two tabs in the beginning of each line

if (newText != text) { // If text changed...
	$(this).val(newText); // finally set value
	// and reset caret position shifted right by one symbol
	$(this).prop('selectionStart', cur + 1);
	$(this).prop('selectionEnd', cur + 1);
}
});
<textarea></textarea>
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.3.1/jquery.min.js"></script>

By the way I'm too lazy to explain how to watch tab count needed for user, this one just inserts two tabs on every line.

本文标签: javascriptHow do you keep the tab level in a textarea when pressing enterStack Overflow