2012-04-12 12 views
9

Ho utenti che fanno una chiamata ajax durante la digitazione. Il problema è che effettua la chiamata per ogni lettera viene digitato, così ho impostato il timeout come questo:Attendere la funzione fino a quando l'utente non smette di digitare

$(input).live('keyup', function(e){ 

setTimeout(function(){ 

var xx = $(input).val(); 
doSearch(xx); 

}, 400); 

}); 

Non attendere 400ms, ma poi esegue per ogni keyup. Come posso cambiarlo per far sì che la chiamata ajax sia "una sola volta" a circa 400 ms dall'ultima lettera digitata?

(io ho usato 'ritardo' in passato, ma che non funziona affatto con il mio script ...)

+0

C'è già una soluzione fornita in un'altra domanda: https://stackoverflow.com/questions/4220126/run-javascript-function-when-user-finishes-typing-instead-of-on-key-up/16324620 # 16324620 –

risposta

18
timer = 0; 
function mySearch(){ 
    var xx = $(input).val(); 
    doSearch(xx); 
} 
$(input).live('keyup', function(e){ 
    if (timer) { 
     clearTimeout(timer); 
    } 
    timer = setTimeout(mySearch, 400); 
}); 

è meglio spostare la funzione per una funzione denominata e chiamarlo più volte, perche' altrimenti si sta creando un'altra funzione lambda su ogni keyup che è inutile e relativamente costoso

+0

Che ha funzionato come un fascino :) – Youss

+0

@Youss e cosa succede se si preme e rilascia un tasto, e quindi tenere premuto un altro tasto? – Alnitak

+0

@Alnitak, hai ragione, e ci sono altri problemi con questo, ad esempio quando digiti troppo lento (più di 400ms tra 2 chiavi), ma nel caso normale rende le cose più agevoli – Gavriel

4

È necessario azzerare il timer ogni volta che si preme una nuova chiave, per esempio

(function() { 
    var timer = null; 

    $(input).live('keyup', function(e) { 
     timer = setTimeout(..., 400); 
    }); 

    $(input).live('keydown', function(e) { 
     clearTimeout(timer); 
    }); 
)(); 

L'espressione funzione viene utilizzato per garantire che la portata della variabile timer è limitata a queste due funzioni che ne hanno bisogno.

+0

Probabilmente dovrebbe usare '.on ('keyup', ...)' Poiché jquery 1.7 '.live' è stato deprecato. – ZombieCode

+0

@Ekaterina sì, probabilmente dovrebbe, ma questa era la serie minima di modifiche al codice dell'OP. – Alnitak

0

Vorrei pensare che delay() utilizzare di nuovo in questo contesto finché sei ok con l'aggiunta di un nuovo "qualcosa" temporaneo al mix. Funzionerebbe per te?

$(input).live('keyup', function(e) { 
    if (!$(input).hasClass("outRunningAJob")) { 
     var xx = $(input).val(); 
     $(input).addClass("outRunningAJob"); 
     doSearch(xx); 
     $(input).delay(400).queue(function() { 
      $(this).removeClass("outRunningAJob"); 
      $(this).dequeue(); 
     }); 
    } 
}); 
+0

Sembra una soluzione alternativa ... La risposta fornita da @ Flöcsy è più semplice. ps cosa è outRunningAJob :) – Youss

+0

Personalmente non sono ancora diventato a mio agio con le funzioni di "timeout" e quindi ho pensato che forse eri in un posto simile da quando te lo stai chiedendo. È una soluzione? È come vorrei affrontare il problema al momento. Se al momento si ha maggiore familiarità con l'uso di 'delay', questa potrebbe essere una soluzione migliore (nel rispetto della manutenibilità). 'outRunningAJob' è arbitrario ma autodocumentante. Lieto che ti sia piaciuto :-) – veeTrain

0

ho trovato il seguente più facile da implementare:

$(input).on('keyup', function() { 
    delay(function() { 
     if (input).val() !== '' && $(input).val() !== $(input).attr('searchString')) { 
      // make the AJAX call at this time 
      // Store the value sent so we can compare when JSON returns 
      $(input).attr('searchString', $(input).val()); 

      namepicker2_Search_Prep(input); 
     } 
    }, 500); 
}); 

Memorizzando la stringa corrente si è in grado di vedere che l'utente ha smesso di scrivere. Quindi puoi tranquillamente chiamare la tua funzione per fare ciò che deve accadere in qualsiasi momento.

Problemi correlati