[javascript] How do I detect "shift+enter" and generate a new line in Textarea?

Currently, if the person presses enter inside the text area, the form will submit.
Good, I want that.

But when they type shift + enter, I want the textarea to move to the next line: \n

How can I do that in JQuery or plain JavaScript as simple as possible?

This question is related to javascript jquery html css

The answer is


Better use simpler solution:

Tim's solution below is better I suggest using that: https://stackoverflow.com/a/6015906/4031815


My solution

I think you can do something like this..

EDIT : Changed the code to work irrespective of the caret postion

First part of the code is to get the caret position.

Ref: How to get the caret column (not pixels) position in a textarea, in characters, from the start?

function getCaret(el) { 
    if (el.selectionStart) { 
        return el.selectionStart; 
    } else if (document.selection) { 
        el.focus();
        var r = document.selection.createRange(); 
        if (r == null) { 
            return 0;
        }
        var re = el.createTextRange(), rc = re.duplicate();
        re.moveToBookmark(r.getBookmark());
        rc.setEndPoint('EndToStart', re);
        return rc.text.length;
    }  
    return 0; 
}

And then replacing the textarea value accordingly when Shift + Enter together , submit the form if Enter is pressed alone.

$('textarea').keyup(function (event) {
    if (event.keyCode == 13) {
        var content = this.value;  
        var caret = getCaret(this);          
        if(event.shiftKey){
            this.value = content.substring(0, caret - 1) + "\n" + content.substring(caret, content.length);
            event.stopPropagation();
        } else {
            this.value = content.substring(0, caret - 1) + content.substring(caret, content.length);
            $('form').submit();
        }
    }
});

Here is a demo


Most of these answers overcomplicate this. Why not try it this way?

$("textarea").keypress(function(event) {
        if (event.keyCode == 13 && !event.shiftKey) {
         submitForm(); //Submit your form here
         return false;
         }
});

No messing around with caret position or shoving line breaks into JS. Basically, the function will not run if the shift key is being pressed, therefore allowing the enter/return key to perform its normal function.


Why not just

$(".commentArea").keypress(function(e) {
    var textVal = $(this).val();
    if(e.which == 13 && e.shiftKey) {

    }
    else if (e.which == 13) {
       e.preventDefault(); //Stops enter from creating a new line
       this.form.submit(); //or ajax submit
    }
});

In case someone is still wondering how to do this without jQuery.

HTML

<textarea id="description"></textarea>

Javascript

const textarea = document.getElementById('description');

textarea.addEventListener('keypress', (e) => {
    e.keyCode === 13 && !e.shiftKey && e.preventDefault(); 
})

Vanilla JS

var textarea = document.getElementById('description');

textarea.addEventListener('keypress', function(e) {
    if(e.keyCode === 13 && !e.shiftKey) {
      e.preventDefault();
    }
})

using ng-keyup directive in angularJS, only send a message on pressing Enter key and Shift+Enter will just take a new line.

ng-keyup="($event.keyCode == 13&&!$event.shiftKey) ? sendMessage() : null"

Use the jQuery hotkeys plugin and this code

jQuery(document).bind('keydown', 'shift+enter', 
         function (evt){ 
             $('textarea').val($('#textarea').val() + "\n");// use the right id here
             return true;
         }
);

I use div by adding contenteditable true instead of using textarea.

Hope can help you.

$("#your_textarea").on('keydown', function(e){//textarea keydown events
  if(e.key == "Enter")
  {
    if(e.shiftKey)//jump new line
    {
     // do nothing
    }
    else  // do sth,like send message or else
    {
       e.preventDefault();//cancell the deafult events
    }
  }
})

Here is an AngularJS solution using ng-keyup if anyone has the same issue using AngularJS.

ng-keyup="$event.keyCode == 13 && !$event.shiftKey && myFunc()"

I found this thread looking for a way to control Shift + any key. I pasted together other solutions to make this combined function to accomplish what I needed. I hope it helps someone else.

