【问题标题】:Get text from field on keyup, but with delay for further typing从键盘上的字段中获取文本,但延迟进一步输入
【发布时间】:2010-01-20 12:24:07
【问题描述】:

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

最好是这样的

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

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

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

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

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

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;
}

【问题讨论】:

    标签: javascript jquery jquery-plugins jquery-events


    【解决方案1】:

    抱歉,我还没有对此进行测试,这让我有点想不通,但是这些方面的东西应该可以解决问题。将 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>
    

    【讨论】:

    • 在 setTimeout 函数中,您可能能够将 jQuery('#myelement') 更改为 jQuery(this)
    • 谢谢 dan - 它在第一个 .data('timeout', null) 处倒下,说它不是一个函数。在调用 .data 之前,我是否必须执行其他操作?在这种情况下,我在文本字段中调用它。
    • Max,你确定你已经包含了 jQuery 库并将#myelement 更改为你自己的元素选择器吗?我刚刚对其进行了快速测试,它的工作点在 :) Dan
    • 此外,您还需要确保在 jQuery 加载函数中拥有它。我的原始答案已使用完整代码进行了更新。丹
    • 啊,现在很好用,谢谢。之前,我从另一个函数内部调用了您之前的条目。我以前没有遇到过 jquery 加载函数,就像我说我有点 js 新手一样。再次感谢!最大
    【解决方案2】:

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

    默认延迟半秒。

    【讨论】:

    • 我会减少使用(但似乎无法正确格式化?):var trimmedVal = $.trim($(this).val()); if (trimmedVal.length &gt; 0) { //reload my data store using the filter string. }
    【解决方案3】:

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

    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。不过,这是一项不错的家庭作业。

    【讨论】:

    • 嘿 Max,使用 typeof 清除超时而无需全局显式创建变量的好主意 :)
    【解决方案4】:

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

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

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

    【讨论】:

      【解决方案5】:

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

      我想要一个与现有 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 */ });    
      

      【讨论】:

        猜你喜欢
        • 2012-12-27
        • 2011-02-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-17
        • 2015-09-25
        • 1970-01-01
        相关资源
        最近更新 更多