【问题标题】:How do I detect "shift+enter" and generate a new line in Textarea?如何检测“shift+enter”并在 Textarea 中生成新行?
【发布时间】:2011-08-26 06:16:28
【问题描述】:

目前,如果用户在文本区域内按enter,表单将提交。
很好,我想要那个。

但是当他们键入 shift + enter 时,我希望 textarea 移动到下一行:\n

如何在 JQuery 或纯 JavaScript 中尽可能简单地做到这一点?

【问题讨论】:

  • 您能告诉我们您当前的代码吗?
  • 我正在建立一个聊天室。 Skype 就是这样坐的。
  • 检查e.shiftKey
  • 您需要做的就是找到阻止 Enter 提交表单的代码并检查事件的 shiftKey 属性。
  • Shift ENTER 在文本字段中换行不是“更改”行为。这是驴子多年以来的预期行为,对于各种各样的事情。几十年前我在电子表格中输入文本时使用过它。

标签: javascript jquery html css


【解决方案1】:

简单优雅的解决方案:

首先,在 textarea 中按 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);

【讨论】:

    【解决方案2】:

    最好使用更简单的解决方案:

    以下 Tim 的解决方案更好,我建议使用它: https://stackoverflow.com/a/6015906/4031815


    我的解决方案

    我认为你可以做这样的事情..

    编辑:更改了代码以使其与插入符号位置无关

    代码的第一部分是获取插入符号的位置。

    参考: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; 
    }
    

    然后当Shift + Enter一起替换textarea值,如果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();
            }
        }
    });
    

    这是demo

    【讨论】:

    • 如果插入符号不在文本区域内容的末尾,那将不起作用。
    • 另外,还有一个错字(你的意思是event.keyCode == 13),我想你可能还想要event.preventDefault()而不是event.stopPropagation()
    • 我改了。现在无论插入符号位置如何,它都可以工作。通过event.stopPropagation(),我的意思是停止他可能为提交表单而编写的一些其他代码。
    • 插入符号位置功能存在缺陷(请参阅我对链接插入符号位置问题的评论和回答),无论如何您都不需要插入符号位置来执行此操作。在这里查看我的答案。回复event.stopPropagation(),这将防止事件在DOM 中进一步冒泡,但不会阻止按键执行其插入换行符的默认操作(尽管实际上在keyup 我对event.preventDefault() 的建议不会那样做要么)。
    • 虽然它工作正常,但它给出了 carent 未定义的错误,如果我将它更改为插入符号,它会添加 2 个新行
    【解决方案3】:

    这些答案中的大多数都过于复杂了。为什么不这样尝试呢?

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

    没有乱七八糟的插入符号位置或推线插入 JS。基本上,如果按下 shift 键,该功能将不会运行,因此允许 enter/return 键执行其正常功能。

    【讨论】:

    • 这正是我想要的。谢谢。
    【解决方案4】:

    为什么不直接

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

    【讨论】:

    • 您可以只使用一种条件,例如 (event.keyCode == 13 && !event.shiftKey)。提示:如果你使用knockoutjs,你需要将textarea拳头散开来更新值:jQuery(this).blur();
    • 你是“停止进入创建新行”的人:)
    【解决方案5】:

    如果有人在使用 AngularJS 时遇到同样的问题,这里是使用 ng-keyup 的 AngularJS 解决方案。

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

    【讨论】:

      【解决方案6】:

      使用jQuery hotkeys 插件和此代码

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

      【讨论】:

        【解决方案7】:

        这里使用 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>

        【讨论】:

          【解决方案8】:

          我发现这个帖子正在寻找一种控制 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));
              });
          });
          

          【讨论】:

            【解决方案9】:

            我通过添加 contenteditable true 来使用 div,而不是使用 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
                }
              }
            })
            

            【讨论】:

              【解决方案10】:

              Angular2+检测Shift+Enter键的另一种解决方案

              Component.html 内部

              &lt;input type="text" (keydown.shift.enter)="newLine($event)"&gt;

              Component.ts 内部

              newLine(event){
                    if(event.keyCode==13 && event.shiftKey){
                      alert('Shift+Enter key Pressed');
                    }
                }
              

              【讨论】:

                【解决方案11】:

                如果有人仍然想知道如何在没有 jQuery 的情况下做到这一点。

                HTML

                &lt;textarea id="description"&gt;&lt;/textarea&gt;

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

                【讨论】:

                  【解决方案12】:

                  这对我有用!

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

                  【讨论】:

                    【解决方案13】:

                    和 jquery 的例子

                    $.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>

                    【讨论】:

                      【解决方案14】:

                      在 angularJS 中使用ng-keyup 指令,仅在按下Enter 键时发送消息,Shift+Enter 将换行。

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

                      【讨论】:

                        【解决方案15】:

                        这段代码非常适合我的目的

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

                        【讨论】:

                          【解决方案16】:

                          我知道这是一个老问题,但我想抛出一个隐含的观察,如果使用 Shift + A-Z,有些人可能会考虑。

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

                          您可以按大小写检查密钥,例如"Q""q"。如果是前者,则暗示 Shift 被按下,因为它是一个大写字母。

                          这里涉及功能的一个错误是CapsLock 是否打开。但是,如果您像我一样在个人脚本中使用它,那么这并不是什么大不了的事。

                          另一个潜在的好处可能是“隐藏”一个明确的条件,寻找要按下的Shift 键。不过,这无疑是一个不成熟的建议。

                          【讨论】:

                            【解决方案17】:

                            一些复杂的解决方案发送\n 是不必要的。
                            keydown 事件上,如果按下 shift 键,只需返回键 13

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

                            【讨论】:

                              【解决方案18】:
                              <input type="text" onkeydown="handleMessageKeydown" /> 
                              

                              或一些内容可编辑的元素:

                              <div contenteditable="true" onchange="handleMessageKeydown" />
                              
                              handleMessageKeydown(e) {
                                    if (!e.shiftKey && e.key === "Enter") {
                                        e.preventDefault()
                                        sendMessage()
                                    }
                               }
                              

                              如果用回车键按下 shift 那么它将创建新行,否则它将落在上面给出的 if 条件内。在 if 条件中,e.preventDefault() 行是最重要的。对于 keydown 事件处理程序,e.preventDefault() 停止运行操作,以便您可以执行自己的操作,例如向服务器发送消息等。

                              【讨论】:

                                猜你喜欢
                                • 1970-01-01
                                • 2017-12-04
                                • 2011-11-12
                                • 1970-01-01
                                • 1970-01-01
                                • 2015-12-12
                                • 2010-10-10
                                • 2017-01-22
                                相关资源
                                最近更新 更多