jQuery DataTables:延迟搜索,直到键入3个字符或单击一个按钮


82

输入3个字符后,是否可以选择开始搜索?

我为同事显示了20,000个条目编写了一个PHP脚本,他们抱怨说,输入单词时,前几个字母会冻结所有内容。

另一种选择是通过单击按钮而不是通过字符键入来开始搜索。

下面是我当前的代码:

$("#my_table").dataTable( {
        "bJQueryUI": true,
        "sPaginationType": "full_numbers",
        "bAutoWidth": false,
        "aoColumns": [
                /* qdatetime */   { "bSearchable": false },
                /* id */          null,
                /* name */        null,
                /* category */    null,
                /* appsversion */ null,
                /* osversion */   null,
                /* details */     { "bVisible": false },
                /* devinfo */     { "bVisible": false, "bSortable": false }
        ],
        "oLanguage": {
                "sProcessing":   "Wait please...",
                "sZeroRecords":  "No ids found.",
                "sInfo":         "Ids from _START_ to _END_ of _TOTAL_ total",
                "sInfoEmpty":    "Ids from 0 to 0 of 0 total",
                "sInfoFiltered": "(filtered from _MAX_ total)",
                "sInfoPostFix":  "",
                "sSearch":       "Search:",
                "sUrl":          "",
                "oPaginate": {
                        "sFirst":    "<<",
                        "sLast":     ">>",
                        "sNext":     ">",
                        "sPrevious": "<"
                },
                "sLengthMenu": 'Display <select>' +
                        '<option value="10">10</option>' +
                        '<option value="20">20</option>' +
                        '<option value="50">50</option>' +
                        '<option value="100">100</option>' +
                        '<option value="-1">all</option>' +
                        '</select> ids'
        }
} );

Answers:


75

版本1.10的解决方案-

在这里找到一个完整的答案但没有找到答案之后,我已经写了这个(利用文档中的代码,还有一些答案)。

以下代码可延迟搜索,直到至少输入3个字符:

// Call datatables, and return the API to the variable for use in our code
// Binds datatables to all elements with a class of datatable
var dtable = $(".datatable").dataTable().api();

// Grab the datatables input box and alter how it is bound to events
$(".dataTables_filter input")
    .unbind() // Unbind previous default bindings
    .bind("input", function(e) { // Bind our desired behavior
        // If the length is 3 or more characters, or the user pressed ENTER, search
        if(this.value.length >= 3 || e.keyCode == 13) {
            // Call the API search function
            dtable.search(this.value).draw();
        }
        // Ensure we clear the search if they backspace far enough
        if(this.value == "") {
            dtable.search("").draw();
        }
        return;
    });

3
对于那些无法正常使用的人,请尝试使用此功能init.dt,例如$('#yourTable').on('init.dt', function () { ... });
arao6 2014年

在版本11中,您需要首先设置搜索字符串,然后按如下所示运行fnDraw():$(“。datatable”)。dataTable()。api()。search(“ aaaa2”); $(“。 datatable“)。dataTable()。fnDraw()
Hesham Yassin

2
我有输入而不是keydown功能,现在可以正常工作了。谢谢
阿扎IDZ

1
@Maxime我将其回滚到有效的编辑状态,并且没有使那些错误的变量名不匹配。让我知道您是否仍然需要修改/关注。
random_user_name 2016年

1
@cale_b我可以确认这仍然适用于1.10.16。谢谢。
AnotherDeveloper

77

注意:这是针对更早版本的数据表的,请参阅jQuery数据表v1.10及更高版本的答案


这会将输入框的行为修改为仅在按下回车键或搜索中至少包含3个字符时过滤:

$(function(){
  var myTable=$('#myTable').dataTable();

  $('.dataTables_filter input')
    .unbind('keypress keyup')
    .bind('keypress keyup', function(e){
      if ($(this).val().length < 3 && e.keyCode != 13) return;
      myTable.fnFilter($(this).val());
    });
});

您可以在这里看到它的工作:http : //jsbin.com/umuvu4/2。我不知道为什么dataTables成员既绑定到keypress也绑定到keyup,但是尽管我认为keyup就足够了,但我还是重写了二者以保持兼容。

希望这可以帮助!


