jQuery DataTables: Delay search until 3 characters been typed OR a button clicked

JqueryDatatables

Jquery Problem Overview


Is there please an option to start the search only after 3 characters have been typed in?

I have written a PHP-script for colleagues displaying 20,000 entries and they complain, that when typing a word, the first few letters cause everything to freeze.

An alternative would be to have the search to be started by a button clicked and not by character typing.

Below is my current code:

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

Jquery Solutions


Solution 1 - Jquery

Solution for version 1.10 -

After looking here for a complete answer and not finding one, I've written this (utilizing code from the documentation, and a few answers here).

The below code works to delay searching until at least 3 characters are entered:

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

Solution 2 - Jquery

Note: This was for a much earlier version of data tables, please see this answer for jQuery datatables v1.10 and above.


This will modify the behaviour of the input box to only filter when either return has been pressed or there are at least 3 characters in the search:

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

You can see it working here: http://jsbin.com/umuvu4/2. I don't know why the dataTables folks are binding to both keypress and keyup, but I'm overriding both of them to stay compatible although I think keyup is sufficient.

Hope this helps!

Solution 3 - Jquery

Why not try this extended version of Stony's answer :)

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

This will delay the search until the user has stopped typing.

Hope it helps.

Solution 4 - Jquery

Here is how to handle it with the api change in version 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;
});

Solution 5 - Jquery

To invoke the server call after the user has typed the mininum characters in the search box, you can follow Allan's suggestion:

> customize the fnSetFilteringDelay() plug-in API function to add > an extra condition on the string length before setting the filter, also > considering a blank string input to clear the filter

So for a minimum of 3 characters, just change line #19 in the plug-in to:

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

Solution 6 - Jquery

This works on 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

Solution 7 - Jquery

My version of datatables 1.10.10

I changed a little things and it works now. So, i'm sharing, cause it was difficulty to make it work for version 1.10.10. Thanks to cale_b, Stony and Sam Barnes. Look at the code to see what i did.

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

    });

Solution 8 - Jquery

Here's a plugin-like script that extends 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;
}

usage:

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

Solution 9 - Jquery

for 1.10 version add this code to your javascript in the options. The initComplete overrides the search method and wait to 3 characters are written. Thanks to http://webteamalpha.com/triggering-datatables-to-search-only-on-enter-key-press/ for giving me the light.

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

Solution 10 - Jquery

Use this

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

Solution 11 - Jquery

although it does not answer the original question, i had a complex and slow search on my datatables. the filter event was firing after each keypress, which meant a quite noticeable delay after 10 characters. so by introducing a short delay after a keypress before the filter event was fired, where a subsequent keypress reset the counter and prevented the previous search, i was able to make the search seem much faster. others may find this helpful.

i used the answers from stony and christian noel to make this:

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

Solution 12 - Jquery

You can delay the ajax call to the server by this

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

This code will stop the ajax call if the time between to key press is less then 300 ms, in that way when you write a word, only one ajax call will run and only when you stop typing. You can 'play' with the delay param ( the 300) in order to get more or less delay

Solution 13 - Jquery

You'll probably have to modify the plugin.

And instead of making it X characters, use a delay, so the search starts once they stopped typing for 1 second or so.

So the keydown/keyup binding which is currently triggering the search would be modified with a timer...

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

Solution 14 - Jquery

You can get the length of the data that is being passed in using data.currentTarget.value.length, please see below.

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

and obviously you would want this code to run when removing text so set the value to 0

Solution 15 - Jquery

Fixed version for datatables 1.10.12 using API and correctly unbinding the 'input'. Also added search clear on backspace under the character limit.

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

Solution 16 - Jquery

If you're using the old version, it looks like it. Richard's solution works fine. But when I use it, I just added new events, not deleting. Because when code run, table is not yet created. So I found that there is the fnInitComplete method (fire when table created) and I applied it to Ricard's solution. Here it is

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

Solution 17 - Jquery

