Stacking checkbox filters
Stacking checkbox filters
Hi! I'm trying to create a filter a table by using checkboxes, which are extracted from a specific column in the table. It outputs those values in checkboxes, which it filters the table on. So I wrote a function for that:
[code]
var initMerkCheckboxes = function () {
var $rows = oTable.fnGetNodes();
var values = {};
var colnums = [1]; // which column to get the values from
for (var col = 0, n = colnums.length; col < n; col++) {
var colnum = colnums[col];
if (typeof values[colnum] === "undefined") values[colnum] = {};
// Create Unique List of Values
$('td:nth-child(' + colnum + ')', $rows).each(function () {
values[colnum][$(this).text()] = 1;
});
}
var labels = []; // label array for checkboxes
$.each(values[colnum], function (key, count) {
var $checkbox = $('', {
'class': 'filter-column filter-column-' + colnum,
'type': 'checkbox',
'value': key // key is the value of each individual checkbox
});
var $label = $('', { // add label
'class': 'filter-container'
}).append($checkbox).append(' ' + key);
$checkbox.on('click', function () { // if the checkbox is clicked, redraw the table
oTable.fnDraw();
}).data('colnum', colnum);
labels.push($label.get(0));
});
var $sorted_containers = $(labels).sort(function (a, b) {
return $(a).text().toLowerCase() > $(b).text().toLowerCase();
});
$('#checkboxes').prepend($sorted_containers);
$sorted_containers.wrapAll($('', {
'class': 'checkbox-group checkbox-group-column-' + colnum
}));
};
[/code]
This function works. It outputs this:
[code]
Company A
[code]
var initMerkCheckboxes = function () {
var $rows = oTable.fnGetNodes();
var values = {};
var colnums = [1]; // which column to get the values from
for (var col = 0, n = colnums.length; col < n; col++) {
var colnum = colnums[col];
if (typeof values[colnum] === "undefined") values[colnum] = {};
// Create Unique List of Values
$('td:nth-child(' + colnum + ')', $rows).each(function () {
values[colnum][$(this).text()] = 1;
});
}
var labels = []; // label array for checkboxes
$.each(values[colnum], function (key, count) {
var $checkbox = $('', {
'class': 'filter-column filter-column-' + colnum,
'type': 'checkbox',
'value': key // key is the value of each individual checkbox
});
var $label = $('', { // add label
'class': 'filter-container'
}).append($checkbox).append(' ' + key);
$checkbox.on('click', function () { // if the checkbox is clicked, redraw the table
oTable.fnDraw();
}).data('colnum', colnum);
labels.push($label.get(0));
});
var $sorted_containers = $(labels).sort(function (a, b) {
return $(a).text().toLowerCase() > $(b).text().toLowerCase();
});
$('#checkboxes').prepend($sorted_containers);
$sorted_containers.wrapAll($('', {
'class': 'checkbox-group checkbox-group-column-' + colnum
}));
};
[/code]
This function works. It outputs this:
[code]
Company A
This discussion has been closed.
Replies
[code]
[ ] Company A
[ ] Company B
[X] Company C
[ ] Company D
[ ] Option X
[X] Option Y
[ ] Option Z
Returns:
Options Companies
-------------------
Option Y Company C
Unfiltered table:
Options Companies
-------------------
Option X Company A
Option Z Company B
Option Y Company C
Option Z Company D
Option X Company D
Option Z Company A
Option Y Company D
Option Z Company B
[/code]
The head of my HTML table has 2 rows. The top row has the "filters" class. I put a dropdown element in each of the columns that I want to contain a filter. Each select only contains one option, the * option, which the user selects if they do not want to filter on a particular column value. The other options are created dynamically, ie. see below...
[code]
*
*
*
*
*
*
*
File Type Id
File Name
File Type
Size
Year
Month
Day
Hour
Minute
Second
Uri
[/code]
Before I initialize the datatable, I call this function:
[code]
initializeFiltering($this, settings);
[/code]
After I initialize the datatable, I call this function:
[code]
initializeFilters($this, settings);
[/code]
These functions look like this:
[code]
var initializeFiltering = function ($this, settings) {
$.fn.dataTableExt.afnFiltering = [];
settings.filters = [];
var filter = function (oSettings, aData, iDataIndex, index) {
if (settings.$dataTable == undefined ||
oSettings.nTable != settings.$dataTable[0] ||
settings.filters[index].value == undefined) {
return true;
}
switch (settings.filters[index].value) {
case "*":
return true;
default:
return oSettings.aoData[iDataIndex]._aData[index] == settings.filters[index].value;
}
return true;
};
settings.$table.find("tr.filters").find("th").each(function (index, ui) {
var filterFunction = function (oSettings, aData, iDataIndex) {
for (var i = 0; i < $.fn.dataTableExt.afnFiltering.length; i++) {
if (arguments.callee == $.fn.dataTableExt.afnFiltering[i]) {
return filter(oSettings, aData, iDataIndex, i);
}
}
};
settings.filters.push({ "filterFunction": filterFunction });
$.fn.dataTableExt.afnFiltering.push(filterFunction);
});
};
var initializeFilters = function ($this, settings) {
var onFilterChange = function ($this, settings, ui, index) {
settings.filters[index].value = $(ui).find("option:selected").val();
settings.$dataTable.fnDraw();
$.layout.callbacks.resizePaneDataTables(settings.$dataTable, settings.$tableContainer);
};
var oSettings = settings.$dataTable.fnSettings();
var data = settings.$dataTable.fnGetData();
for (var i = 0; i < oSettings.aoHeader[0].length; i++) {
if ($(oSettings.aoHeader[0][i].cell).children().length == 1) {
settings.filters[i].$filter = $($(oSettings.aoHeader[0][i].cell).children().first());
/* Create and append the options to the select element. */
var values = [];
$.each(data, function (index, obj) {
if ($.inArray(obj[i], values) == -1) {
values.push(obj[i]);
settings.filters[i].$filter.append("" + obj[i] + "");
}
});
/* Sort options by text */
var selectedValue = settings.filters[i].$filter.val();
settings.filters[i].$filter.html($("option", settings.filters[i].$filter).sort(function (a, b) {
return a.text == b.text ? 0 : a.text < b.text ? -1 : 1
}));
settings.filters[i].$filter.val(selectedValue);
/* Add a change handler to the select element that redraws (refilters) and resizes the datatable. */
settings.filters[i].$filter.change({ column: i }, function (event) {
onFilterChange($this, settings, this, event.data.column);
});
/* Set the selected option. */
if (settings.filters[i].value != undefined) {
settings.filters[i].$filter.find("option[value='" + settings.filters[i].value + "']").attr("selected", "selected");
onFilterChange($this, settings, settings.filters[i].$filter[0], i);
}
}
}
};
[/code]
The end effect is that select elements appear in each of the columns that I put them in. Each contains a list of options that are created from values that appear in my table. When the user selects an option other than *, the datatable is filtered. The user can select any number of available filters. The filtering is achieved in an AND fashion, ie. all selected filters apply.