Wie erkenne ich "Shift + Enter" und generiere eine neue Zeile in Textarea?

145

Wenn die Person derzeit enterin den Textbereich drückt , wird das Formular gesendet.
Gut, das will ich.

Wenn sie jedoch shift+ entereingeben, soll der Textbereich in die nächste Zeile verschoben werden:\n

Wie kann ich das in JQueryoder einfach in JavaScript so einfach wie möglich machen?

TIMEX
quelle
3
Oh, wie ich solch verändertes Verhalten hasse ... ^^ Warum würdest du das tun? Wenn Sie einen Buchstaben in Wort schreiben, würden Sie erwarten, dass er den Text in einer Datei speichert, wenn Sie die Eingabetaste drücken, oder sollte er eine neue Zeile beginnen?
Andreas
18
Ich baue einen Chatraum. So sitzt Skype.
TIMEX
10
Überprüfen Sie auf e.shiftKey.
Thai
6
Sie müssen lediglich den Code finden, der verhindert, dass Enter das Formular sendet, und nach der shiftKeyEigenschaft des Ereignisses suchen .
Tim Down
3
Die Umschalttaste ENTER für eine neue Zeile in einem Textfeld wird nicht "geändert". Es wurde seit Eseljahren Verhalten für alle möglichen Dinge erwartet. Ich habe es vor Jahrzehnten verwendet, als ich Text in Tabellen eingegeben habe.
Entspannen in Zypern

Antworten:

81

Einfachere Lösung besser nutzen:

Tims Lösung unten ist besser. Ich schlage vor, diese zu verwenden: https://stackoverflow.com/a/6015906/4031815


Meine Lösung

Ich denke, Sie können so etwas tun ..

BEARBEITEN: Der Code wurde so geändert, dass er unabhängig von der Caret-Position funktioniert

Der erste Teil des Codes besteht darin, die Caret-Position zu ermitteln.

Ref: Wie wird die Position der Caret-Spalte (nicht der Pixel) in einem Textbereich in Zeichen von Anfang an ermittelt?

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; 
}

Wenn Sie dann den Textbereichswert entsprechend ersetzen, wenn Shift+ Enterzusammen, senden Sie das Formular, wenn Sie Enteralleine drücken.

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

Hier ist eine Demo

Jishnu AP
quelle
Das funktioniert nicht, wenn das Caret nicht am Ende des Inhalts des Textbereichs steht.
Tim Down
Außerdem gibt es einen Tippfehler (du meinst event.keyCode == 13) und ich denke, du wolltest wahrscheinlich auch event.preventDefault()eher als event.stopPropagation().
Tim Down
Ich habe es geändert. Jetzt funktioniert es unabhängig von der Caret-Position. Und damit wollte event.stopPropagation()ich einen anderen Code stoppen, den er möglicherweise geschrieben hat, um das Formular einzureichen.
Jishnu AP
7
Diese Caret-Positionsfunktion ist fehlerhaft (siehe meinen Kommentar und meine Antwort auf die Frage zur verknüpften Caret-Position), und Sie benötigen die Caret-Position sowieso nicht, um dies zu tun. Siehe meine Antwort hier. Dies verhindert event.stopPropagation(), dass das Ereignis weiter im DOM sprudelt, aber nicht, dass der Tastendruck seine Standardaktion zum Einfügen eines Zeilenumbruchs ausführt (obwohl dies in keyupmeinem Vorschlag event.preventDefault()auch nicht der Fall ist ).
Tim Down
2
Es hat zwar gut funktioniert, aber es gab einen Fehler, der carentnicht definiert ist. Wenn ich ihn in Caret ändere, werden 2 neue Zeilen
hinzugefügt
162

Einfache und elegante Lösung:

EnterWenn Sie in einem Textbereich drücken , wird das Formular nur gesendet, wenn Sie über ein Skript verfügen, das dies ermöglicht. Das ist das Verhalten, das der Benutzer erwartet, und ich würde empfehlen, es nicht zu ändern. Wenn Sie dies jedoch tun müssen, besteht der einfachste Ansatz darin, das Skript zu finden, mit dem Enterdas Formular gesendet wird, und es zu ändern. Der Code wird so etwas wie haben

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

... und Sie könnten es einfach ändern

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

Wenn Sie jedoch aus irgendeinem Grund keinen Zugriff auf diesen Code haben, müssen Sie die folgenden Schritte ausführen, damit er in allen gängigen Browsern funktioniert, auch wenn sich das Caret nicht am Ende des Textes befindet:

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);
Tim Down
quelle
42

Die meisten dieser Antworten erschweren dies. Warum versuchen Sie es nicht so?

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

Kein Herumspielen mit der Caret-Position oder dem Schieben der Schnur bricht in JS ein. Grundsätzlich wird die Funktion nicht ausgeführt, wenn die Umschalttaste gedrückt wird, sodass die Eingabe- / Eingabetaste ihre normale Funktion ausführen kann.

Matt Goodwin
quelle
Genau das wollte ich. Vielen Dank.
Taku Yoshi
18

Warum nicht einfach

$(".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
quelle
2
Sie können nur eine Bedingung wie (event.keyCode == 13 &&! Event.shiftKey) verwenden. Nur ein Tipp: Wenn Sie Knockoutjs verwenden, müssen Sie die Faust des Textbereichs aufheben, um den Wert zu aktualisieren: jQuery (this) .blur ();
Justin
4

Verwenden Sie das jQuery-Hotkeys- Plugin und diesen Code

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

Hier ist eine AngularJS-Lösung mit ng-keyup, wenn jemand das gleiche Problem mit AngularJS hat.

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

Die Verwendung von ReactJS ES6 ist hier der einfachste Weg

shift+ enterNeue Linie an einer beliebigen Position

enter verstopft

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>

Shrroy
quelle
2

Ich fand diesen Thread auf der Suche nach einer Möglichkeit, Shift + eine beliebige Taste zu steuern. Ich habe andere Lösungen zusammengefügt, um diese kombinierte Funktion zu erstellen und das zu erreichen, was ich brauchte. Ich hoffe es hilft jemand anderem.

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
quelle
1

Für den Fall, dass sich noch jemand fragt, wie dies ohne jQuery geschehen soll.

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
quelle
1

Ich benutze div, indem ich contenteditable true hinzufüge, anstatt textarea zu verwenden.

Hoffnung kann dir helfen.

$("#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
quelle
1

Das funktioniert bei mir!

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

          $('form').submit();

    }
});
Mȍhǟmmǟd Șamȋm
quelle
0

ng-keyupWenn Sie die Direktive in angleJS verwenden, senden Sie eine Nachricht nur beim Drücken der EnterTaste und Shift+Enternehmen nur eine neue Zeile ein.

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