You can use this code on Medtronic datatable or other code to search after using 3 character :

        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 for first show.

Solution 18 - Jquery

Can you write your own function to test for the length of the inputed string attached to an onKeyUp event handler and trigger the search function once the min length has been reached?

Something along the lines of:

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

...that is, in a pseudo code kind of way but you get the jist.

Solution 19 - Jquery

You can use the parameter by name minlength in order to restrict the search until 3 characters:

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

Solution 20 - Jquery

This works with DataTables version 1.10.19. It only requires including the js in your website template - useful for a site that has multiple dataTables configured on different pages. Also useful for any slow xhr loading tables, will not allow any new xhr requests until all currently running finish. The search function used is very similar to how the plugin sets up the search function originally.

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

Solution 21 - Jquery

Most of the answers here in some way manipulate the existing DataTable event bindings but personally after spending far too long trying to get this working the best approach I found, in the end, was to just send a dummy value in the search parameter during the ajax call.

// ... denotes expected code for DataTable to function excluded for clarity.
$("#example").dataTable({
  ...
  'ajax': {
    ...
    'data': function (d) {
       d.search.value = d.search.value.length >= 3 ? d.search.value : "##EmptySearch##";
       return JSON.stringify(d);
    }
  }
});

The ##EmptySearch## string simply acts as a value that shouldn't match any returned data (it's entirely personal preference what to use, but it should be a string that is guaranteed to not match any data). Because the bindings have not been manipulated all the usual bells and whistles still work but nothing meaningful is returned until the search is greater than or equal to three characters. Admittedly it isn't ideal, would prefer to not make the server request at all but this is (in my opinion) the simplest approach that doesn't ruin the existing functionality of the DataTable search.

Solution 22 - Jquery

You need to modify the jquery.datatables.js

----- updated ofcourse you can do a check on lenght > 3, but I think you still need a timer. if you have a lot of data, you don't want to keep getting it filtered after every character update.

Within this method:

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

Add a timer to the keyup, like shown in one of the answers.

Then go to this site http://jscompress.com/

And past your modified code and the js wil get minified.

Solution 23 - Jquery

Is there a reason you wouldn't just check length on 'change'?

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlexander FarberView Question on Stackoverflow
Solution 1 - Jqueryrandom_user_nameView Answer on Stackoverflow
Solution 2 - JqueryRichardView Answer on Stackoverflow
Solution 3 - JquerySam BarnesView Answer on Stackoverflow
Solution 4 - JqueryChad KuehnView Answer on Stackoverflow
Solution 5 - JqueryMarius ButucView Answer on Stackoverflow
Solution 6 - JqueryMárcio Souza JúniorView Answer on Stackoverflow
Solution 7 - JqueryZanteView Answer on Stackoverflow
Solution 8 - JqueryChristian NoelView Answer on Stackoverflow
Solution 9 - Jquerymato gallardoView Answer on Stackoverflow
Solution 10 - JqueryNitin BouraiView Answer on Stackoverflow
Solution 11 - Jquerypgee70View Answer on Stackoverflow
Solution 12 - Jqueryzion ben yacovView Answer on Stackoverflow
Solution 13 - JquerysmdragerView Answer on Stackoverflow
Solution 14 - JqueryTom McDonoughView Answer on Stackoverflow
Solution 15 - JqueryTinoView Answer on Stackoverflow
Solution 16 - JquerycihancoskunView Answer on Stackoverflow
Solution 17 - JqueryLPLNView Answer on Stackoverflow
Solution 18 - JqueryChrisView Answer on Stackoverflow
Solution 19 - JqueryLokesh SView Answer on Stackoverflow
Solution 20 - JquerysiteView Answer on Stackoverflow
Solution 21 - Jqueryuser692942View Answer on Stackoverflow
Solution 22 - JqueryTahir MalikView Answer on Stackoverflow
Solution 23 - JqueryjimyshockView Answer on Stackoverflow