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

3
Для тих, хто має проблеми з тим, щоб це працювало, спробуйте використовувати це у init.dtвипадку, наприклад $('#yourTable').on('init.dt', function () { ... });.
arao6,

У версії 11 потрібно спочатку встановити рядок пошуку, а потім запустити fnDraw () таким чином: $ (". Datatable"). DataTable (). Api (). Search ("aaaa2"); $ (". datatable "). dataTable (). fnDraw ()
Hesham Yassin

2
У мене був ввід замість функції клавіатури, зараз він працює добре. Дякую
azza idz

1
@Maxime Я повернув його до редагування, яке спрацювало і не зробило тих помилкових розбіжностей імен змінних. Повідомте мене, якщо ви вважаєте, що це все ще потребує редагувань / уваги.
random_user_name

1
@cale_b Я можу підтвердити, що це все ще працює на 1.10.16. Дякую.
розробник

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 прив'язані як до натискання клавіш, так і до клавіатури, але я перевизначаю їх обох, щоб залишатися сумісними, хоча я думаю, що клавіатури достатньо.

Сподіваюся, це допомагає!


2
Помітив і це. Прив’язка як до натискання клавіші, так і до клавіатури означає, що запит запускається двічі. Тим, хто дивиться вдома, слід просто вийняти те чи інше як з розв’язання, так і зв’язування.
Громовий Кролик

1
це рішення не працює при натисканні зворотного простору. @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) ...
nageeb

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 мс і перевіряє, чи не було resetWait встановлено на 0. Наприклад, якщо ви продовжуєте щось вводити у вхід, ви завжди скидаєте searchWait на 0 = пошук ніколи не виконується. Однак я вважаю використання searchWait цілим числом, яке рахує до 3, досить неясним. Краще було б просто істинним / хибним прапором, якби введення користувачем відбулося і setIntervalзначення 600.
r3mark

3
Так jqueryDatatables 1.10.3, є можливість для цього: searchDelay
panmari

1
@panmari - searchDelay просто затримає пошук на вказаний час і (запустить ajax) перекроє таблицю згодом, а не тоді, коли користувач перестав вводити текст, чого очікували більшість з нас.
Chris Landeza,

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, 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 або натиснута клавіша введення?if ( anControl.val().length > 2 || e.keyCode == 13)
Джеромі Френч

так, це теж працює. я просто більше зосереджений на стороні перевірки, так що навіть якщо передано порожній рядок і натиснуто клавішу Enter, нічого не відбувається.
Крістіан Ноель

7

Це працює в 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


6

Для цього потрібно викликати виклик сервера після того, як користувач набрав у полі пошуку мінімальні символи, ви можете слідувати пропозиції Аллана :

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

Отже, принаймні 3 символи, просто змініть рядок № 19 у плагіні на:

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

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 obj, а лише aoData [5] ['value'] ['value'] (текст, набраний у полі введення).
Вернер,

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

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 секунду.

Тож прив'язка клавіатури / клавіатури, яка в даний час ініціює пошук, буде змінена за допомогою таймера ...

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

1
Під "модифікувати плагін" ви маєте на увазі редагування jquery.dataTables.js? А чи знаєте ви, як потім його "мінімізувати"?
Олександр Фарбер

2

Виправлена ​​версія для таблиць даних 1.10.12 з використанням API та коректного розв’язування «вводу». Також додано пошук, очищений у зворотному просторі з обмеженням кількості символів.

    // 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 (запускається при створенні таблиці), і застосував його до рішення Рікарда. Ось

$("#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

Ви можете використовувати цей код на таблиці даних Medtronic або інший код для пошуку після використання 3 символів:

        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) {
        функція mySearch ();
    }
});

... тобто у вигляді псевдокоду, але ви отримуєте суть.


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 символів. Додавання таймера - наступний цінний крок.
Тахір Малік
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.