如何检测“shift+enter”并在 Textarea 中生成新行?

Posted

技术标签:

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

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

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

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

【问题讨论】:

您能告诉我们您当前的代码吗? 我正在建立一个聊天室。 Skype 就是这样坐的。 检查e.shiftKey 您需要做的就是找到阻止 Enter 提交表单的代码并检查事件的 shiftKey 属性。 Shift ENTER 在文本字段中换行不是“更改”行为。这是驴子多年以来的预期行为,对于各种各样的事情。几十年前我在电子表格中输入文本时使用过它。 【参考方案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://***.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() 停止运行操作,以便您可以执行自己的操作,例如向服务器发送消息等。

【讨论】:

以上是关于如何检测“shift+enter”并在 Textarea 中生成新行?的主要内容,如果未能解决你的问题,请参考以下文章

如何只允许 shift+enter 在文本区域中返回新行?

软回车(shift+enter)与硬回车(enter)区别

使用 Shift + Enter 键运行函数

Adobe Animate (Flash):在调试 (Ctrl+Shift+Enter) 中违反安全沙箱,但在测试中违反 (Ctrl+Enter)

RobotFramework:SHIFT+ENTER 组合按键 SeleniumLibrary

Anaconda Spyder快捷键Ctrl + Enter和Shift + Enter不起作用