jQuery DataTables: задержка поиска до ввода 3 символов или нажатия кнопки

есть ли возможность начать поиск только после ввода 3 символов?

Я написал PHP-скрипт для коллег, отображающих 20 000 записей, и они жалуются, что при вводе слова первые несколько букв заставляют все замереть.

альтернативой было бы начать поиск нажатием кнопки, а не вводом символов.

ниже мой текущий код:

$("#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'
        }
} );

19 ответов


решение для версии 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;
    });

Примечание: это было для гораздо более ранней версии таблиц данных, пожалуйста, смотрите ответ для jQuery datatables 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 привязаны к обоим нажатие клавиши и keyup, но я переопределяю оба из них, чтобы оставаться совместимыми, хотя я думаю, что keyup достаточно.

надеюсь, что это помогает!


почему бы не попробовать эту расширенную версию ответа Стоуни:)

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

});

это задержит поиск, пока пользователь не перестанет печатать.

надеюсь, что это помогает.


вот как справиться с этим с изменением api в версии 1.10

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

вот плагин-подобный скрипт, который расширяет datatables.

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();

чтобы сделать, это вызвать вызов сервера после того, как пользователь набрал символы mininum в поле поиска, вы можете следовать Аллан предложение:

настройки fnSetFilteringDelay () функция API плагина добавить дополнительное условие для длины строки перед установкой фильтра, также учитывая пустую строку ввода, чтобы очистить фильтр

поэтому для минимум 3 символов просто измените строку #19 в плагин в:

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

это работает на DataTables 10.0.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


использовать

   "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.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();
                }
            });
        }

    } );
} );

хотя он не отвечает на исходный вопрос, у меня был сложный и медленный поиск в моих datatables. событие фильтра срабатывало после каждого нажатия клавиши, что означало довольно заметную задержку после 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;
}

вы можете отложить вызов 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);
        });

этот код остановит вызов ajax, если время между нажатием клавиши составляет менее 300 мс, таким образом, когда вы пишете слово, будет выполняться только один вызов ajax и только при остановке ввода. Вы можете "играть" с задержкой param (300), чтобы получить более или менее задержку


моя версия datatables 1.10.10

Я изменил некоторые вещи, и теперь он работает. Итак, я делюсь, потому что было трудно заставить его работать для версии 1.10.10. Благодаря cale_b, каменистые и Сэм Барнс. Посмотрите на код, чтобы увидеть, что я сделал.

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

    });

вероятно, вам придется изменить плагин.

и вместо того, чтобы делать это X символов, используйте задержку, поэтому поиск начинается, как только они перестали печатать на 1 секунду или около того.

таким образом, привязка keydown/keyup, которая в настоящее время запускает поиск, будет изменена с помощью таймера...

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

вы можете получить длину данных, которые передаются с помощью данных.currentTarget.значение.длина, см. ниже.

$('[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


исправлена версия для datatables 1.10.12 с помощью API и правильно разматывает "вход". Также добавлен поиск clear на backspace под лимитом символов.

    // 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();
        }
    });

можете ли вы написать свою собственную функцию, чтобы проверить длину строки inputed, прикрепленной к обработчику событий onKeyUp, и запустить функцию поиска после достижения минимальной длины?

что-то вроде:

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

...то есть, в псевдо-коде, но вы получаете jist.


вы можете использовать параметр по имени minlength, чтобы ограничить поиск до 3 символов:

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

есть ли причина, по которой вы не будете просто проверять длину на "change"?

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

вам нужно изменить jquery.объекты DataTable.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 
                } );
         }
        } );

добавьте таймер в keyup, как показано в одном из ответов.

затем перейдите на этот сайт http://jscompress.com/

и прошлое ваш измененный код и js Wil будут уменьшены.