Pregunta ¿Cómo retrasar el controlador .keyup () hasta que el usuario deje de escribir?


Tengo un campo de búsqueda. En este momento, busca cada keyup. Entonces, si alguien escribe "Windows", realizará una búsqueda con AJAX para cada tecla: "W", "Wi", "Win", "Wind", "Windo", "Window", "Windows".

Quiero tener un retraso, por lo que solo busca cuando el usuario deja de escribir durante 200 ms.

No hay opción para esto en el keyup función, y lo he intentado setTimeout, pero no funcionó.

¿Cómo puedo hacer eso?


526
2017-12-15 18:33


origen


Respuestas:


Utilizo esta función para el mismo propósito, ejecutando una función después de que el usuario haya dejado de escribir durante un período de tiempo específico:

var delay = (function(){
  var timer = 0;
  return function(callback, ms){
    clearTimeout (timer);
    timer = setTimeout(callback, ms);
  };
})();

Uso:

$('input').keyup(function() {
    delay(function(){
      alert('Time elapsed!');
    }, 1000 );
});

Para algo más sofisticado, eche un vistazo a jQuery Typewatch enchufar.


930
2017-12-15 18:45



Si desea buscar después de que se termine el tipo, use una variable global para contener el tiempo de espera devuelto por su setTimout llamar y cancelarlo con un clearTimeout si aún no ha sucedido para que no se active el tiempo de espera, excepto en el último keyup evento

