Haga clic en el botón de disparadores

168

Tengo una página con dos botones. Uno es un <button>elemento y el otro es un <input type="submit">. Los botones aparecen en la página en ese orden. Si estoy en un campo de texto en cualquier parte del formulario y presiono <Enter>, clickse activa el evento del elemento del botón . Supongo que es porque el elemento del botón se encuentra primero.

No puedo encontrar nada que parezca una forma confiable de configurar el botón predeterminado, ni quiero necesariamente en este punto. En ausencia de algo mejor, capturé una tecla <Enter>presionada en cualquier parte del formulario y, si se presionó la tecla, simplemente la estoy negando:

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

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

Por lo que puedo decir hasta ahora, parece estar funcionando, pero se siente increíblemente duro.

¿Alguien sabe de una técnica más sofisticada para hacer esto?

Del mismo modo, ¿hay alguna dificultad en esta solución de la que simplemente no sea consciente?

Gracias.

Rob Wilkerson
fuente
1
Esto puede suceder también cuando se usan formas reactivas angulares, no solo útiles para JQuery, sino también para el desarrollo angular.
HDJEMAI

Respuestas:

362

Utilizando

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

debería hacer el truco.

La razón es porque un botón dentro de un formulario tiene su tipo implícitamente establecido en submit. Como dice zzzzBoz, la Especificación dice que lo primero buttono inputcon type="submit"lo que se desencadena en esta situación. Si configura específicamente type="button", el navegador lo elimina de la consideración.

Perro rabioso
fuente
1
dulce, gracias, parece botones en IE8 para mí capturando <enter> clics, type="button"parece resolver esto ... ¡Gracias! ps alguna idea de por qué es esto? ie8 tratando botones como tipo enviar? Extraño.
Quang Van
3
Buena respuesta, esto sugiere al navegador qué botones no son botones de envío, por lo que puede hacer lo correcto sin reordenar el marcado.
Don Spaulding
2
La respuesta de @ Leinster cubre la razón de esta peculiaridad: "Un botón sin atributo de tipo se trata igual que un botón con su tipo configurado para enviar".
Cubo el
2
Lo mismo se aplica para <input type="submit"/>(activará el clic) y <input type="button"/>(no activará el clic)
Marius Balčytis
1
¡¡Increíble!! Estaba muy confundido.
Margus Pala
54

Es importante leer las especificaciones HTML para comprender realmente qué comportamiento es de esperar:

La especificación HTML5 establece explícitamente lo que sucede enimplicit submissions :

El botón predeterminado de un elemento de formulario es el primer botón de envío en orden de árbol cuyo propietario de formulario es ese elemento de formulario.

Si el agente de usuario admite permitir que el usuario envíe un formulario implícitamente (por ejemplo, en algunas plataformas presionando la tecla "enter" mientras un campo de texto está enfocado, envía implícitamente el formulario), y luego lo hace para un formulario cuyo botón predeterminado tiene una activación definida El comportamiento debe hacer que el agente de usuario ejecute pasos de activación de clic sintético en ese botón predeterminado.

Esto no se hizo explícito en la especificación HTML4, sin embargo, los navegadores ya han implementado lo que se describe en la especificación HTML5 (por lo que se incluye explícitamente).

Editar para agregar:

La respuesta más simple que se me ocurre es colocar el botón de enviar como el primer [type="submit"]elemento del formulario, agregar relleno al final del formulario con css y colocar el botón de enviar en la parte inferior donde lo desee.

zzzzBov
fuente
Allí estaba maldiciendo a IE, ¡resultó que fue mi marcado descuidado todo el tiempo! ¡Salud!
Shawson
2
Wow ... Gracias buen señor. Este fue un hallazgo accidental. Ni siquiera podía entender por qué se activaba un evento de clic al presionar la tecla Intro, pero su cita me llevó a w3.org/TR/html5/forms.html#implicit-submission
quimio
El enlace está roto. Creo que w3c.github.io/html/sec-forms.html#implicit-submission es la nueva url.
TJ.
22

No creo que necesites JavaScript o CSS para arreglar esto.

De acuerdo con la especificación html 5 para botones, un botón sin atributo de tipo se trata igual que un botón con su tipo establecido en "enviar", es decir, como un botón para enviar su formulario contenedor. Establecer el tipo de botón en "botón" debería evitar el comportamiento que está viendo.

