jquery - debounce - ¿Cómo desencadenar un evento en el texto de entrada después de dejar de escribir/escribir?
debounce jquery (8)
¡Necesitas rebotar!
Aquí hay un plugin jQuery , y aquí está todo lo que necesita saber sobre debounce . Si vienes desde Google y Underscore ha encontrado su camino en el JSoup de tu aplicación, ¡ya se ha eliminado correctamente el reblandecimiento!
Quiero desencadenar un evento justo después de dejar de escribir caracteres (no mientras escribo) en mi cuadro de texto de entrada.
Lo he intentado con:
$(''input#username'').keypress(function() {
var _this = $(this); // copy of this object for further usage
setTimeout(function() {
$.post(''/ajax/fetch'', {
type: ''username'',
value: _this.val()
}, function(data) {
if(!data.success) {
// continue working
} else {
// throw an error
}
}, ''json'');
}, 3000);
});
Pero este ejemplo produce un tiempo de espera para cada carácter escrito y obtengo unas 20 solicitudes AJAX si escribo 20 caracteres.
En este violín , demuestro el mismo problema con una simple alerta en lugar de un AJAX.
¿Hay una solución para esto o solo estoy usando un mal enfoque para esto?
Deberá usar setTimeout
(como usted) pero también almacenar la referencia para que pueda seguir restableciendo el límite. Algo como:
//
// $(''#element'').donetyping(callback[, timeout=1000])
// Fires callback when a user has finished typing. This is determined by the time elapsed
// since the last keystroke and timeout parameter or the blur event--whichever comes first.
// @callback: function to be called when even triggers
// @timeout: (default=1000) timeout, in ms, to to wait before triggering event if not
// caused by blur.
// Requires jQuery 1.7+
//
;(function($){
$.fn.extend({
donetyping: function(callback,timeout){
timeout = timeout || 1e3; // 1 second default timeout
var timeoutReference,
doneTyping = function(el){
if (!timeoutReference) return;
timeoutReference = null;
callback.call(el);
};
return this.each(function(i,el){
var $el = $(el);
// Chrome Fix (Use keyup over keypress to detect backspace)
// thank you @palerdot
$el.is('':input'') && $el.on(''keyup keypress paste'',function(e){
// This catches the backspace button in chrome, but also prevents
// the event from triggering too preemptively. Without this line,
// using tab/shift+tab will make the focused element fire the callback.
if (e.type==''keyup'' && e.keyCode!=8) return;
// Check if timeout has been set. If it has, "reset" the clock and
// start over again.
if (timeoutReference) clearTimeout(timeoutReference);
timeoutReference = setTimeout(function(){
// if we made it here, our timeout has elapsed. Fire the
// callback
doneTyping(el);
}, timeout);
}).on(''blur'',function(){
// If we can, fire the event since we''re leaving the field
doneTyping(el);
});
});
}
});
})(jQuery);
$(''#example'').donetyping(function(){
$(''#example-output'').text(''Event last fired @ '' + (new Date().toUTCString()));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input type="text" id="example" />
<p id="example-output">Nothing yet</p>
Eso se ejecutará cuando:
- El tiempo de espera ha transcurrido, o
- El usuario cambió los campos (evento de
blur
)
(Lo que sea que venga primero)
En mi opinión, un usuario deja de escribir cuando no se enfoca en esa entrada. Para esto tienes una función llamada "desenfoque" que hace cosas like
Hay un plugin simple que he hecho que hace exactamente eso. Requiere mucho menos código que las soluciones propuestas y es muy ligero (~ 0,6kb)
Primero crea un objeto Bid
que puede ser bumped
cualquier momento. Cada bache retrasará la devolución de la oferta para la próxima cantidad de tiempo dada.
var searchBid = new Bid(function(inputValue){
//your action when user will stop writing for 200ms.
yourSpecialAction(inputValue);
}, 200); //we set delay time of every bump to 200ms
Cuando el objeto Bid
está listo, necesitamos bump
alguna manera. Vamos a adjuntar golpes al event
keyup
.
$("input").keyup(function(){
searchBid.bump( $(this).val() ); //parameters passed to bump will be accessable in Bid callback
});
Lo que sucede aquí es:
Cada vez que el usuario presiona la tecla, la oferta se "retrasa" (se golpea) durante los próximos 200 ms. Si pasan 200 ms sin que se repita el mensaje, se activará la devolución de llamada.
Además, tiene 2 funciones adicionales para detener la oferta (si el usuario presionó esc o hizo clic fuera de la entrada, por ejemplo) y para finalizar y activar la devolución de llamada inmediatamente (por ejemplo, cuando el usuario presione la tecla Intro):
searchBid.stop();
searchBid.finish(valueToPass);
He estado buscando un código HTML / JS simple y no encontré ninguno. Luego, escribí el siguiente código usando onkeyup="DelayedSubmission()"
.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pt-br" lang="pt-br">
<head><title>Submit after typing finished</title>
<script language="javascript" type="text/javascript">
function DelayedSubmission() {
var date = new Date();
initial_time = date.getTime();
if (typeof setInverval_Variable == ''undefined'') {
setInverval_Variable = setInterval(DelayedSubmission_Check, 50);
}
}
function DelayedSubmission_Check() {
var date = new Date();
check_time = date.getTime();
var limit_ms=check_time-initial_time;
if (limit_ms > 800) { //Change value in milliseconds
alert("insert your function"); //Insert your function
clearInterval(setInverval_Variable);
delete setInverval_Variable;
}
}
</script>
</head>
<body>
<input type="search" onkeyup="DelayedSubmission()" id="field_id" style="WIDTH: 100px; HEIGHT: 25px;" />
</body>
</html>
Puede usar underscore.js "rebote"
$(''input#username'').keypress( _.debounce( function(){<your ajax call here>}, 500 ) );
Esto significa que su llamada de función se ejecutará después de 500 ms de presionar una tecla. Pero si presiona otra tecla (se activa otro evento de pulsación de tecla) antes de los 500 ms, la ejecución de la función previa se ignorará (antirrebote) y la nueva se ejecutará después de un nuevo temporizador de 500 ms.
Para obtener información adicional, usar _.debounce (func, timer, true ) significaría que la primera función se ejecutará y todos los demás eventos de pulsación de tecla con los siguientes temporizadores de 500ms se ignorarán.
SOLUCIÓN:
Aquí está la solución. Ejecutar 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(''Hi, func called'');
}, 1000 );
});
solución limpiada
$.fn.donetyping = function(callback, delay){
delay || (delay = 1000);
var timeoutReference;
var doneTyping = function(elt){
if (!timeoutReference) return;
timeoutReference = null;
callback(elt);
};
this.each(function(){
var self = $(this);
self.on(''keyup'',function(){
if(timeoutReference) clearTimeout(timeoutReference);
timeoutReference = setTimeout(function(){
doneTyping(self);
}, delay);
}).on(''blur'',function(){
doneTyping(self);
});
});
return this;
};