Clique no botão Enter triggers

168

Eu tenho uma página com dois botões. Um é um <button>elemento e o outro é um <input type="submit">. Os botões aparecem na página nessa ordem. Se eu estiver em um campo de texto em qualquer lugar do formulário e pressionar <Enter>, o clickevento do elemento button será acionado. Presumo que é porque o elemento button fica em primeiro lugar.

Não consigo encontrar nada que pareça uma maneira confiável de definir o botão padrão, nem quero necessariamente neste momento. Na ausência de algo melhor, capturei uma tecla pressionada em qualquer lugar do formulário e, se foi a <Enter>tecla pressionada, estou negando:

$('form').keypress( function( e ) {
  var code = e.keyCode || e.which;

  if( code === 13 ) {
    e.preventDefault();
    return false; 
  }
})

Até onde eu sei até agora, parece estar funcionando, mas parece incrivelmente maluco.

Alguém conhece uma técnica mais sofisticada para fazer isso?

Da mesma forma, existem armadilhas para esta solução das quais simplesmente não estou ciente?

Obrigado.

Rob Wilkerson
fonte
1
Isso pode acontecer ao usar formas reativas angulares também, não apenas úteis para JQuery, mas também para desenvolvimento angular.
HDJEMAI

Respostas:

362

Usando

<button type="button">Whatever</button>

deve fazer o truque.

O motivo é que um botão dentro de um formulário tem seu tipo definido implicitamente submit. Como diz o zzzzBoz, o Spec diz que o primeiro buttonou o inputcom type="submit"é o que é acionado nessa situação. Se você definir especificamente type="button", ele será removido de consideração pelo navegador.

Cachorro Louco
fonte
1
doce, obrigado, parece botões no IE8 para eu capturar <enter> cliques, type="button"parece resolver isso ... Obrigado! ps alguma idéia de por que isso é? ie8 tratando botões como tipo enviar? Esquisito.
Quang Van
3
Boa resposta, isso indica ao navegador quais botões não são botões de envio, para que ele possa fazer a coisa certa sem reordenar a marcação.
quer
2
A resposta de @ Leinster cobre o motivo dessa peculiaridade - "Um botão sem atributo de tipo é tratado da mesma forma que um botão com seu tipo definido para envio".
Balde
2
O mesmo se aplica a <input type="submit"/>(acionará o clique) e <input type="button"/>(não acionará o clique) #
Marius Balčytis 10/04
1
Inacreditável!! Eu estava tão confuso.
Margus Pala
54

É importante ler as especificações HTML para entender realmente qual é o comportamento esperado:

A especificação HTML5 afirma explicitamente o que acontece emimplicit submissions :

O botão padrão de um elemento do formulário é o primeiro botão de envio em ordem de árvore cujo proprietário do formulário é esse elemento do formulário.

Se o agente do usuário suportar permitir que o usuário envie um formulário implicitamente (por exemplo, em algumas plataformas, pressionando a tecla "enter" enquanto um campo de texto estiver focado no envio implicitamente do formulário), faça isso para um formulário cujo botão padrão tenha uma ativação definida o comportamento deve fazer com que o agente do usuário execute etapas de ativação de clique sintético nesse botão padrão.

Isso não foi explicitado na especificação HTML4, no entanto, os navegadores já estão implementando o que é descrito na especificação HTML5 (e é por isso que é incluído explicitamente).

Edite para adicionar:

A resposta mais simples que consigo pensar é colocar o botão de envio como o primeiro [type="submit"]item no formulário, adicionar preenchimento na parte inferior do formulário com css e posicionar absolutamente o botão de envio na parte inferior, onde você desejar.

zzzzBov
fonte
Lá estava eu ​​xingando o IE, e foi a minha marcação desleixada o tempo todo! Felicidades!
Shawson
2
Uau ... Obrigado, bom senhor. Esta foi uma descoberta acidental. Eu não podia sequer entender por que um evento de clique estava sendo demitido de bater a tecla enter, mas a sua cotação me levou a w3.org/TR/html5/forms.html#implicit-submission
chemoish
O link está quebrado. Eu acho que o w3c.github.io/html/sec-forms.html#implicit-submission é o novo URL.
TJ.
22

Eu não acho que você precise de javascript ou CSS para corrigir isso.

De acordo com a especificação html 5 para botões, um botão sem atributo de tipo é tratado da mesma forma que um botão com seu tipo definido como "enviar", ou seja, como um botão para enviar seu formulário. Definir o tipo do botão como "botão" deve impedir o comportamento que você está vendo.

Não tenho certeza sobre o suporte ao navegador para isso, mas o mesmo comportamento foi especificado na especificação html 4.01 para botões, então espero que seja muito bom.

Leinster
fonte
13

Ao pressionar 'Enter' no foco, <input type="text">você aciona o evento 'click' no primeiro elemento posicionado: <button>ou <input type="submit">. Se você pressionar 'Enter' <textarea>, basta criar uma nova linha de texto.

Veja o exemplo aqui .

Seu código impede a inserção de uma nova linha de texto <textarea>, portanto, você deve pressionar apenas a tecla <input type="text">.