2
也注意到这一点。绑定到keypress和keyup意味着查询被触发两次。对于在家中观看的人,您应该只从解绑定和绑定中取出一个或另一个。
雷兔

1
按退格键时此解决方案不起作用。@Sam Barnes是最好的答案
Idrees Khan 2013年

2
作为萨姆·巴恩斯(Sam Barnes)出色答案的替代方案,您可以将其替换为,以解决退格(并清除字段)的问题e.keycode != 13,方法是e.keyCode > 13,当他们跳出字段时也会触发。
cincodenada 2013年

2
不幸的是这并不起作用与版本1.10
random_user_name

按照@ThunderRabbit所说的,我发现最好的方法是取消两者的绑定,但只重新绑定其中一个。 .unbind('keypress keyup') .bind('keypress', function(e) ...
nageeb 2015年

33

为什么不尝试这个扩展版本的Stony的答案:)

var searchWait = 0;
var searchWaitInterval;
$('.dataTables_filter input')
.unbind('keypress keyup')
.bind('keypress keyup', function(e){
    var item = $(this);
    searchWait = 0;
    if(!searchWaitInterval) searchWaitInterval = setInterval(function(){
        if(searchWait>=3){
            clearInterval(searchWaitInterval);
            searchWaitInterval = '';
            searchTerm = $(item).val();
            oTable.fnFilter(searchTerm);
            searchWait = 0;
        }
        searchWait++;
    },200);

});

这将延迟搜索,直到用户停止键入为止。

希望能帮助到你。


效果很好。但是我必须更改oTable.fnFilter(...)以引用我的数据表实例。
YudhiWidyatama

这实际上不是扩展版本,它是完全不同(但有用)的解决方案。不过,我对于searchWait参数无法完成的工作感到困惑,setTimeout(function(){...}, 600)因为该函数似乎并未在其他字符上重新触发。
cincodenada

@cincodenada必须为setInterval,因为它每200 / 600ms触发一次,并检查searchWait是否未重置为0。例如,如果继续在输入中输入内容,则始终将searchWait重置为0 =永远不会执行搜索。但是,我发现将searchWait用作整数,该整数为3,相当模糊。更好的将只是一个真/假标志,如果用户输入发生和setInterval的600
r3mark

3
从jqueryDatatables 1.10.3开始,为此提供了一个选项:searchDelay
panmari

1
@panmari-searchDelay只会延迟搜索指定的时间,然后(触发ajax)会在以后重新绘制表,而不是在用户停止键入我们大多数人期望的时间时。
克里斯·兰德扎

11

以下是使用1.10版中的api更改来处理它的方法

var searchbox = $('#promogrid_filter input');
var pgrid = $('#promogrid').DataTable();

//Remove default datatable logic tied to these events
searchbox.unbind();

searchbox.bind('input', function (e) {
   if(this.value.length >= 3) {
      pgrid.search(this.value).draw();
   }
   if(this.value == '') {
      pgrid.search('').draw();
   }
   return;
});

8

我的数据表版本1.10.10

我做了一些更改,现在可以使用了。因此,我正在共享,因为很难使其适用于1.10.10版本。感谢cale_b,Stony和Sam Barnes。查看代码,看看我做了什么。

    var searchWait = 0;
    var searchWaitInterval;
    $('.dataTables_filter input')
    .unbind() // leave empty here
    .bind('input', function(e){ //leave input
        var item = $(this);
        searchWait = 0;
        if(!searchWaitInterval) searchWaitInterval = setInterval(function(){
            if(searchWait >= 3){
                clearInterval(searchWaitInterval);
                searchWaitInterval = '';
                searchTerm = $(item).val();
                oTable.search(searchTerm).draw(); // change to new api
                searchWait = 0;
            }
            searchWait++;
        },200);

    });

7

这是一个类似于插件的脚本,用于扩展数据表。

jQuery.fn.dataTableExt.oApi.fnSetFilteringEnterPress = function ( oSettings ) {
    var _that = this;

    this.each( function ( i ) {
        $.fn.dataTableExt.iApiIndex = i;
        var
            $this = this, 
            oTimerId = null, 
            sPreviousSearch = null,
            anControl = $( 'input', _that.fnSettings().aanFeatures.f );

            anControl
              .unbind( 'keyup' )
              .bind( 'keyup', function(e) {

              if ( anControl.val().length > 2 && e.keyCode == 13){
                _that.fnFilter( anControl.val() );
              }
        });

        return this;
    } );
    return this;
}