var globalTimeout = null;  
$('#id').keyup(function(){
  if(globalTimeout != null) clearTimeout(globalTimeout);  
  globalTimeout =setTimeout(SearchFunc,200);  
}   
function SearchFunc(){  
  globalTimeout = null;  
  //ajax code
}

O con una función anónima:

var globalTimeout = null;  
$('#id').keyup(function() {
  if (globalTimeout != null) {
    clearTimeout(globalTimeout);
  }
  globalTimeout = setTimeout(function() {
    globalTimeout = null;  

    //ajax code

  }, 200);  
}   

50
2017-12-15 18:43



Otra ligera mejora en la respuesta de CMS. Para permitir retrasos por separado, puede usar lo siguiente:

function makeDelay(ms) {
    var timer = 0;
    return function(callback){
        clearTimeout (timer);
        timer = setTimeout(callback, ms);
    };
};

Si quiere reutilizar la misma demora, solo haga

var delay = makeDelay(250);
$(selector1).on('keyup', function() {delay(someCallback);});
$(selector2).on('keyup', function() {delay(someCallback);});

Si desea demoras por separado, puede hacer

$(selector1).on('keyup', function() {makeDelay(250)(someCallback);});
$(selector2).on('keyup', function() {makeDelay(250)(someCallback);});

25
2017-10-08 22:27



También podrías mirar underscore.js, que proporciona métodos de utilidad como rebotar:

var lazyLayout = _.debounce(calculateLayout, 300);
$(window).resize(lazyLayout);

25
2018-02-18 10:06



Basado en la respuesta de CMS, hice esto:

Coloque el código a continuación después de incluir jQuery:

/*
 * delayKeyup
 * http://code.azerti.net/javascript/jquery/delaykeyup.htm
 * Inspired by CMS in this post : http://stackoverflow.com/questions/1909441/jquery-keyup-delay
 * Written by Gaten
 * Exemple : $("#input").delayKeyup(function(){ alert("5 secondes passed from the last event keyup."); }, 5000);
 */
(function ($) {
    $.fn.delayKeyup = function(callback, ms){
        var timer = 0;
        $(this).keyup(function(){                   
            clearTimeout (timer);
            timer = setTimeout(callback, ms);
        });
        return $(this);
    };
})(jQuery);

Y simplemente usa esto:

$('#input').delayKeyup(function(){ alert("5 secondes passed from the last event keyup."); }, 5000);

Cuidado: la variable $ (this) en la función pasada como parámetro no coincide con la entrada


13
2018-03-13 14:40



Retrasar llamadas de múltiples funciones usando etiquetas

Esta es la solución con la que trabajo Demorará la ejecución de CUALQUIER función que desee. Puede ser la consulta de búsqueda por teclado, tal vez haga clic rápidamente en los botones anterior o siguiente (que de lo contrario enviarían varias solicitudes si se hace clic de forma continua y no se usarán después de todo). Utiliza un objeto global que almacena cada tiempo de ejecución y lo compara con la solicitud más reciente.

¡Así que el resultado es que solo se llamará al último clic / acción, porque esas solicitudes se almacenan en una cola, que después de los X milisegundos se llama si no existe otra solicitud con la misma etiqueta en la cola!

function delay_method(label,callback,time){
    if(typeof window.delayed_methods=="undefined"){window.delayed_methods={};}  
    delayed_methods[label]=Date.now();
    var t=delayed_methods[label];
    setTimeout(function(){ if(delayed_methods[label]!=t){return;}else{  callback();}}, time||500);
  }

Puede establecer su propio tiempo de retardo (es opcional, por defecto es 500ms). Y envíe los argumentos de su función de una "manera cerrada".

Por ejemplo, si desea llamar a la función siguiente:

function send_ajax(id){console.log(id);}

Para evitar solicitudes múltiples send_ajax, las demoras utilizando:

delay_method( "check date", function(){ send_ajax(2); } ,600);

Toda solicitud que utilice la etiqueta "fecha de verificación" solo se activará si no se realiza ninguna otra solicitud en el marco de tiempo de 600 milisegundos. Este argumento es opcional

Independencia de etiqueta (llamando a la misma función de destino) pero ejecuta ambos: 

delay_method("check date parallel", function(){send_ajax(2);});
delay_method("check date", function(){send_ajax(2);});

Resultados al llamar a la misma función pero retrasarlos independientemente debido a que sus etiquetas son diferentes


8
2018-05-28 10:25



Esta función amplía un poco la función de la respuesta de Gaten para recuperar el elemento:

$.fn.delayKeyup = function(callback, ms){
    var timer = 0;
    var el = $(this);
    $(this).keyup(function(){                   
    clearTimeout (timer);
    timer = setTimeout(function(){
        callback(el)
        }, ms);
    });
    return $(this);
};

$('#input').delayKeyup(function(el){
    //alert(el.val());
    // Here I need the input element (value for ajax call) for further process
},1000);

http://jsfiddle.net/Us9bu/2/


6
2017-09-25 10:36



Me sorprende que nadie mencione el problema con la entrada múltiple en CMS muy bien recortado.

Básicamente, debe definir la variable de retardo individualmente para cada entrada. De lo contrario, si sb coloca texto en la primera entrada y rápidamente salta a otra entrada y comienza a escribir, vuelva a llamar para la primera NO ¡ser llamado!

Vea el siguiente código que vine con base en otras respuestas:

(function($) {
    /**
     * KeyUp with delay event setup
     * 
     * @link http://stackoverflow.com/questions/1909441/jquery-keyup-delay#answer-12581187
     * @param function callback
     * @param int ms
     */
    $.fn.delayKeyup = function(callback, ms){
            $(this).keyup(function( event ){
                var srcEl = event.currentTarget;
                if( srcEl.delayTimer )
                    clearTimeout (srcEl.delayTimer );
                srcEl.delayTimer = setTimeout(function(){ callback( $(srcEl) ); }, ms);
            });

        return $(this);
    };
})(jQuery);

Esta solución mantiene la referencia de setTimeout dentro de la variable delayTimer de entrada. También pasa la referencia del elemento a la devolución de llamada como se sugirió fazzyx.

Probado en IE6, 8 (comp - 7), 8 y Opera 12.11.


5
2017-12-17 12:17



Esto funcionó para mí donde retrasé la operación de lógica de búsqueda y verifico si el valor es el mismo que ingresé en el campo de texto. Si el valor es el mismo, continúo y realizo la operación para los datos relacionados con el valor de búsqueda.

$('#searchText').on('keyup',function () {
    var searchValue = $(this).val();
    setTimeout(function(){
        if(searchValue == $('#searchText').val() && searchValue != null && searchValue != "") {
           // logic to fetch data based on searchValue
        }
        else if(searchValue == ''){
           // logic to load all the data
        }
    },300);
});

5
2017-08-31 20:48



Función de retardo para llamar en cada tecla. Se requiere jQuery 1.7.1 o superior

jQuery.fn.keyupDelay = function( cb, delay ){
  if(delay == null){
    delay = 400;
  }
  var timer = 0;
  return $(this).on('keyup',function(){
    clearTimeout(timer);
    timer = setTimeout( cb , delay );
  });
}

Uso: $('#searchBox').keyupDelay( cb );


4
2018-06-29 11:42



Si a alguien le gusta retrasar la misma función, y sin una variable externa, puede usar el siguiente script:

function MyFunction() {

    //Delaying the function execute
    if (this.timer) {
        window.clearTimeout(this.timer);
    }
    this.timer = window.setTimeout(function() {

        //Execute the function code here...

    }, 500);
}

3
2018-01-07 10:23