Як я можу виявити "shift + enter" та створити новий рядок у Textarea?


145

Наразі, якщо людина натисне enterвсередині текстової області, форма подається.
Добре, я хочу цього.

Але коли вони вводять shift+ enter, я хочу, щоб textarea перейшла до наступного рядка:\n

Як я можу зробити це в JQueryпростому JavaScript якомога простішим?


3
О, як я ненавиджу таку змінену поведінку ... ^^ Навіщо ти це робив? Якщо ви пишете лист словом, чи очікуєте, що він збереже текст у файлі під час натискання клавіші "Введення" чи має розпочати новий рядок?
Андреас

18
Я будую кімнату чату. Ось як сидять скайп.
TIMEX

10
Перевірте e.shiftKey.
Тайська

6
Все, що вам потрібно зробити - це знайти код, який заважає Enter надіслати форму та перевірити shiftKeyвластивість події .
Тім Даун

3
Shift ENTER для нового рядка в текстовому полі не змінюється. Очікувана поведінка протягом років ослів, до всіляких речей. Я використовував це десятиліття тому, коли вводив текст у електронні таблиці.
Відпочинок на Кіпрі

Відповіді:


81

Краще використовувати більш просте рішення:

Рішення Тіма нижче, я краще пропоную скористатися цим: https://stackoverflow.com/a/6015906/4031815


Моє рішення

Я думаю, ти можеш зробити щось подібне ..

EDIT: Змінено код на роботу незалежно від положення карети

Перша частина коду - це отримати позицію каре.

Ref: Як отримати положення стовпця карет (не пікселів) у текстовій області, символами, з самого початку?

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

Ось демонстрація


Це не спрацює, якщо карета не знаходиться в кінці вмісту textarea.
Тім Даун

Крім того, є друкарська помилка (ви маєте на увазі event.keyCode == 13), і я думаю, ви, мабуть, теж хотіли, event.preventDefault()а не event.stopPropagation().
Тім Даун

Я це змінив. Тепер він працюватиме незалежно від положення карети. І event.stopPropagation()я мав намір зупинити якийсь інший код, який він, можливо, написав, щоб подати форму.
Jishnu AP

7
Ця функція позиції каретки є помилковою (див. Мій коментар та відповідь на пов'язане питання щодо позиції каретки), і вам не потрібно це положення каретки для цього. Дивіться мою відповідь тут. Зрештою 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. В основному, функція не буде працювати, якщо натискати клавішу зсуву, тому дозволяючи клавіші введення / повернення виконувати свою звичайну функцію.


Це саме те, що я хотів. Дякую.
Taku Yoshi

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 ();
Джастін


3

Ось рішення AngularJS з використанням ng-keyup, якщо хтось має таку ж проблему, що використовує AngularJS.

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

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>


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

    }
});

0

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

ng-keyup="($event.keyCode == 13&&!$event.shiftKey) ? sendMessage() : null"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.