用法:

$('#table').dataTable().fnSetFilteringEnterPress();

您是否不想“如果长度大于2按Enter键?”if ( anControl.val().length > 2 || e.keyCode == 13)
Jeromy French

是的,这也有效。我只是更加侧重于验证方面,因此,即使传递了空字符串并且按下了Enter键,也不会发生任何事情。
克里斯蒂安·诺埃尔

6

要执行的操作是在用户在搜索框中键入最小字符后调用服务器调用,您可以遵循Allan的建议

自定义fnSetFilteringDelay()插件API函数,以在设置过滤器之前在字符串长度上添加额外的条件,同时考虑输入空白字符串以清除过滤器

因此,对于最少3个字符,只需将插件中的第19行更改为:

if ((anControl.val().length == 0 || anControl.val().length >= 3) && (sPreviousSearch === null || sPreviousSearch != anControl.val())) {

5

这适用于DataTables 1.10.4:

var table = $('#example').DataTable();

$(".dataTables_filter input")
    .unbind()
    .bind('keyup change', function(e) {
        if (e.keyCode == 13 || this.value == "") {
            table
                .search(this.value)
                .draw();
        }
    });

JSFiddle


4

对于1.10版本,请在选项中将此代码添加到您的javascript中。initComplete覆盖搜索方法,并等待写入3个字符。多亏了http://webteamalpha.com/triggering-datatables-to-search-only-on-enter-key-press/给我带来的启发。

    var dtable= $('#example').DataTable( {
        "deferRender": true,
        "processing": true,
        "serverSide": true,


        "ajax": "get_data.php",
        "initComplete": function() {
            var $searchInput = $('div.dataTables_filter input');

            $searchInput.unbind();

            $searchInput.bind('keyup', function(e) {
                if(this.value.length > 3) {
                    dtable.search( this.value ).draw();
                }
            });
        }

    } );
} );

3

用这个

   "fnServerData": function (sSource, aoData, fnCallback, oSettings) {

            if ($("#myDataTable_filter input").val() !== "" && $("#myDataTable_filter input").val().length < 3)
                return;
            oSettings.jqXHR = $.ajax({
                "dataType": 'json',
                "timeout":12000,
                "type": "POST",
                "url": sSource,
                "data": aoData,
                "success": fnCallback
            });
        }

+1好。这很好地集成在数据表定义中。顺便说一句,在我的情况下,只返回aoData [5] ['value'] ['value'](在输入字段中键入的文本)就不返回整个aoData obj就足够了。
Werner

3

尽管它不能回答原始问题,但我对数据表的搜索却很复杂且缓慢。每次按键后都会触发filter事件,这意味着在10个字符之后会有相当明显的延迟。因此,通过在按下按键之后在触发过滤事件之前引入短暂的延迟(随后的按键重置计数器并阻止了之前的搜索),我能够使搜索看起来更快。其他人可能会发现这很有帮助。

我用斯托尼和克里斯蒂安·诺埃尔的答案来做到这一点:

var dataTableFilterTimeout;
var dataTableFilterWait = 200; // number of milliseconds to wait before firing filter

$.fn.dataTableExt.oApi.fnSetFilteringEnterPress = function ( oSettings ) {
    var _that = this;
    this.each( function ( i ) {
        $.fn.dataTableExt.iApiIndex = i;
        var $this = this;
        var oTimerId = null;
        var sPreviousSearch = null;
        anControl = $( 'input', _that.fnSettings().aanFeatures.f );
        anControl.unbind( 'keyup' ).bind( 'keyup', function(e) {
            window.clearTimeout(dataTableFilterTimeout);
            if ( anControl.val().length > 2 || e.keyCode == 13){
                dataTableFilterTimeout = setTimeout(function(){
                    _that.fnFilter( anControl.val() );
                },dataTableFilterWait);
            }
        });
        return this;
    } );
    return this;
}

3

您可以以此延迟对服务器的ajax调用

