jQuery DataTables: Opóźnij wyszukiwanie do momentu wpisania 3 znaków LUB kliknięcia przycisku


83

Czy istnieje możliwość rozpoczęcia wyszukiwania dopiero po wpisaniu 3 znaków?

Napisałem skrypt PHP dla kolegów wyświetlających 20 000 wpisów i narzekają, że przy wpisywaniu słowa pierwsze kilka liter powoduje zawieszenie się wszystkiego.

Alternatywą byłoby rozpoczęcie wyszukiwania kliknięciem przycisku, a nie wpisywaniem znaków.

Poniżej znajduje się mój aktualny kod:

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

Odpowiedzi:


76

Rozwiązanie dla wersji 1.10 -

Po szukaniu tutaj pełnej odpowiedzi i jej nie znalezieniu, napisałem to (wykorzystując kod z dokumentacji i kilka odpowiedzi tutaj).

Poniższy kod opóźnia wyszukiwanie do momentu wprowadzenia co najmniej 3 znaków:

// 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
Dla tych z Was, którzy mają problemy z uruchomieniem tego, spróbuj użyć tego w init.dtprzypadku, np $('#yourTable').on('init.dt', function () { ... });.
arao6,

W wersji 11 musisz najpierw ustawić szukany ciąg, a następnie uruchomić fnDraw () w następujący sposób: $ (". Datatable"). DataTable (). Api (). Search ("aaaa2"); $ (". datatable "). dataTable (). fnDraw ()
Hesham Yassin,

2
Miałem dane wejściowe zamiast funkcji keydown, teraz działa ładnie. Dziękuję
azza idz

1
@Maxime Przywróciłem to z powrotem do edycji, która działała i nie spowodowałem tych błędnych niezgodności nazw zmiennych. Daj mi znać, jeśli uważasz, że nadal wymaga edycji / uwagi.
random_user_name

1
@cale_b Mogę potwierdzić, że to nadal działa w wersji 1.10.16. Dziękuję Ci.
AnotherDeveloper

77

Uwaga: dotyczyło to znacznie wcześniejszej wersji tabel danych, zobacz tę odpowiedź dla danych jQuery w wersji 1.10 i nowszych.


Spowoduje to zmianę zachowania pola wejściowego, aby filtrować tylko po naciśnięciu klawisza return lub w wyszukiwaniu są co najmniej 3 znaki:

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

Możesz zobaczyć, jak działa tutaj: http://jsbin.com/umuvu4/2 . Nie wiem, dlaczego ludzie z dataTables wiążą się zarówno z klawiszem, jak i klawiszem, ale nadpisuję oba z nich, aby zachować zgodność, chociaż myślę, że kluczowanie jest wystarczające.

Mam nadzieję że to pomoże!


2
Zauważyłem to również. Powiązanie zarówno z klawiszem, jak i klawiszem oznacza, że ​​zapytanie jest uruchamiane dwukrotnie. Dla tych, którzy oglądają w domu, powinniście po prostu wyjąć jedną lub drugą z obu wiązań i wiązań.
Thunder Rabbit

1
to rozwiązanie nie działa po naciśnięciu klawisza Backspace. @Sam Barnes to najlepsza odpowiedź
Idrees Khan

2
Jako alternatywę dla doskonałej odpowiedzi Sama Barnesa możesz to zmienić, aby uwzględnić cofanie się (i czyszczenie pola), zastępując e.keycode != 13je e.keyCode > 13, które również będą uruchamiane, gdy wyjdą z pola.
cincodenada

2
Niestety to nie działa z wersją 1.10
random_user_name

Zgodnie z tym, co powiedział @ThunderRabbit, najlepszym sposobem, jaki znalazłem, było rozpięcie obu, ale tylko ponowne powiązanie jednego lub drugiego. .unbind('keypress keyup') .bind('keypress', function(e) ...
nageeb

33

Dlaczego nie wypróbować tej rozszerzonej wersji odpowiedzi Stony'ego :)

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

});

Spowoduje to opóźnienie wyszukiwania do momentu, gdy użytkownik przestanie pisać.

Mam nadzieję, że to pomoże.


działa dobrze. ale muszę zmienić oTable.fnFilter (...), aby odwołać się do mojej instancji tabeli danych.
YudhiWidyatama