No estoy seguro sobre el soporte del navegador para esto, pero el mismo comportamiento se especificó en la especificación html 4.01 para botones, así que espero que sea bastante bueno.

Leinster
fuente
13

Al presionar 'Enter' en el foco, <input type="text">se activa el evento 'clic' en el primer elemento posicionado: <button>o <input type="submit">. Si presiona 'Enter' <textarea>, simplemente crea una nueva línea de texto.

Vea el ejemplo aquí .

Su código evita que ingrese una nueva línea de texto <textarea>, por lo que debe presionar la tecla solo para <input type="text">.

Pero, ¿por qué necesita presionar Enteren el campo de texto? Si desea enviar el formulario presionando 'Enter', pero <button>debe permanecer primero en el diseño, solo juegue con el marcado: coloque el <input type="submit">código antes <button>y use CSS para guardar el diseño que necesita.

Capturando 'Enter' y guardando marcado:

$('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
fuente
¿No debería la instrucción if tener una llave para ejecutar ambas instrucciones solo cuando se presiona enter? De lo contrario, el envío se realizará por cada pulsación de tecla. Me recuerda a ir a fallar. :)
danmiser
13

Donde sea que use un <button>elemento por defecto, considera ese botón, type="submit"por lo que si define el botón type="button", no lo considerará <button>como botón de envío.

Ram Thota
fuente
2

Al presionar enter en el campo de texto de un formulario, se enviará el formulario de manera predeterminada. Si no desea que funcione de esa manera, debe capturar la tecla Intro y consumirla como lo hizo. No hay forma de evitar esto. Funcionará de esta manera incluso si no hay un botón presente en el formulario.

Sparafusile
fuente
44
No creo que el problema es que la forma somete, es que desencadena la clickacción sobre el deseo de elementos del botón es una consecuencia no deseada
Martin Jespersen
Estás en lo correcto. De cualquier manera, el resultado es el mismo: debe capturar la tecla Intro para evitar envíos de formularios no deseados.
Sparafusile
2

Puede usar javascript para bloquear el envío de formularios hasta el momento apropiado. Un ejemplo muy crudo:

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

Al presionar Intro aún se activará el formulario para enviar, pero el javascript evitará que se envíe, hasta que presione el botón.

Dave
fuente
2

Ejemplo de 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.
}

si no usa preventDefault (), se activarán otros botones.

Mehmet Ali Kuş
fuente
0

Lo haría de la siguiente manera: en el controlador para el evento onclick del botón (no enviar) verifique el código clave del objeto de evento. Si es "enter", devolvería falso.

Satyajit
fuente
Ese código clave siempre se pasa como si fuera un clic. Ahí yace el problema. :-)
Rob Wilkerson
Entonces supongo que lo haces de la manera difícil: también maneja el evento onkeydown en el botón. El controlador pasará un keyEvent; verifique el KeyCode -> if 13, preventDefault. De esta manera, puede permitir que los usuarios presionen enter en ese botón también sin el efecto secundario de ejecutar el evento de clic.
Satyajit
0

Mi situación tiene dos Submitbotones dentro del elemento de formulario: Updatey Delete. El Deletebotón elimina una imagen y el Updatebotón actualiza la base de datos con los campos de texto en el formulario.

Como el Deletebotón estaba primero en el formulario, era el botón predeterminado en la Entertecla. No es lo que quería. El usuario esperaría poder golpear Enterdespués de cambiar algunos campos de texto.

Encontré mi respuesta para configurar el botón predeterminado aquí :

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

Sin usar ningún script, definí la forma a la que pertenece cada botón usando el <button> form="bla"atributo Configuré el Deletebotón en un formulario que no existe y configuré el Updatebotón que quería activar en la Entertecla del formulario en el que estaría el usuario al ingresar texto.

Esto es lo único que me ha funcionado hasta ahora.

Dan Vachon
fuente
0

Puedes hacer algo como esto.

asocia tu evento a una función común y llama al evento presionando una tecla o haciendo clic en un botón.

por ejemplo.

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



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

Agregué un botón de tipo "enviar" como primer elemento del formulario y lo hice invisible ( width:0;height:0;padding:0;margin:0;border-style:none;font-size:0;). Funciona como una actualización del sitio, es decir, no hago nada cuando se presiona el botón, excepto que el sitio se vuelve a cargar. Para mí funciona bien ...

torabe
fuente