var search_thread = null;
    $(".dataTables_filter input")
        .unbind()
        .bind("input", function(e) { 
            clearTimeout(search_thread);
            search_thread = setTimeout(function(){
                var dtable = $("#list_table").dataTable().api();
                var elem = $(".dataTables_filter input");
                return dtable.search($(elem).val()).draw();
            }, 300);
        });

如果两次按键之间的时间少于300毫秒,此代码将停止ajax调用,这样,当您写一个单词时,只有一个ajax调用将运行,并且仅当您停止键入时才运行。您可以“玩”延迟参数(300)以获得更多或更少的延迟


2

您可能需要修改插件。

而不是将其设置为X个字符,而是使用延迟功能,这样,一旦他们停止键入1秒钟左右,搜索就会开始。

因此,当前触发搜索的keydown / keyup绑定将使用计时器进行修改...

var timer;
clearTimeout(timer);
timer = setTimeout(searchFunctionName, 1000 /* timeToWaitInMS */);

1
“修改插件”是指编辑jquery.dataTables.js吗?而且您知道以后如何“最小化”它吗?
亚历山大·法伯

2

使用API​​并正确解除对“输入”的绑定的数据表1.10.12的固定版本。还添加了在字符限制下按退格键清除搜索的功能。

    // Create the Datatable
    var pTable = $('#pTable').DataTable();

    // Get the Datatable input box and alter events
    $('.dataTables_filter input')
    .unbind('keypress keyup input')
    .bind('keypress keyup input', function (e) {
        if ($(this).val().length > 2) {
            pTable.search(this.value).draw();
        } else if (($(this).val().length == 2) && (e.keyCode == 8)) {
            pTable.search('').draw();
        }
    });

2

如果您使用的是旧版本,则看起来像它。理查德的解决方案效果很好。但是当我使用它时,我只是添加了新事件,而不是删除。因为在运行代码时,尚未创建表。因此,我发现有一个fnInitComplete方法(在创建表时触发),并将其应用于Ricard的解决方案。这里是