To nie jest tak naprawdę rozszerzona wersja, to zupełnie inne (ale przydatne) rozwiązanie. Nie mam jednak pojęcia, co robi parametr searchWait, czego nie można osiągnąć setTimeout(function(){...}, 600), ponieważ funkcja nie wydaje się być ponownie uruchamiana na kolejnych znakach.
cincodenada

@cincodenada musi to być a setInterval, ponieważ jest odświeżane co 200/600 ms i sprawdza, czy funkcja searchWait nie została zresetowana do 0. np. jeśli nadal będziesz wprowadzać coś do wejścia, zawsze zresetujesz searchWait do 0 = wyszukiwanie nigdy nie jest wykonywane. Uważam jednak, że użycie searchWait jako liczby całkowitej, która liczy do 3, jest raczej niejasne. Lepiej byłoby po prostu prawdziwą / fałszywą flagą, gdyby nastąpiło wejście użytkownika i setInterval600.
r3mark

3
Od wersji jqueryDatatables 1.10.3 istnieje opcja: searchDelay
panmari

1
@panmari - searchDelay po prostu opóźni wyszukiwanie o określony czas i (wyzwoli Ajax) później przerysuje tabelę, a nie gdy użytkownik przestanie pisać, czego większość z nas oczekuje.
Chris Landeza

12

Oto jak sobie z tym poradzić ze zmianą interfejsu API w wersji 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

Moja wersja danych 1.10.10

Zmieniłem trochę rzeczy i teraz działa. Więc udostępniam, ponieważ trudno było sprawić, by działało w wersji 1.10.10. Dzięki cale_b, Stony i Sam Barnes. Spójrz na kod, aby zobaczyć, co zrobiłem.

    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

Oto skrypt podobny do wtyczki, który rozszerza dane.

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

stosowanie:

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

Nie chcesz "jeśli długość jest większa niż 2 lub wciśnięty klawisz Enter?if ( anControl.val().length > 2 || e.keyCode == 13)
Jeromy Francuski

tak, to też działa. jestem po prostu bardziej skoncentrowany na stronie walidacji, więc nawet jeśli przekazano pusty ciąg i naciśnięto klawisz Enter, nic się nie dzieje.
Christian Noel

6

Aby to zrobić, wywołać wywołanie serwera po wpisaniu przez użytkownika minimalnych znaków w polu wyszukiwania, możesz postępować zgodnie z sugestią Allana :

dostosuj funkcję API wtyczki fnSetFilteringDelay (), aby dodać dodatkowy warunek do długości łańcucha przed ustawieniem filtru, uwzględniając również wprowadzenie pustego ciągu w celu wyczyszczenia filtra

Więc dla minimum 3 znaków, po prostu zmień wiersz nr 19 we wtyczce na:

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

6

Działa to w 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

dla wersji 1.10 dodaj ten kod do swojego javascript w opcjach. InitComplete zastępuje metodę wyszukiwania i czeka na zapisanie 3 znaków. Podziękowania dla http://webteamalpha.com/triggering-datatables-to-search-only-on-enter-key-press/ za danie mi światła.

    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

Użyj tego

   "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 miło. To ładnie integruje się z definicją danych. btw w moim przypadku wystarczyło nie zwrócić całego obiektu aoData, a jedynie aoData [5] ['value'] ['value'] (tekst wpisany w polu wejściowym).
Werner,

3

chociaż nie odpowiada na pierwotne pytanie, przeszedłem złożone i powolne wyszukiwanie w moich plikach danych. zdarzenie filtra było uruchamiane po każdym naciśnięciu klawisza, co oznaczało dość zauważalne opóźnienie po 10 znakach. więc wprowadzając krótkie opóźnienie po naciśnięciu klawisza przed uruchomieniem zdarzenia filtrującego, w którym kolejne naciśnięcie klawisza resetuje licznik i uniemożliwia poprzednie wyszukiwanie, udało mi się sprawić, że wyszukiwanie wydawało się znacznie szybsze. inni mogą uznać to za pomocne.

Użyłem odpowiedzi Stony and Christian Noel, aby to zrobić:

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

Możesz przez to opóźnić wywołanie AJAX do serwera

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

Ten kod zatrzyma wywołanie Ajax, jeśli czas między naciśnięciem klawisza jest krótszy niż 300 ms, w ten sposób, gdy napiszesz słowo, uruchomi się tylko jedno wywołanie Ajax i tylko wtedy, gdy przestaniesz pisać. Możesz „grać” z parametrem opóźnienia (300), aby uzyskać mniej lub więcej opóźnienia


