Quantcast
Viewing all articles
Browse latest Browse all 82150

DataTables individual column filtering

I am using the code from the individual column filtering and I came across what I think could be a bug in the code. I have multiple tables in my site on different pages. Each table has its own settings therefor I need to utilize this filtering multiple times. I found that when doing this if you give your footer a class name and each tables footer has the same class name then datatables crashes.

I have pulled the common code out into a single file:

 
(function($) {
	/*
	 * Function: fnGetColumnData
	 * Purpose:  Return an array of table values from a particular column.
	 * Returns:  array string: 1d data array 
	 * Inputs:   object:oSettings - dataTable settings object. This is always the last argument past to the function
	 *           int:iColumn - the id of the column to extract the data from
	 *           bool:bUnique - optional - if set to false duplicated values are not filtered out
	 *           bool:bFiltered - optional - if set to false all the table data is used (not only the filtered)
	 *           bool:bIgnoreEmpty - optional - if set to false empty values are not filtered from the result array
	 * Author:   Benedikt Forchhammer <b.forchhammer /AT\ mind2.de>
	 */

	  $.fn.dataTableExt.oApi.fnGetColumnData = function ( oSettings, iColumn, bUnique, bFiltered, bIgnoreEmpty ) {
	    // check that we have a column id
	    if ( typeof iColumn == "undefined" ) return new Array();
	     
	    // by default we only want unique data
	    if ( typeof bUnique == "undefined" ) bUnique = true;
	     
	    // by default we do want to only look at filtered data
	    if ( typeof bFiltered == "undefined" ) bFiltered = true;
	     
	    // by default we do not wany to include empty values
	    if ( typeof bIgnoreEmpty == "undefined" ) bIgnoreEmpty = true;
	     
	    // list of rows which we're going to loop through
	    var aiRows;
	     
	    // use only filtered rows
	    if (bFiltered == true){
	      aiRows = oSettings.aiDisplay;
	    } else {
	      // use all rows
	      aiRows = oSettings.aiDisplayMaster; // all row numbers
	    }
	 
	    // set up data array    
	    var asResultData = new Array();
	    var sortType = false;
	    for (var i=0,c=aiRows.length; i<c; i++) {
	        iRow = aiRows[i];
	        var aData = this.fnGetData(iRow);
	        var sValue = aData[iColumn];

	        // sets sortType
	        sortType = isNumber(sValue);
	        // ignore empty values?
	        if (bIgnoreEmpty == true && sValue.length == 0){
	          continue;
	        } else if(bUnique == true && jQuery.inArray(sValue, asResultData) > -1){
	          // ignore unique values?
	          continue;
	        } else {
	                  // else push the value onto the result data array
	          asResultData.push(sValue);
	        }
	    }
	        if(sortType){
	          return asResultData.sort(numOrdA);
	        }else{
	          return asResultData.sort(alph);
	        }
}})(jQuery);

function fnCreateSelect( aData )
{
    var r='<select><option value=""></option>', i, iLen=aData.length;
    for ( i=0 ; i<iLen ; i++ )
    {
        r += '<option value="'+aData[i]+'">'+aData[i]+'</option>';
    }
    return r+'</select>';
}

function isNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

function alph(a, b){
  if(a>b) return 1;
  if(a==b) return 0;
  if(a<b) return -1;
}

function numOrdA(a, b){
  return a-b;
 }

Then the code specialized for each table is in its own separate file. The first file is:

$(document).ready(function() {
	/* Initialise the DataTable */;
      var oTable = $('#users_table').dataTable({
        "bJQueryUI": true,
        "sPaginationType": "full_numbers",
        "iDisplayLength": 25,
        "bAutoWidth": true,
        "oLanguage": {"sSearch": "Search:"},
        "aaSorting": [[3,'desc'],[0,'asc']]
      });

 
    /* Add a select menu for each TH element in the table footer */
    $("tfoot th.makeSelect").each( function(i) {
        this.innerHTML = fnCreateSelect( oTable.fnGetColumnData(i) );
        $('select', this).change( function () {
            oTable.fnFilter( $(this).val(), i );
        } );
    } );
} );

And the second file is this:

$(document).ready(function() {
	/* Initialise the DataTable */;
      var oTable = $('#boards_table').dataTable({
        "bJQueryUI": true,
        "sPaginationType": "full_numbers",
        "iDisplayLength": 25,
        "bAutoWidth": true,
        "oLanguage": {"sSearch": "Search:"},
        "aaSorting": [[3,'desc'],[0,'asc']]
      });

 
    /* Add a select menu for each TH element in the table footer */
    $("tfoot th.makeSelect").each( function(i) {
        this.innerHTML = fnCreateSelect( oTable.fnGetColumnData(i) );
        $('select', this).change( function () {
            oTable.fnFilter( $(this).val(), i );
        } );
    } );
} );

As you see I have $("tfoot th.makeSelect") in both files. Having it the same class name causes datatables to crash. If a user assigns class names to table footers the only way this can work is if each table has a different class name. To be specific the error I was getting is "uncaught typeerror: cannot read property 'aiDisplay' of null". As a side note I get the same error even if I keep the code in a single file.

Viewing all articles
Browse latest Browse all 82150

Trending Articles