Pregunta

Tengo un formulario que se envía de forma remota cuando cambian los distintos elementos.En un campo de búsqueda en particular, estoy usando una tecla para detectar cuándo cambia el texto en el campo.El problema con esto es que cuando alguien escribe "pollo", el formulario se envía siete veces y solo se cuenta la última.

Lo que sería mejor es algo como esto.

  • Keyup detectado - comienza a esperar (durante un segundo)

  • se detectó otra tecla: reinicie el tiempo de espera

  • La espera termina: obtenga valor y envíe el formulario.

Antes de comenzar a codificar mi propia versión de esto (realmente soy un tipo de backend con solo un poco de js, uso jQuery para todo), ¿existe ya una solución para esto?Parece que sería un requisito común.¿Quizás un complemento de jQuery?Si no, ¿cuál es la mejor y más sencilla forma de codificar esto?

ACTUALIZACIÓN: código actual agregado para Dan (abajo)

Dan: esto puede ser relevante.Uno de los complementos de jQuery que estoy usando en la página (tablesorter) requiere este archivo: "tablesorter/jquery-latest.js", que, si se incluye, genera el mismo error con el código que antes:

jQuery ("Input#Search"). Data ("Tiempo de espera", NULL) está indefinido http‍: //192.168.0.234/javascripts/main.js? 1264084467 línea 11

¿Quizás haya algún tipo de conflicto entre diferentes definiciones de jQuery?(o algo)

$(document).ready(function() {
  //initiate the shadowbox player
//  Shadowbox.init({
//    players:  ['html', 'iframe']
//  });
}); 

jQuery(function(){
  jQuery('input#search')
    .data('timeout', null)
    .keyup(function(){
      jQuery(this).data('timeout', setTimeout(function(){
          var mytext = jQuery('input#search').val();
          submitQuizForm();
          jQuery('input#search').next().html(mytext);
        }, 2000)
     )
     .keydown(function(){
       clearTimeout(jQuery(this).data('timeout'));
     });
    });
});

function submitQuizForm(){
  form = jQuery("#searchQuizzes");
  jQuery.ajax({
    async:true, 
    data:jQuery.param(form.serializeArray()), 
    dataType:'script', 
    type:'get', 
    url:'/millionaire/millionaire_quizzes',
    success: function(msg){ 
     // $("#chooseQuizMainTable").trigger("update"); 
    }
  }); 
  return true;
}
¿Fue útil?

Solución

Lo siento, no he probado esto y está un poco fuera de mi cabeza, pero espero que algo como esto debería funcionar.Cambie el 2000 a la cantidad de milisegundos que necesite entre publicaciones del servidor

<input type="text" id="mytextbox" style="border: 1px solid" />
<span></span>

<script language="javascript" type="text/javascript">
    jQuery(function(){
      jQuery('#mytextbox')
        .data('timeout', null)
        .keyup(function(){
            clearTimeout(jQuery(this).data('timeout'));
            jQuery(this).data('timeout', setTimeout(submitQuizForm, 2000));
        });
    });
</script>

Otros consejos

Aquí está tu elegante extensión jquery:

(function($){

$.widget("ui.onDelayedKeyup", {

    _init : function() {
        var self = this;
        $(this.element).keyup(function() {
            if(typeof(window['inputTimeout']) != "undefined"){
                window.clearTimeout(inputTimeout);
            }  
            var handler = self.options.handler;
            window['inputTimeout'] = window.setTimeout(function() {
                handler.call(self.element) }, self.options.delay);
        });
    },
    options: {
        handler: $.noop(),
        delay: 500
    }

});
})(jQuery);

Úselo así:

    $("input.filterField").onDelayedKeyup({
        handler: function() {
            if ($.trim($(this).val()).length > 0) {
                //reload my data store using the filter string.
            }
        }
    });

Tiene un retraso de medio segundo de forma predeterminada.

Como actualización, terminé con esto que parece funcionar bien:

function afterDelayedKeyup(selector, action, delay){
  jQuery(selector).keyup(function(){
    if(typeof(window['inputTimeout']) != "undefined"){
      clearTimeout(inputTimeout);
    }  
    inputTimeout = setTimeout(action, delay);
  });
}

Luego llamo a esto desde el bloque document.ready de la página en cuestión con

  afterDelayedKeyup('input#search',"submitQuizForm()",500)

Lo que sería bueno sería crear un nuevo evento jquery que use esta lógica, por ejemplo, .delayedKeyup para acompañar a .keyup, por lo que podría decir algo como esto para el bloque document.ready de una página individual.

  jQuery('input#search').delayedKeyup(function(){
    submitQuizForm();
  });

Pero no sé cómo personalizar jquery de esta manera.Aunque es una buena tarea.

Buen trabajo, Max, ¡fue de gran ayuda para mí!He realizado una ligera mejora en su función haciéndola más general:

function afterDelayedEvent(eventtype, selector, action, delay) {
    $(selector).bind(eventtype, function() {
        if (typeof(window['inputTimeout']) != "undefined") {
            clearTimeout(inputTimeout);
        }
        inputTimeout = setTimeout(action, delay);
    });
}

De esta manera puedes usarlo para cualquier tipo de evento, aunque el keyup es probablemente el más útil aquí.

Sé que esto es antiguo, pero fue uno de los primeros resultados cuando buscaba cómo hacer algo como esto, así que pensé en compartir mi solución.Utilicé una combinación de las respuestas proporcionadas para obtener lo que necesitaba.

Quería un evento personalizado que funcionara igual que los eventos jQuery existentes y necesitaba funcionar con keypress + eliminar, retroceder y entrar.

Aquí está mi complemento jQuery:

$.fn.typePause = function (dataObject, eventFunc)
    {
        if(typeof dataObject === 'function')
        {
            eventFunc = dataObject;
            dataObject = {};
        }
        if(typeof dataObject.milliseconds === 'undefined')
            dataObject.milliseconds = 500;
        $(this).data('timeout', null)
            .keypress(dataObject, function(e)
            {
                clearTimeout($(this).data('timeout'));
                $(this).data('timeout', setTimeout($.proxy(eventFunc, this, e), dataObject.milliseconds));
            })
            .keyup(dataObject, function(e)
            {
                var code = (e.keyCode ? e.keyCode : e.which);
                if(code == 8 || code == 46 || code == 13)
                    $(this).triggerHandler('keypress',dataObject);
            });
    }

solía $.proxy() para preservar el contexto en el evento, aunque podría haber una mejor manera de hacerlo, en cuanto al rendimiento.

Para utilizar este complemento, simplemente haga:

$('#myElement').typePause(function(e){ /* do stuff */ });

o

$('#myElement').typePause({milliseconds: 500, [other data to pass to event]},function(e){ /* do stuff */ });    
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top