14

当各种元素发生变化时,我有一个远程提交的表单。特别是在搜索字段上,我使用 keyup 来检测字段中的文本何时更改。这样做的问题是,当有人键入“chicken”时,表单会提交七次,只计算最后一次。

什么会更好是这样的

  • 检测到 keyup - 开始等待(等待一秒钟)

  • 检测到另一个键控 - 重新启动等待时间

  • 等待完成 - 获取价值并提交表单

在我开始编写我自己的版本之前(我真的是一个只有一点 js 的后端人员,我对所有事情都使用 jQuery),是否已经有一个现有的解决方案?这似乎是一个普遍的要求。也许是一个 jQuery 插件?如果不是,那么编写此代码的最简单和最好的方法是什么?

更新 - 为 Dan 添加了当前代码(下)

丹 - 这可能是相关的。我在页面上使用的一个 jQuery 插件(tablesorter)需要这个文件 - “tablesorter/jquery-latest.js”,如果包含它,它会导致您的代码出现与以前相同的错误:

jQuery("input#search").data("timeout", null) 未定义 http://192.168.0.234/javascripts/main.js?1264084467 第 11 行

也许不同的jQuery定义之间存在某种冲突?(或者其他的东西)

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

5 回答 5

24

抱歉,我还没有对此进行测试,这有点离题了,但是这些方面的东西应该可以解决问题。将 2000 更改为服务器帖子之间所需的毫秒数

<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>
于 2010-01-20T13:14:02.147 回答
7

这是你喜欢的 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);

像这样使用它:

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

默认情况下延迟半秒。

于 2011-05-19T05:16:47.710 回答
4

作为更新,我最终得到了这个似乎运作良好的结果:

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

然后我从相关页面的 document.ready 块中调用它

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

最好是创建一个使用此逻辑的新 jquery 事件,例如 .delayedKeyup 与 .keyup 并排,所以我可以对单个页面的 document.ready 块说类似的话。

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

但是,我不知道如何以这种方式自定义 jquery。不过,这是一项不错的家庭作业。

于 2010-01-22T17:36:16.977 回答
3

干得好,Max,这对我很有帮助!通过使其更通用,我对您的功能进行了轻微改进:

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

这样您就可以将它用于任何类型的事件,尽管 keyup 可能是这里最有用的。

于 2010-11-30T08:35:02.163 回答
0

我知道这是旧的,但这是我在寻找如何做这样的事情时的第一个结果,所以我想分享我的解决方案。我结合使用提供的答案来获得我需要的答案。

我想要一个与现有 jQuery 事件一样工作的自定义事件,它需要与keypress+ 删除、退格和回车一起使用。

这是我的 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);
            });
    }

我曾经$.proxy()在事件中保留上下文,尽管在性能方面可能有更好的方法来做到这一点。

要使用此插件,只需执行以下操作:

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

或者

$('#myElement').typePause({milliseconds: 500, [other data to pass to event]},function(e){ /* do stuff */ });    
于 2013-08-09T18:30:21.243 回答