Mas por que você precisa pressionar Enterno campo de texto? Se você deseja enviar o formulário pressionando 'Enter', mas ele <button>deve permanecer o primeiro no layout, basta brincar com a marcação: coloque o <input type="submit">código antes do <button>e use CSS para salvar o layout necessário.

Capturando 'Enter' e salvando a marcação:

$('input[type="text"]').keypress(function (e) {
    var code = e.keyCode || e.which;
    if (code === 13)
    e.preventDefault();
    $("form").submit(); /*add this, if you want to submit form by pressing `Enter`*/
});
Feniks502
fonte
A instrução if não deveria ter um suporte para executar as duas instruções somente quando enter for pressionado? Caso contrário, o envio acontecerá a cada pressionamento de tecla. Lembra-me de ir a falhar. :)
danmiser
13

Onde quer que você use um <button>elemento por padrão, ele considera esse botão; type="submit"portanto, se você definir o botão type="button", ele não será considerado <button>como botão de envio.

Ram Thota
fonte
2

Pressionar enter no campo de texto de um formulário enviará, por padrão, o formulário. Se você não deseja que ele funcione dessa maneira, é necessário capturar a tecla Enter e consumi-la como você fez. Não há como contornar isso. Funcionará dessa maneira, mesmo se não houver um botão presente no formulário.

Sparafusile
fonte
4
Eu não acho que o problema é que os submete o formulário, é que desencadeia a clickação na elementos de botão desejo é uma consequência não intencional
Martin Jespersen
Você está certo. De qualquer forma, o resultado é o mesmo - você precisa capturar a tecla Enter para impedir o envio de formulários indesejados.
Sparafusile
2

Você pode usar o javascript para bloquear o envio do formulário até o momento apropriado. Um exemplo muito grosseiro:

<form onsubmit='return false;' id='frmNoEnterSubmit' action="index.html">

    <input type='text' name='txtTest' />

    <input type='button' value='Submit' 
        onclick='document.forms["frmNoEnterSubmit"].onsubmit=""; document.forms["frmNoEnterSubmit"].submit();' />

</form>

Pressionar enter ainda acionará o formulário a ser enviado, mas o javascript impedirá que ele realmente seja enviado até que você realmente pressione o botão.

Dave
fonte
2

Exemplo Dom

  <button onclick="anotherFoo()"> Add new row</button>
  <input type="text" name="xxx" onclick="foo(event)">

javascript

function foo(event){
   if(event.which == 13 || event.keyCode == 13) // for crossbrowser
   {
     event.preventDefault(); // this code prevents other buttons triggers use this
     // do stuff
   }
}

function anotherFoo(){
  // stuffs.
}

se você não usar preventDefault (), outros botões serão acionados.

Mehmet Ali Kuş
fonte
0

Eu faria o seguinte: No manipulador do evento onclick do botão (não enviar), verifique o código-chave do objeto de evento. Se for "enter" eu retornaria false.

Satyajit
fonte
Esse código de chave está sempre sendo passado como se fosse um clique. Ai que está o problema. :-)
Rob Wilkerson
Então eu acho que você faz da maneira mais difícil - lida com o evento onkeydown no botão também. O manipulador receberá um keyEvent; verifique o keyCode -> se 13, preventDefault. Dessa forma, você pode realmente permitir que os usuários pressionem enter nesse botão, sem o efeito colateral de executar o evento click.
precisa saber é o seguinte
0

Minha situação possui dois Submitbotões no elemento do formulário: Updatee Delete. O Deletebotão exclui uma imagem e oUpdate atualiza o banco de dados com os campos de texto no formulário.

Como o Deletebotão foi o primeiro no formulário, foi o botão padrão na Entertecla. Não é o que eu queria. O usuário esperaria poder baterEnter após alterar alguns campos de texto.

Encontrei minha resposta para definir o botão padrão aqui :

<form action="/action_page.php" method="get" id="form1">
  First name: <input type="text" name="fname"><br>
  Last name: <input type="text" name="lname"><br>
</form>
<button type="submit" form="form1" value="Submit">Submit</button>

Sem usar nenhum script, defini o formulário ao qual cada botão pertence ao uso do <button> form="bla"atributo Defino o Deletebotão para um formulário que não existe e defino o Updatebotão que eu queria acionar na Enterchave para o formulário em que o usuário estaria ao inserir texto.

Esta é a única coisa que funcionou para mim até agora.

Dan Vachon
fonte
1
Por favor, verifique como responder no stackoverflow
Morse
0

Você pode fazer algo assim.

vincule seu evento a uma função comum e chame o evento com pressionamento de tecla ou clique no botão.

por exemplo.

function callME(event){
    alert('Hi');
}



$('button').on("click",callME); 
$('input ').keypress(function(event){
  if (event.which == 13) {
    callME(event);
  }
});
newbdeveloper
fonte
-1

Adicionei um botão do tipo "enviar" como primeiro elemento do formulário e o tornei invisível ( width:0;height:0;padding:0;margin:0;border-style:none;font-size:0;). Funciona como uma atualização do site, ou seja, não faço nada quando o botão é pressionado, exceto que o site é carregado novamente. Para mim funciona bem ...

torabe
fonte