184

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?

Shadow The GPT Wizard
  • 66,030
  • 26
  • 140
  • 208
TIMEX
  • 259,804
  • 351
  • 777
  • 1,080

19 Answers19

205

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);
Community
  • 1
  • 1
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • How do I distinguish left shift and right shift? Say, enter+left shift send message, enter+right shift clear message. I checked `event.location == KeyboardEvent.DOM_KEY_LOCATION_LEFT`, it doesn't work because when the key down, the key is Enter, not the shift, so it's always DOM_KEY_LOCATION_STANDARD. – Zhang Jun 11 '23 at 01:03
90

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

CommonSenseCode
  • 23,522
  • 33
  • 131
  • 186
Jishnu A P
  • 14,202
  • 8
  • 40
  • 50
  • That won't work if the caret is not at the end of the textarea's content. – Tim Down May 16 '11 at 10:03
  • Also, there's a typo (you mean `event.keyCode == 13`) and I think you probably also wanted `event.preventDefault()` rather than `event.stopPropagation()`. – Tim Down May 16 '11 at 11:01
  • I changed it. Now it'll work irrespective of caret position. And by `event.stopPropagation()` i meant to stop some other code which he may have written to submit the form. – Jishnu A P May 16 '11 at 12:23
  • 7
    That caret position function is flawed (see my comment and answer on the linked caret position question), and you don't need the caret position to do this anyway. See my answer here. Re `event.stopPropagation()`, that will prevent the event from bubbling further up the DOM but will not prevent the keypress from doing its default action of inserting a line break (although actually in `keyup` my suggestion of `event.preventDefault()` won't do that either). – Tim Down May 17 '11 at 11:31
  • 2
    Although it worked fine, but it gave error that `carent` is not defined, if i change it to caret it adds 2 new lines – Aamir Mahmood Aug 14 '12 at 18:54
  • `getCaret` function can be replaced by this library - https://github.com/timdown/rangy – Oleg Abrazhaev Aug 24 '18 at 13:15
  • @JishnuAP also gets an error that `carent is not defined` – SeaBass Sep 22 '19 at 07:30
52

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.

Matthew Goodwin
  • 1,162
  • 12
  • 16
20

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
    }
});
Liam Hall
  • 217
  • 3
  • 9
  • 2
    You can just use one condition like (event.keyCode == 13 && !event.shiftKey). Just a tip: if you use knockoutjs, you need to unfocus the textarea fist to update the value: jQuery(this).blur(); – Justin May 20 '13 at 10:20
  • you are the man for "stops enter from creating a new line" :) – Orhan Gazi Nov 02 '20 at 21:49
4

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

ng-keyup="$event.keyCode == 13 && !$event.shiftKey && myFunc()"
Tombery
  • 266
  • 2
  • 15
4

Using ReactJS ES6 here's the simplest way

shift + enter New Line at any position

enter Blocked

class App extends React.Component {

 constructor(){
    super();
    this.state = {
      message: 'Enter is blocked'
    }
  }
  onKeyPress = (e) => {
     if (e.keyCode === 13 && e.shiftKey) {
        e.preventDefault();
        let start = e.target.selectionStart,
            end = e.target.selectionEnd;
        this.setState(prevState => ({ message:
            prevState.message.substring(0, start)
            + '\n' +
            prevState.message.substring(end)
        }),()=>{
            this.input.selectionStart = this.input.selectionEnd = start + 1;
        })
    }else if (e.keyCode === 13) { // block enter
      e.preventDefault();
    }
    
  };

  render(){
    return(
      <div>
      New line with shift enter at any position<br />
       <textarea 
       value={this.state.message}
       ref={(input)=> this.input = input}
       onChange={(e)=>this.setState({ message: e.target.value })}
       onKeyDown={this.onKeyPress}/>
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id='root'></div>
Liam
  • 6,517
  • 7
  • 25
  • 47
4

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;
         }
);
Thariama
  • 50,002
  • 13
  • 138
  • 166
2

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));
    });
});
Spencer Sullivan
  • 527
  • 6
  • 13
