jQuery DataTables: отложите поиск до тех пор, пока не будут набраны 3 символа ИЛИ не будет нажата кнопка

83

Есть ли возможность начать поиск только после того, как будут введены 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'
        }
} );
Александр Фарбер
источник

Ответы:

76

Решение для версии 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;
    });
random_user_name
источник
3
Для тех из вас, у кого есть проблемы с тем, чтобы это работало, попробуйте использовать это в init.dtслучае, например $('#yourTable').on('init.dt', function () { ... });.
arao6
В версии 11 вам нужно сначала задать строку поиска, а затем запустить fnDraw () следующим образом: $ (". Datatable"). DataTable (). Api (). Search ("aaaa2"); $ (". datatable "). dataTable (). fnDraw ()
Хешам Ясин
2
У меня был ввод вместо функции нажатия клавиши, теперь она работает нормально. Спасибо
azza idz
1
@Maxime Я откатил его к редактированию, которое сработало и не сделало эти ошибочные несоответствия имен переменных. Сообщите мне, если вы считаете, что он все еще нуждается в редактировании / внимании
random_user_name 07
1
@cale_b Я могу подтвердить, что это все еще работает для 1.10.16. Спасибо.
AnotherDeveloper
77

Примечание: это было для гораздо более ранней версии таблиц данных, см. Этот ответ для jQuery datatables v1.10 и выше.


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

Надеюсь это поможет!

Ричард
источник
2
Заметил и это. Привязка как к нажатию клавиш, так и к нажатию клавиш означает, что запрос запускается дважды. Для тех, кто смотрит дома, вы должны просто вынуть одно или другое как из развязки, так и из привязки.
Thunder Rabbit
1
это решение не работает при нажатии клавиши Backspace. @Sam Barnes - лучший ответ
Idrees Khan
2
В качестве альтернативы отличному ответу Сэма Барнса вы можете изменить это, чтобы учесть отступ (и очистку поля), заменив его e.keycode != 13на e.keyCode > 13, который также будет срабатывать, когда они выходят из поля.
cincodenada
2
К сожалению, это не работает с версией 1.10
random_user_name
Следуя тому, что сказал @ThunderRabbit, лучший способ, который я нашел, - это отвязать оба, но только повторно связать одно или другое. .unbind('keypress keyup') .bind('keypress', function(e) ...
нагиб
33

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

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, это должен быть a setInterval, потому что он обновляется каждые 200/600 мс и проверяет, не был ли searchWait сброшен на 0. например, если вы продолжаете вводить что-то на вход, вы всегда сбрасываете searchWait на 0 = поиск никогда не выполняется. Однако я считаю использование searchWait целым числом, которое считается до 3, довольно непонятным. Лучше было бы просто установить флаг «истина / ложь», если пользователь setInterval
вводит
3
Так jqueryDatatables 1.10.3, есть возможность для этого: searchDelay
panmari
1
@panmari - searchDelay просто задержит поиск на указанное время и будет (запускать ajax) перерисовать таблицу позже, а не тогда, когда пользователь перестанет печатать, чего многие из нас ожидали.
Крис Ландеза
12

Вот как с этим справиться с изменением 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;
});
Чад Куэн
источник
8

Моя версия таблиц данных 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);

    });
Занте
источник
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 или нажата клавиша ввода?»if ( anControl.val().length > 2 || e.keyCode == 13)
Джероми Френч,
да, это тоже работает. Я просто больше сосредоточен на стороне проверки, так что даже если передана пустая строка и нажата клавиша ввода, ничего не произойдет.
Кристиан Ноэль
6

Для этого нужно вызвать серверный вызов после того, как пользователь набрал минимальные символы в поле поиска, вы можете следовать предложению Аллана :

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

Таким образом, если вы хотите использовать минимум 3 символа, просто измените строку №19 в плагине на:

if ((anControl.val().length == 0 || anControl.val().length >= 3) && (sPreviousSearch === null || sPreviousSearch != anControl.val())) {
Мариус Бутук
источник
6

Это работает с 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();
                }
            });
        }

    } );
} );
Mato Gallardo
источник
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, а только aoData [5] ['значение'] ['значение'] (текст, введенный в поле ввода).
Вернер
3

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

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

Сион Бен Яков
источник
2

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

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

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

var timer;
clearTimeout(timer);
timer = setTimeout(searchFunctionName, 1000 /* timeToWaitInMS */);
smdrager
источник
1
Под «изменением плагина» вы имеете в виду редактирование jquery.dataTables.js? А знаете, как потом его "минимизировать"?
Александр Фарбер
2

Исправленная версия для таблиц данных 1.10.12 с использованием API и правильной отмены привязки «input». Также добавлена ​​очистка поиска по пробелу ниже лимита символов.

    // 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());
                    });
                }
Cihancoskun
источник
2

Вы можете использовать этот код в таблице данных 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 для первого показа.

LPLN
источник
1

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

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

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

... то есть псевдокодом, но вы понимаете суть.

Крис
источник
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 в шаблон вашего сайта - полезно для сайта, на котором настроено несколько таблиц данных на разных страницах. Также полезно для любых таблиц с медленной загрузкой 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
-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 символов. Добавление таймера - следующий важный шаг.
Тахир Малик