function () {
    return this.each(function () {
    $(this).keydown(function (e) {
        var key = e.charCode || e.keyCode || 0;
        // Shift + anything is not desired
        if (e.shiftKey) {
            return false;
        }
        // allow backspace, tab, delete, enter, arrows, numbers 
        //and keypad numbers ONLY
        // home, end, period, and numpad decimal
        return (
            key == 8 ||
            key == 9 ||
            key == 13 ||
            key == 46 ||
            key == 110 ||
            key == 190 ||
            (key >= 35 && key <= 40) ||
            (key >= 48 && key <= 57) ||
            (key >= 96 && key <= 105));
    });
});

Easy & Elegant solution:

First, pressing Enter inside a textarea does not submit the form unless you have script to make it do that. That's the behaviour the user expects and I'd recommend against changing it. However, if you must do this, the easiest approach would be to find the script that is making Enter submit the form and change it. The code will have something like

if (evt.keyCode == 13) {
    form.submit();
}

... and you could just change it to

if (evt.keyCode == 13 && !evt.shiftKey) {
    form.submit();
}

On the other hand, if you don't have access to this code for some reason, you need to do the following to make it work in all major browsers even if the caret is not at the end of the text:

jsFiddle: http://jsfiddle.net/zd3gA/1/

Code:

function pasteIntoInput(el, text) {
    el.focus();
    if (typeof el.selectionStart == "number"
            && typeof el.selectionEnd == "number") {
        var val = el.value;
        var selStart = el.selectionStart;
        el.value = val.slice(0, selStart) + text + val.slice(el.selectionEnd);
        el.selectionEnd = el.selectionStart = selStart + text.length;
    } else if (typeof document.selection != "undefined") {
        var textRange = document.selection.createRange();
        textRange.text = text;
        textRange.collapse(false);
        textRange.select();
    }
}

function handleEnter(evt) {
    if (evt.keyCode == 13 && evt.shiftKey) {
        if (evt.type == "keypress") {
            pasteIntoInput(this, "\n");
        }
        evt.preventDefault();
    }
}

// Handle both keydown and keypress for Opera, which only allows default
// key action to be suppressed in keypress
$("#your_textarea_id").keydown(handleEnter).keypress(handleEnter);

This works for me!

$("#your_textarea").on('keydown', function(e){
    if(e.keyCode === 13 && !e.shiftKey) 
    {

          $('form').submit();

    }
});

Using ReactJS ES6 here's the simplest way

shift + enter New Line at any position

enter Blocked

_x000D_
_x000D_
class App extends React.Component {_x000D_
_x000D_
 constructor(){_x000D_
    super();_x000D_
    this.state = {_x000D_
      message: 'Enter is blocked'_x000D_
    }_x000D_
  }_x000D_
  onKeyPress = (e) => {_x000D_
     if (e.keyCode === 13 && e.shiftKey) {_x000D_
        e.preventDefault();_x000D_
        let start = e.target.selectionStart,_x000D_
            end = e.target.selectionEnd;_x000D_
        this.setState(prevState => ({ message:_x000D_
            prevState.message.substring(0, start)_x000D_
            + '\n' +_x000D_
            prevState.message.substring(end)_x000D_
        }),()=>{_x000D_
            this.input.selectionStart = this.input.selectionEnd = start + 1;_x000D_
        })_x000D_
    }else if (e.keyCode === 13) { // block enter_x000D_
      e.preventDefault();_x000D_
    }_x000D_
    _x000D_
  };_x000D_
_x000D_
  render(){_x000D_
    return(_x000D_
      <div>_x000D_
      New line with shift enter at any position<br />_x000D_
       <textarea _x000D_
       value={this.state.message}_x000D_
       ref={(input)=> this.input = input}_x000D_
       onChange={(e)=>this.setState({ message: e.target.value })}_x000D_
       onKeyDown={this.onKeyPress}/>_x000D_
      </div>_x000D_
    )_x000D_
  }_x000D_
}_x000D_
_x000D_
ReactDOM.render(<App />, document.getElementById('root'));
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>_x000D_
_x000D_
<div id='root'></div>
_x000D_
_x000D_
_x000D_


Another Solution for detecting Shift+Enter Key with Angular2+

Inside Component.html

<input type="text" (keydown.shift.enter)="newLine($event)">

Inside Component.ts

newLine(event){
      if(event.keyCode==13 && event.shiftKey){
        alert('Shift+Enter key Pressed');
      }
  }

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to jquery

How to make a variable accessible outside a function? Jquery assiging class to th in a table Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Getting all files in directory with ajax Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) bootstrap 4 file input doesn't show the file name Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource how to remove json object key and value.?

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width