2012-06-30 8 views
9

Ho un numero di input che dovrebbe attivare jQuery ad ogni modifica. Per fare ciò, eseguo uno $('#id').bind('keyup change', ...);, che viene attivato su qualsiasi keyup o controller del mouse modificato.jQuery code triggerato due volte per bind ('keyup change') quando si preme il tasto

Questo funziona trova per clic del mouse (trigger change) e per digitare numeri (trigger keyup). Ma per i tasti cursore attiva sia change sia keyup. Come posso farlo in modo che si inneschi solo una volta in tutte le situazioni?

Ecco un esempio che mostra il problema: http://jsfiddle.net/jSjkE/

+2

se conta keyup come una modifica quindi usa semplicemente la modifica – Hassek

+0

"onchange" si attiva solo quando l'elemento perde lo stato attivo e ha un valore diverso rispetto a quando ha ottenuto lo stato attivo. Hai provato 'oninput' di HTML5? [Fiddle] (http://jsfiddle.net/ult_combo/jSjkE/2/) –

+0

@Hassek; Hai ragione. La situazione è un po 'più complessa a causa dell'input "type =" number "'. Modificherò la mia domanda per spiegare. – Martijn

risposta

12

Si hanno un concetto sbagliato sull'evento onchange.

Non NON fuoco quando il valore cambia dell'elemento, invece, spara solo quando sono soddisfatte 2 condizioni:

  • Le sfocature elemento (non è più attivo);
  • L'elemento ha un valore diverso rispetto a quando ha ottenuto la messa a fuoco.

Nota: quanto sopra è per gli ingressi di tipo text. Per i tipi checkbox/radio si attiva non appena le loro modifiche alla proprietà checked e per gli elementi select non appena viene modificata l'opzione selezionata.

L'evento onchange (eventualmente erroneamente) si attiva quando si preme le frecce su/giù di input type="number" di Chrome. Si dovrebbe non contare su di esso, come molti altri principali browser non hanno ancora un'implementazione del numero di ingressi ancora e potrebbe non seguire questo comportamento.

Invece, poiché si utilizza HTML5, è necessario fare affidamento sull'evento HTML5 oninput, che viene attivato ogni volta che viene aggiornato il valore dell'elemento.

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

Fiddle

edit:

per browser meno recenti (e non HTML5), è possibile utilizzare l'evento keyup come ripiego:

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

Il il modo più resiliente per fare questo per i browser non HTML5 sarebbe havin ga setInterval controllando costantemente se il valore dell'elemento è cambiato, come keyup non si attiva se si seleziona del testo e trascinandolo nella casella di testo - si potrebbe provare .on('input keyup mouseup', ma poi non si innescherà se l'utente utilizza il menu Modifica> Incolla del browser .

EDIT2:

Se non si desidera utilizzare setInterval, si può mettere un enorme di eventi Mappa all'interno del .on/.bind e controllare se il valore è cambiato, memorizzando il valore corrente nel .data() di l'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

ho aggiunto la onchange evento alla mappa degli eventi, quindi anche se lo oninput e onkeyup non riesce (browser non html5 utilizzando il menu del browser per incollare i dati), l'evento si attiverà ancora quando l'elemento perde lo stato attivo.

Ecco il montaggio finale con una commentato setInterval e .data() evitare l'uso di variabili globali, in modo da poter scegliere quale dei fallback da utilizzare:

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

Browser che non supportano 'type =" number "' ripiega su 'type =" text "', che funzionerà comunque bene. Se si verifica solo l'evento 'oninput', i browser che non lo supportano (IE8 e precedenti) non attivano affatto il codice. – Martijn

+0

@Martijn Io uso [GCF] (https://developers.google.com/chrome/chrome-frame/) sulle mie pagine per gli utenti di IE, tuttavia sì, per i browser non HTML5 è possibile aggiungere un evento 'keyup' lì anche. La versione più resiliente di 'oninput' per le versioni precedenti utilizza un' setInterval' e controlla se il valore è cambiato, sfortunatamente. –

+0

La maggior parte degli utenti di vecchie versioni di IE sono utenti aziendali che non possono installare GCF più di quanto non possano installare Chrome o una nuova versione di IE. Daremo un'occhiata al tuo suggerimento sull'Interval set, anche se sembra una soluzione molto sporca. – Martijn

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

Non so chi ha downvoted la mia risposta, ma è corretto al 100% e dritto al punto. – lufi

+0

Non so neanche perché ha downvotes - ha funzionato per me (+1). Grazie!!! – mike123

+0

Grazie del microfono, appialo. Molte persone qui sostengono di essere pro e downvote senza motivo senza avere un clou. – lufi

Problemi correlati