2

Prawdopodobnie będziesz musiał zmodyfikować wtyczkę.

Zamiast tworzyć X znaków, użyj opóźnienia, więc wyszukiwanie rozpocznie się, gdy przestaną pisać na 1 sekundę.

Tak więc powiązanie keydown / keyup, które obecnie uruchamia wyszukiwanie, zostanie zmodyfikowane za pomocą timera ...

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

1
Mówiąc „zmodyfikuj wtyczkę”, masz na myśli edycję pliku jquery.dataTables.js? Czy wiesz, jak później to „zminimalizować”?
Alexander Farber,

2

Poprawiona wersja dla danych 1.10.12 wykorzystująca API i poprawne rozpinanie 'wejścia'. Dodano również jasne wyszukiwanie w backspace poniżej limitu znaków.

    // 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

Jeśli używasz starej wersji, wygląda na to. Rozwiązanie Richarda działa dobrze. Ale kiedy go używam, po prostu dodałem nowe wydarzenia, nie usuwając. Ponieważ po uruchomieniu kodu tabela nie jest jeszcze utworzona. Odkryłem więc, że istnieje metoda fnInitComplete (uruchamiaj po utworzeniu tabeli) i zastosowałem ją do rozwiązania Ricarda. Tutaj jest

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

Możesz użyć tego kodu w bazie danych Medtronic lub innym kodzie do wyszukiwania po użyciu 3 znaków:

        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 dla pierwszego pokazu.


1

Czy możesz napisać własną funkcję do testowania długości wprowadzonego ciągu dołączonego do procedury obsługi zdarzeń onKeyUp i wyzwolić funkcję wyszukiwania po osiągnięciu minimalnej długości?

Coś w rodzaju:

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

... to znaczy w formie pseudokodu, ale masz jist.


1

Możesz użyć parametru według nazwy minlength, aby ograniczyć wyszukiwanie do 3 znaków:

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

1

Długość przekazywanych danych można uzyskać za pomocą parametru data.currentTarget.value.length, patrz poniżej.

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

i oczywiście chciałbyś, aby ten kod działał podczas usuwania tekstu, więc ustaw wartość na 0


0

Działa to z DataTables w wersji 1.10.19. Wymaga tylko włączenia js do szablonu witryny - przydatne w przypadku witryny, która ma wiele dataTables skonfigurowanych na różnych stronach. Przydatne również dla dowolnych wolno ładujących się tabel xhr, nie zezwala na żadne nowe żądania xhr, dopóki wszystkie aktualnie uruchomione nie zostaną zakończone. Funkcja wyszukiwania używany jest bardzo podobny do tego, jak Wtyczka ustawia funkcję wyszukiwania pierwotnie.

(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

Czy jest jakiś powód, dla którego nie sprawdzałeś długości po prostu po „zmianie”?

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

2
Ponieważ DataTables jest już z tym powiązany i automatycznie wywołuje wyszukiwanie. Musisz przechwycić / zmienić wiązania.
random_user_name

-1

Musisz zmodyfikować plik jquery.datatables.js

----- zaktualizowano oczywiście możesz sprawdzić długość> 3, ale myślę, że nadal potrzebujesz timera. jeśli masz dużo danych, nie chcesz filtrować ich po każdej aktualizacji postaci.

W ramach tej metody:

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

Dodaj licznik czasu do klucza, jak pokazano w jednej z odpowiedzi.

Następnie przejdź do tej witryny http://jscompress.com/

Po przejściu zmodyfikowanego kodu plik js zostanie zminimalizowany.


Witam, dziękuję - ale czy mogę dodać $ ('. Input'). Length> 3 or $ (# input '). Length> 3 check zamiast timera? Nie jestem jednak pewien, jak odwołać się do pola wyszukiwania.
Alexander Farber,

oczywiście możesz sprawdzić długość> 3, ale myślę, że nadal potrzebujesz timera. jeśli masz dużo danych, nie chcesz filtrować ich po każdej aktualizacji postaci. Zaktualizowałem odpowiedź, odpowiednio zaznaczając długość powyżej 3 znaków. Dodanie timera to kolejny cenny krok.
Tahir Malik
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.