$("#my_table").dataTable( {
        "bJQueryUI": true,
        "sPaginationType": "full_numbers",
        "bAutoWidth": false,
         ...
         ...,
         "fnInitComplete": function (oSettings, json) {
                    var activeDataTable = $(this).DataTable();
                    $("#my_table_filter input")
                        .unbind('keypress keyup')
                        .bind('keypress keyup', function (e) {

                        if ($(this).val().length < 3 || e.keyCode !== 13) return;
                        activeDataTable.fnFilter($(this).val());
                    });
                }

2

使用3个字符后,可以在Medtronic数据表上使用此代码或其他代码进行搜索:

        onDataLoad: function (RequestGrid) {
            // execute some code on ajax data load
            var searchInput = $('div.dataTables_filter input').val();
            if (searchInput.length() > 3 || searchInput.length() ==0) {
                alert(searchInput);
                dt.draw();
            }
            else {
                return false;
            }
        },

首次播放时searchInput.length()== 0。


1

您是否可以编写自己的函数来测试附加到onKeyUp事件处理程序的输入字符串的长度,并在达到最小长度后触发搜索功能?

类似于以下内容:

input.onKeyUp(function(){
    if(input.length> 3){
        mySearchfunction();
    }
});

...就是以伪代码的一种方式,但是您得到了jist。


1

您可以使用名称minlength来使用参数,以便将搜索限制为3个字符:

function(request, response) {
    $.getJSON("/speakers/autocomplete", {  
        q: $('#keywordSearch').val()
    }, response);
}, minLength: 3

1

您可以使用data.currentTarget.value.length获取要传递的数据的长度,请参见下文。

$('[id$="Search"]').keyup(function (data) {
            if (data.currentTarget.value.length > 2 || data.currentTarget.value.length == 0) {
                if (timoutOut) { clearTimeout(timoutOut); }
                timoutOut = setTimeout(function () {
                    var value = $('[id$="Search"]').val();
                    $('#jstree').jstree(true).search(value);
                }, 250);
            }
        });

并且显然您希望在删除文本时运行此代码,因此将值设置为0


0

这适用于DataTables 1.10.19版本。它只需要在您的网站模板中包含js,这对在不同页面上配置了多个dataTables的网站很有用。对于任何缓慢的xhr加载表也很有用,在所有当前运行完成之前,不允许任何新的xhr请求。所使用的搜索功能非常类似于插件如何设置的搜索功能原本。

(function(window, document, $){
var xhring = 0;

$(document).on( 'preXhr.dt', function () {
    xhring++;
} );
$(document).on( 'xhr.dt', function () {
    xhring--;
} );

//at a minimum wait the full freq, and wait for any pending XHR requests to finish before calling fn
function choke( fn, freq ) {
    var
        frequency = freq !== undefined ? freq : 200,
        last,
        timerFn,
        timer;

    return function () {
        var
            that = this,
            args = arguments;

        timerFn = function () {
            if (xhring || +new Date() < last + frequency) {
                clearTimeout( timer );
                timer = setTimeout( timerFn, frequency);
            } else {
                fn.apply( that, args );
            }
        }
        last = +new Date();

        clearTimeout( timer );
        timer = setTimeout( timerFn, frequency );
    };
}

//See https://github.com/DataTables/DataTables/blob/156faa83386460c578e00c460eca9766e38a0c5f/media/js/jquery.dataTables.js
//See https://github.com/DataTables/Plugins/blob/master/features/searchHighlight/dataTables.searchHighlight.js
$(document).on( 'preInit.dt', function (e, settings, json) {
    var previousSearch = settings.oPreviousSearch;

    var searchFn = function() {
        /* Update all other filter input elements for the new display */
        var val = !this.value ? "" : this.value; // mental IE8 fix :-(

        /* Now do the filter */                                                                                                  
        if ( val != previousSearch.sSearch && (val.length >= 3 || val == "")) {
            $.fn.dataTable.ext.internal._fnFilterComplete( settings, {
                "sSearch": val,
                "bRegex": previousSearch.bRegex,
                "bSmart": previousSearch.bSmart ,
                "bCaseInsensitive": previousSearch.bCaseInsensitive
            } );

            // Need to redraw, without resorting
            settings._iDisplayStart = 0;
            $.fn.dataTable.ext.internal._fnDraw( settings );
        }
    };

    var searchDelay = settings.searchDelay !== null ?                                                                            
        settings.searchDelay :
        $.fn.dataTable.ext.internal._fnDataSource( settings ) === 'ssp' ?
            700 :
            200;

    var jqFilter = $( 'input', settings.aanFeatures.f )
        .off('keyup.DT search.DT input.DT paste.DT cut.DT')
        .on('keyup.DT search.DT input.DT paste.DT cut.DT', choke(searchFn, searchDelay))
        ;
} );

})(window, document, jQuery);

-1

您是否有理由不只是检查“更改”的长度?

$('.input').change(function() {
  if( $('.input').length > 3 ) {
     //do the search
  }
});

2
因为DataTables已经绑定到此,并自动调用搜索。您必须拦截/更改绑定。
random_user_name 2014年

-1

您需要修改jquery.datatables.js

-----更新了课程,您可以检查长度> 3,但是我认为您仍然需要计时器。如果您有大量数据,则不想在每次字符更新后都对其进行过滤。

在此方法内:

jqFilter.keyup( function(e) {
            if ( **this.value**.length > 3) {
                var n = oSettings.aanFeatures.f;
                for ( var i=0, iLen=n.length ; i<iLen ; i++ )
                {
                    if ( n[i] != this.parentNode )
                    {
                        $('input', n[i]).val( this.value );
                    }
                }
                /* Now do the filter */
                _fnFilterComplete( oSettings, { 
                    "sSearch": this.value, 
                    "bRegex":  oSettings.oPreviousSearch.bRegex,
                    "bSmart":  oSettings.oPreviousSearch.bSmart 
                } );
         }
        } );

像在答案之一中所示,将一个计时器添加到该快捷键中。

然后转到此站点http://jscompress.com/

过去的修改后的代码和js将变得最小化。


您好,谢谢-但是我可以添加$('。input')。length> 3或$(#input')。length> 3代替计时器吗?我不确定如何引用搜索字段。
亚历山大·法伯

当然,您可以检查长度> 3,但是我认为您仍然需要计时器。如果您有大量数据,则不想在每次字符更新后都对其进行过滤。我已对3个字符以上的长度进行了正确的检查,从而更新了答案。添加计时器是下一个有价值的步骤。
塔希尔·马利克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.