2012-06-30 16 views
9

Tengo una entrada de número que debe desencadenar jQuery en cada cambio. Para hacer esto, hago un $('#id').bind('keyup change', ...);, que se desencadena en cualquier teclado o controlador de mouse cambiado.jQuery código desencadenado dos veces para bind ('cambio de tecla') al presionar la tecla

Esto funciona para encontrar clics del mouse (activadores change) y para escribir números (activadores keyup). Pero para las teclas de cursor activa change y keyup. ¿Cómo puedo hacerlo para que solo se active una vez en todas las situaciones?

He aquí un ejemplo que muestra el problema: http://jsfiddle.net/jSjkE/

+2

si los recuentos keyup como un cambio, solo use change – Hassek

+0

'onchange' solo se activa cuando el elemento pierde el foco y tiene un valor diferente al que ganó el foco. ¿Intentó el 'oninput' de HTML5? [Fiddle] (http://jsfiddle.net/ult_combo/jSjkE/2/) –

+0

@Hassek; Tienes razón. La situación es un poco más compleja debido a que la entrada es 'type =" number "'. Editaré mi pregunta para explicar. – Martijn

Respuesta

12

Usted tienen un concepto equivocado sobre el evento onchange.

No NO fuego cuando cambia el valor del elemento, en cambio, se dispara sólo cuando se cumplen 2 condiciones:

  • Las faltas de definición de elemento (pierde el foco);
  • El elemento tiene un valor diferente al que adquirió el foco.

Nota: Lo anterior es para las entradas del tipo text. Para los tipos checkbox/radio, se activa tan pronto como cambia su propiedad checked, y para los elementos select tan pronto como su opción seleccionada cambie.

El evento onchange (posiblemente erróneamente) se dispara al presionar las flechas arriba/abajo de Chrome input type="number". Debería no basarse en él, ya que muchos otros navegadores importantes ni siquiera tienen una implementación del número de entradas todavía y pueden no seguir este comportamiento.

En su lugar, como está utilizando HTML5, debe confiar en el evento HTML5 oninput, que se activa siempre que se actualiza el valor del elemento.

$(function() { 
    var count = 0; 
    $('#num').on('input', function(e) { 
     console.log('update ' + (++count) + ' Value: ' + this.value);  
    }); 
});​ 

Fiddle

edición:

Para los navegadores antiguos (y no HTML5), es posible utilizar el evento keyup como punto de retorno:

$('#num').on('input keyup', function(e) { 

El La forma más flexible de hacer esto para los navegadores que no sean HTML5 sería ga setInterval constantemente comprobando si el valor del elemento ha cambiado, como keyup no se activa si selecciona texto y lo arrastra al cuadro de texto; puede intentar .on('input keyup mouseup', pero luego no se activará si el usuario utiliza el menú Editar> Pegar del navegador .

Edit2:

Si no desea utilizar setInterval, se puede poner una enorme eventos dentro del mapa .on/.bind y comprobar si el valor ha cambiado almacenando el valor actual en el .data() de el elemento:

var count = 0; 
$('#num').on('input keyup change', function(e) { 
    if (this.value == $(this).data('curr_val')) 
     return false; 
    $(this).data('curr_val', this.value); 

    console.log('update ' + (++count) + ' Value: ' + this.value); 
}); 

Fiddle

he añadido el onchange evento en el mapa de eventos, por lo tanto, aunque fallan oninput y onkeyup (navegador no html5 que utiliza el menú del navegador para pegar datos), el evento onchange se disparará cuando el elemento pierda el foco.

Aquí está la edición final con una comentado setInterval y .data() evitar el uso de variables globales, para que pueda elegir cuál de los retrocesos de empleo:

$(function() { 
    var $num = $('#num'); 
    $num.data('curr_val', $num.val()); //sets initial value 

    var count = 0; 
    setInterval(function(){ 
     if ($num.data('curr_val') == $num.val()) //if it still has same value 
      return false; //returns false 
     $num.data('curr_val', $num.val()); //if val is !=, updates it and 
     //do your stuff 
     console.log('update ' + (++count) + ' Value: ' + $num.val()); 
    }, 100); //100 = interval in miliseconds 
}); 

Fiddle

+0

Navegadores que no admite 'type =" number "' volver a 'tipo =" texto "', que todavía funcionará bien. Al comprobar solo el evento 'oninput', los navegadores que no lo admiten (IE8 y anterior) no activarán el código. – Martijn

+0

@Martijn Utilizo [GCF] (https://developers.google.com/chrome/chrome-frame/) en mis páginas para los usuarios de IE, sin embargo, sí, para los navegadores que no sean HTML5, puede agregar un evento 'keyup' allí también. La versión más flexible de 'oninput' para versiones anteriores está utilizando' setInterval' y comprobando si el valor ha cambiado, desafortunadamente. –

+0

La mayoría de los usuarios de versiones antiguas de IE son usuarios corporativos que no pueden instalar GCF más de lo que podrían instalar Chrome o una nueva versión de IE. Echaré un vistazo a tu sugerencia setInterval, aunque suena como una solución muy sucia. – Martijn

0
$('input').unbind('keyup').bind('keyup',function(e){ ... 
+0

No sé quién rechazó mi respuesta, pero es 100% correcta y directa. – lufi

+0

No estoy seguro de por qué tiene downvotes - funcionó para mí (+1). ¡¡¡Gracias!!! – mike123

+0

Gracias, amigo, appriciate. Mucha gente aquí dice ser pros y downvote sin ninguna razón sin tener un clou. – lufi

Cuestiones relacionadas