Как мне определить «shift + enter» и создать новую строку в Textarea?

145

В настоящее время, если человек нажимает enterвнутри текстовой области, форма будет отправлена.
Хорошо, я этого хочу.

Но когда они набирают shift+ enter, я хочу, чтобы текстовая область переместилась на следующую строку:\n

Как я могу сделать это в JQueryпростом JavaScript или как можно проще?

TIMEX
источник
3
О, как я ненавижу такое изменившееся поведение ... ^^ Зачем ты это делаешь? Если вы напишите букву в слове, ожидаете ли вы сохранения текста в файле при нажатии клавиши ввода или она должна начинаться с новой строки?
Андреас
18
Я строю чат. Вот так скайп доу сидеть.
TIMEX
10
Проверьте для e.shiftKey.
Тайский
6
Все, что вам нужно сделать, это найти код, который не позволяет Enter отправить форму и проверить shiftKeyсвойство события .
Тим Даун
3
Сдвиг ENTER для новой строки в текстовом поле не является «измененным» поведением. Это было ожидаемое поведение в течение ослиных лет, для всех видов вещей. Я использовал это десятилетия назад, когда вводил текст в электронные таблицы.
Отдых на Кипре

Ответы:

81

Лучше использовать более простое решение:

Приведенное ниже решение Тима лучше, я предлагаю использовать это: https://stackoverflow.com/a/6015906/4031815


Мое решение

Я думаю, что вы можете сделать что-то вроде этого ..

РЕДАКТИРОВАТЬ: изменил код для работы независимо от положения каретки

Первая часть кода - получить позицию каретки.

Ссылка: Как получить позицию столбца каретки (не пикселей) в текстовой области, в символах, с самого начала?

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

И затем, заменяя значение textarea соответствующим образом, когда Shift+ Enterвместе, отправьте форму, если Enterнажата одна.

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

Вот демо

Джишну А.П.
источник
Это не сработает, если каретка не находится в конце содержимого текстовой области.
Тим Даун
Кроме того, есть опечатка (вы имеете в виду event.keyCode == 13), и я думаю, что вы также хотели, event.preventDefault()а не event.stopPropagation().
Тим Даун
Я изменил это. Теперь это будет работать независимо от положения каретки. И под этим event.stopPropagation()я намеревался остановить какой-то другой код, который он, возможно, написал для отправки формы.
Джишну А.П.
7
Эта функция положения каретки имеет недостатки (см. Мой комментарий и ответ на связанный вопрос о положении каретки), и вам все равно не требуется позиция каретки для этого. Смотрите мой ответ здесь. Re event.stopPropagation(), что позволит предотвратить событие из барботажных дальше вверх по DOM , но не будет мешать делать нажатие клавиши свое действие вставки разрыва строки по умолчанию (хотя на самом деле в keyupмоем предложении event.preventDefault()не будет делать что либо).
Тим Даун
2
Хотя он работал нормально, но выдавал ошибку, которая carentне определена, если я изменил его на каретный, он добавляет 2 новые строки
Аамир Махмуд
164

Простое и элегантное решение:

Во-первых, нажатие Enterвнутри текстовой области не отправляет форму, если у вас нет сценария, чтобы сделать это. Такое поведение ожидает пользователь, и я бы рекомендовал не менять его. Однако, если вы должны сделать это, самый простой подход - найти скрипт, который заставляет Enterотправить форму и изменить ее. Код будет иметь что-то вроде

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

... и вы можете просто изменить его на

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

С другой стороны, если по какой-то причине у вас нет доступа к этому коду, вам нужно сделать следующее, чтобы он работал во всех основных браузерах, даже если курсор не находится в конце текста:

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

Код:

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

Большинство из этих ответов усложняют это. Почему бы не попробовать это так?

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

Никаких проблем с положением каретки или разрывом линии толчка в JS. По сути, функция не будет работать, если нажата клавиша Shift, что позволяет клавише ввода / возврата выполнять свою обычную функцию.

Мэтт Гудвин
источник
Это именно то, что я хотел. Спасибо.
Таку Йоши
18

Почему не просто

$(".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
Вы можете просто использовать одно условие, например (event.keyCode == 13 &&! Event.shiftKey). Просто совет: если вы используете knockoutjs, вам нужно расфокусировать кулак textarea, чтобы обновить значение: jQuery (this) .blur ();
Джастин
4

Используйте плагин горячих клавиш JQuery и этот код

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

Вот решение AngularJS, использующее ng-keyup, если у кого-то есть такая же проблема с использованием AngularJS.

ng-keyup="$event.keyCode == 13 && !$event.shiftKey && myFunc()"
Tombery
источник
3

Используя ReactJS ES6, вот самый простой способ

shift+ enterНовая Линия в любой позиции

enter блокированный

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
источник
2

Я нашел эту ветку в поисках способа управления Shift + любой клавишей. Я склеил вместе другие решения, чтобы сделать эту комбинированную функцию для достижения того, что мне нужно. Я надеюсь, что это помогает кому-то еще.

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

В случае, если кто-то все еще задается вопросом, как это сделать без jQuery.

HTML

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

Javascript

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

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

Ваниль JS

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

textarea.addEventListener('keypress', function(e) {
    if(e.keyCode === 13 && !e.shiftKey) {
      e.preventDefault();
    }
})
Жако Ахмад
источник
1

Я использую div, добавляя contenteditable true вместо использования textarea.

Надежда может помочь вам.

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

Это работает для меня!

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

          $('form').submit();

    }
});
Mȍhǟmmǟd Șamȋm
источник
0

используя ng-keyupдирективу angularJS, только отправляете сообщение по нажатию Enterклавиши и Shift+Enterпросто занимает новую строку.

ng-keyup="($event.keyCode == 13&&!$event.shiftKey) ? sendMessage() : null"
Абдалла Окаша
источник