2012-04-12 15 views
9

Tengo usuarios que hacen una llamada ajax mientras escriben. El problema es que hace la llamada para cada letra está tecleando, por lo que poner el tiempo de la siguiente manera:Espere la función hasta que el usuario deje de escribir

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

setTimeout(function(){ 

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

}, 400); 

}); 

No espere a 400 ms, pero luego ejecuta para cada keyup. ¿Cómo puedo cambiar esto para hacer que la llamada ajax solo 'una vez' alrededor de 400ms después de la última letra escrita?

(he usado 'retraso' en el pasado, pero eso no funciona en absoluto con mi guión ...)

+0

Ya existe una solución en otra pregunta: https://stackoverflow.com/questions/4220126/run-javascript-function-when-user-finishes-typing-instead-of-on-key-up/16324620 # 16324620 –

Respuesta

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

que es mejor para mover su función a una función llamada y llamarlo varias veces, porque de lo contrario va a crear otra función lambda en cada keyup que es innecesario y relativamente caro

+0

Eso funcionó como un amuleto :) – Youss

+0

@Youss y ¿qué sucede si presiona y suelta una tecla y luego mantiene presionada otra tecla? – Alnitak

+0

@Alnitak, tienes razón, y hay otros problemas con esto, por ejemplo, cuando escribes demasiado lento (más de 400ms entre 2 teclas), pero en el caso normal hace las cosas más suaves – Gavriel

4

Es necesario restablecer el temporizador cada vez que se pulsa una nueva clave, por ejemplo,

(function() { 
    var timer = null; 

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

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

La expresión función se utiliza para asegurar que el alcance de la variable de timer se limita a esas dos funciones que lo necesitan.

+0

Probablemente debería usar '.on ('keyup', ...)' Dado que jquery 1.7 '.live' ha quedado en desuso. – ZombieCode

+0

@Ekaterina Sí, probablemente debería, pero este fue el conjunto mínimo de cambios en el código del OP. – Alnitak

0

Me gustaría pensar que usted podría usar delay() nuevamente en este contexto, siempre y cuando esté bien con agregar un nuevo 'algo' temporal a la mezcla. Que este trabajo para usted?

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

Parece una solución alternativa ... La respuesta proporcionada por @ Flöcsy es más directa. ps ¿Qué es outRunningAJob :) – Youss

+0

Personalmente todavía no me he sentido cómodo con las funciones 'timeout' y por eso pensé que tal vez estabas en un lugar similar ya que estás preguntando sobre ello. ¿Es una solución? Así es cómo abordaría el problema actualmente. Si actualmente está más familiarizado con el uso de 'delay ', esta podría ser una solución mejor (en términos de mantenimiento). 'outRunningAJob' es simplemente arbitrario pero autodocumentado. Me alegro de que te haya gustado :-) – veeTrain

0

encontré la siguiente más fácil de implementar:

$(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); 
}); 

Al almacenar la cadena actual que son capaces de ver que el usuario ha dejado de escribir. Entonces puede llamar a su función de forma segura para hacer lo que sea que el procesamiento deba suceder.

Cuestiones relacionadas