Come posso rilevare "shift + enter" e generare una nuova riga in Textarea?


145

Attualmente, se la persona preme enterall'interno dell'area di testo, il modulo verrà inviato.
Bene, lo voglio.

Ma quando digitano shift+ enter, voglio che l'area di testo passi alla riga successiva:\n

Come posso farlo in JQueryJavaScript o nel modo più semplice possibile?


3
Oh, come odio un comportamento così cambiato ... ^^ Perché dovresti farlo? Se scrivi una lettera in parola, ti aspetteresti che salvi il testo in un file quando premi Invio o dovrebbe iniziare una nuova riga?
Andreas,

18
Sto costruendo una chat room. Ecco come siedono Skype.
TIMEX,

10
Controlla per e.shiftKey.
Thai

6
Tutto quello che devi fare è trovare il codice che impedisce a Enter di inviare il modulo e verificare la shiftKeyproprietà dell'evento .
Tim Down,

3
Maiusc INVIO per una nuova riga in un campo di testo non è un comportamento "modificato". È stato previsto un comportamento per gli anni dell'asino, per ogni sorta di cose. L'ho usato decenni fa quando ho inserito del testo nei fogli di calcolo.
Rilassarsi a Cipro

Risposte:


81

Utilizzare meglio la soluzione più semplice:

La soluzione di Tim qui sotto è migliore, suggerisco di usarla: https://stackoverflow.com/a/6015906/4031815


La mia soluzione

Penso che tu possa fare qualcosa del genere ..

EDIT: modificato il codice per funzionare indipendentemente dalla posizione del cursore

La prima parte del codice è quella di ottenere la posizione del cursore.

Rif: Come ottenere la posizione della colonna del cursore (non dei pixel) in un'area di testo, in caratteri, dall'inizio?

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

Quindi, sostituendo il valore textarea di conseguenza quando Shift+ Enterinsieme, invia il modulo se Enterviene premuto da solo.

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

Ecco una demo


Ciò non funzionerà se il cursore non si trova alla fine del contenuto della textarea.
Tim Down,

Inoltre, c'è un refuso (intendi event.keyCode == 13) e penso che probabilmente anche tu volevi event.preventDefault()piuttosto che event.stopPropagation().
Tim Down,

L'ho cambiato. Ora funzionerà indipendentemente dalla posizione del cursore. E event.stopPropagation()intendevo fermare qualche altro codice che potrebbe aver scritto per inviare il modulo.
Jishnu AP,

7
La funzione di posizione del punto di inserimento è imperfetta (vedere il mio commento e la risposta sulla domanda di posizione di punto di inserimento collegata) e non è comunque necessario che la posizione di punto di inserimento venga eseguita. Vedi la mia risposta qui. Ri event.stopPropagation(), ciò impedirà all'evento di gorgogliare ulteriormente il DOM ma non impedirà al keypress di fare la sua azione predefinita di inserimento di un'interruzione di riga (anche se in realtà nel keyupmio suggerimento di event.preventDefault()non farlo neanche).
Tim Down,

2
Anche se ha funzionato bene, ma ha dato un errore che carentnon è definito, se lo cambio in modo da aggiungere un punto, aggiunge 2 nuove righe
Aamir Mahmood

164

Soluzione semplice ed elegante:

Innanzitutto, premendo Enterall'interno di un'area di testo non si invia il modulo a meno che non si disponga di uno script per farlo. Questo è il comportamento che l'utente si aspetta e sconsiglio di cambiarlo. Tuttavia, se è necessario farlo, l'approccio più semplice sarebbe quello di trovare lo script che sta facendo Enterinviare il modulo e modificarlo. Il codice avrà qualcosa di simile

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

... e potresti semplicemente cambiarlo in

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

D'altra parte, se non hai accesso a questo codice per qualche motivo, devi fare quanto segue per farlo funzionare in tutti i principali browser anche se il cursore non è alla fine del testo:

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

Codice:

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

42

La maggior parte di queste risposte è complicata. Perché non provarlo in questo modo?

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

Non si scherza con la posizione del cursore o la linea di spinta si interrompe in JS. Fondamentalmente, la funzione non funzionerà se si preme il tasto Maiusc, consentendo quindi al tasto Invio / Ritorno di svolgere la sua normale funzione.


Questo è esattamente quello che volevo. Grazie.
Taku Yoshi,

18

Perché non solo

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

2
Puoi semplicemente usare una condizione come (event.keyCode == 13 &&! Event.shiftKey). Un consiglio: se usi knockoutjs, devi sfocare il pugno di textarea per aggiornare il valore: jQuery (this) .blur ();
Giustino,

4

Utilizzare il plug-in di scelta rapida jQuery e questo codice

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

3

Ecco una soluzione AngularJS che utilizza ng-keyup se qualcuno ha lo stesso problema con AngularJS.

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

3

Utilizzando ReactJS ES6 ecco il modo più semplice

shift+ enterNuova linea in qualsiasi posizione

enter bloccato

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>


2

Ho trovato questo thread alla ricerca di un modo per controllare Maiusc + qualsiasi tasto. Ho incollato insieme altre soluzioni per rendere questa funzione combinata per realizzare ciò di cui avevo bisogno. Spero che aiuti qualcun altro.

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

1

Nel caso qualcuno si stia ancora chiedendo come farlo senza 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();
    }
})

1

Uso div aggiungendo true contenteditable invece di usare textarea.

La speranza può aiutarti.

$("#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
    }
  }
})

1

Questo funziona per me!

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

          $('form').submit();

    }
});

0

utilizzando ng-keyup direttiva in angularJS, invia un messaggio solo premendo il Entertasto e Shift+Enterprenderà semplicemente una nuova riga.

ng-keyup="($event.keyCode == 13&&!$event.shiftKey) ? sendMessage() : null"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.