2

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
    }
  }
})
Hsinhsin Hung
  • 343
  • 1
  • 2
  • 12
2

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');
      }
  }
2

This code works perfectly fine for my purpose

document.getElementById('text').addEventListener('keypress', (e) => {
  if (e.key == 'Enter' && !e.shiftKey) {
    e.preventDefault()
    console.log('your code goes here');
  }
  if (e.key == 'Enter' && e.shiftKey) {
    e.preventDefault();
    console.log("insertLineBreak");
    const txtArea = document.getElementById('text');
    txtArea.value += '\r\n';
  }
})
Elliot404
  • 127
  • 2
  • 3
2

And jquery example

$.fn.pressEnter = function(fn) {
    return this.each(function() {  
        $(this).bind('enterPress', fn);
        $(this).keyup(function(e){
        
            /*When SHIFT return false*/
            if(e.shiftKey==true) return false;

            if(e.keyCode == 13)
            {
              /*You can do the thing on ENTER*/
              alert('Enter press');
            }

        })
    });  
}; 
$('.exampleClass').pressEnter(function(){})
div{
  width:200px;
  height:100px;
  border:solid 1px #000;
  float:left;
}
textarea{
  width:200px;
  height:100px;
  border:solid 1px #000;
  float:right;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="exampleClass" contenteditable></div>

<textarea  class="exampleClass"></textarea>
Tsolov
  • 79
  • 5
1

This works for me!

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

          $('form').submit();

    }
});
Mȍhǟmmǟd Șamȋm
  • 261
  • 1
  • 4
  • 14
0

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"
Abdallah Okasha
  • 1,879
  • 17
  • 20
0

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();
    }
})
Jaco Ahmad
  • 43
  • 7
0

I know this is an old question, but I wanted to toss in an implicit observation that some might want to consider if using Shift + A-Z.

document.onkeydown = (k) => {
  if (k.key === "Q") {
    console.log("Shift + Q");
  }
}

You can check for a key by its case, like "Q" or "q". If doing the former, then it's implied that Shift is being pressed since it's a capital letter.

One bug here where functionality is concerned is if CapsLock is on. But if, like me, you're utilizing it in a personal script, then it's not really a big deal.

Another potential benefit might be "hiding" an explicit condition looking for the Shift key to be pressed. This is admittedly a half-baked suggestion, though.

dsasmblr
  • 113
  • 6
0

Some complicated solutions sending \n are not necessary.
On keydown event just return the key 13 if shift is pressed

​$("#mytestarea").keydown(function (e) {
   ​
   ​if (e.keyCode == 13) { // Enter pressed
       //No shift or alt or ctrl
       ​if (!e.shiftKey && !e.altKey && !e.ctrlKey) {
           ​SendMsg(); // or submit or what you wan't
       ​}
       ​if (e.shiftKey) {
           //replace the shift for keycode 13 only
           ​return 13;
       ​}
                   ​
       ​//method to prevent from default behaviour
       ​e.preventDefault();
   ​}
});
Rui Caramalho
  • 455
  • 8
  • 16
0
<input type="text" onkeydown="handleMessageKeydown" /> 

or some content editable element:

<div contenteditable="true" onchange="handleMessageKeydown" />

handleMessageKeydown(e) {
      if (!e.shiftKey && e.key === "Enter") {
          e.preventDefault()
          sendMessage()
      }
 }

if shift is pressed with enter then it will create new lines otherwise it will fall inside the if condition given above. Inside the if condition, the e.preventDefault() line is the most important. For a keydown event handler, the e.preventDefault() stops running the operation so that u can perform your own operations like sending messages to server etc.

Baraja Swargiary
  • 381
  • 2
  • 10
0

Here is the best way to do

  if (e.key === 'Enter') {
    console.log('enter');
  }
  if (e.key === 'Enter' && e.ctrlKey) {
    console.log('clt+enter');
  }
  if (e.key === 'Enter' && e.ctrlKey && e.shiftKey) {
    console.log('clt+shift+enter');
  }
kumbhani bhavesh
  • 2,189
  • 1
  • 15
  • 26