FilterTable introduces my "Stuff I Wrote and Never Released Because I Was Too Busy" series—a JavaScript class designed to turn plain HTML tables into interactive tools. I built this to solve a recurring problem: making table data manageable without fuss. This documentation guides you through setup and usage, using a sample table with five columns: id, last name, first name, gender, and age. Each example highlights a core feature, ending with a full-featured setup.
What FilterTable Is
FilterTable enhances any HTML table with a header row. It adds text search, enum filters (dropdowns), range filters (for numbers), sortable columns, and pagination. It analyzes your data to apply these features automatically where they fit. English serves as the default language, but translation remains an option. No fluff—just functionality.
Sample Table
Here is the table we use for examples:
<table id="peopleTable">
<thead>
<tr>
<th>ID</th>
<th>Last Name</th>
<th>First Name</th>
<th>Gender</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr><td>1</td><td>Smith</td><td>John</td><td>Male</td><td>34</td></tr>
<tr><td>2</td><td>Johnson</td><td>Emily</td><td>Female</td><td>28</td></tr>
<tr><td>3</td><td>Lee</td><td>Michael</td><td>Male</td><td>45</td></tr>
<tr><td>4</td><td>Brown</td><td>Sarah</td><td>Female</td><td>31</td></tr>
<tr><td>5</td><td>Davis</td><td>James</td><td>Male</td><td>39</td></tr>
</tbody>
</table>
Getting Started
The script has no dependencies, add a <script> tag to your <head> and it's ready to go. Bootstrap 5 and Font Awesome support are baked in, but not required.
Basic Activation
You could activate FilterTable on your table with no configuration, but it wouldn't do anything. Out of the box, it's not sortable, or filterable. You MUST configure it. Let's start with its namesake function.
Text Filter
const config = {
filterableColumns: [1, 2] // Last Name, First Name
};
const filterTable = new FilterTable('peopleTable', config);
You'll get this result. Type any name, first or last, and the table will render only the matches. Checkboxes indicate which columns are being filtered. Check and uncheck to limit which columns the filter applies to.
ID | Last Name | First Name | Gender | Age |
---|---|---|---|---|
1 | Smith | John | Male | 34 |
2 | Johnson | Emily | Female | 28 |
3 | Lee | Michael | Male | 45 |
4 | Brown | Sarah | Female | 31 |
5 | Davis | James | Male | 39 |
Enum Filter
Generate dropdowns for columns with repeating values, like gender.
const config = {
enumColumns: 3 // Gender, in this case - but you can select multiple columns like [1,2,3]
};
const filterTable = new FilterTable('peopleTable', config);
A dropdown appears above the table for the Gender column, offering "All," "Male," and "Female." Select "Female" to show only Emily Johnson and Sarah Brown. The values are selected from those found in the table column.
ID | Last Name | First Name | Gender | Age |
---|---|---|---|---|
1 | Smith | John | Male | 34 |
2 | Johnson | Emily | Female | 28 |
3 | Lee | Michael | Male | 45 |
4 | Brown | Sarah | Female | 31 |
5 | Davis | James | Male | 39 |
Range Filters
For purely numeric columns, you can set up range filters. As with the enums, the min and max values are selected from the table column itself. Selecting min and max values reduces the table entries to show only those within the range.
const config = {
rangeColumns: {
4: {} // an empty object picks the available range. defaultMin and defaultMax optional
}
};
const filterTable = new FilterTable('peopleTable', config);
Two numeric filters appear, allowing you to filter by min and max values in the Age column.
ID | Last Name | First Name | Gender | Age |
---|---|---|---|---|
1 | Smith | John | Male | 34 |
2 | Johnson | Emily | Female | 28 |
3 | Lee | Michael | Male | 45 |
4 | Brown | Sarah | Female | 31 |
5 | Davis | James | Male | 39 |
Sortable Columns
There's no reason to stop with filters, let's jump into the sort feature. Simple to configure, powerful to behold.
const config = {
sortableColumns: [0,1,2,3,4], // Let's sort by everything
defaultSortColumn: 0, // ID, this setting is optional - defaults to the default table order
defaultSortDirection: 'asc' // asc or desc - optional, defaults to asc
};
const filterTable = new FilterTable('peopleTable', config);
ID | Last Name | First Name | Gender | Age |
---|---|---|---|---|
1 | Smith | John | Male | 34 |
2 | Johnson | Emily | Female | 28 |
3 | Lee | Michael | Male | 45 |
4 | Brown | Sarah | Female | 31 |
5 | Davis | James | Male | 39 |
Pagination
There's nothing worse than a table that never ends, or having to scroll all the way back up from the bottom of a neverending table just to sort!
const config = {
rowsPerPageOptions: [2,4,6], // what pagination options are visible to the user, defaults to [5,10,15]
};
const filterTable = new FilterTable('peopleTable', config);
When there aren't enough rows to paginate - no pagination is displayed.
ID | Last Name | First Name | Gender | Age |
---|---|---|---|---|
1 | Smith | John | Male | 34 |
2 | Johnson | Emily | Female | 28 |
3 | Lee | Michael | Male | 45 |
4 | Brown | Sarah | Female | 31 |
5 | Davis | James | Male | 39 |
Kitchen Sink Example
All features combined, and a much expanded table (50 entries). I even altered a few of the language strings.
const config = {
filterableColumns: [1, 2], // Last Name, First Name for text search
enumColumns: 3, // Gender for dropdown
rangeColumns: {
4: { defaultMin: 30, defaultMax: 40 } // Age for range filter
},
sortableColumns: [0, 1, 2, 3, 4], // All columns sortable
defaultSortColumn: 1, // Start sorted by Last Name
defaultSortDirection: 'asc',
rowsPerPageOptions: [2, 4, 6], // Pagination options
language: {
searchLabel: "Find",
enumAllOption: "Any",
paginationNext: "Forward"
}
};
const filterTable = new FilterTable('peopleTable', config);
ID | Last Name | First Name | Gender | Age |
---|---|---|---|---|
1 | Smith | John | Male | 34 |
2 | Johnson | Emily | Female | 28 |
3 | Lee | Michael | Male | 45 |
4 | Brown | Sarah | Female | 31 |
5 | Davis | James | Male | 39 |
6 | Brown | Sarah | Female | 25 |
7 | Jones | Michael | Male | 40 |
8 | Miller | Jessica | Female | 35 |
9 | Davis | Chris | Male | 18 |
10 | Garcia | Laura | Female | 22 |
11 | Martinez | David | Male | 28 |
12 | Hernandez | Anna | Female | 19 |
13 | Lopez | Daniel | Male | 33 |
14 | Gonzalez | Maria | Female | 27 |
15 | Wilson | Paul | Male | 45 |
16 | Anderson | Linda | Female | 50 |
17 | Thomas | Mark | Male | 60 |
18 | Moore | Patricia | Female | 55 |
19 | Jackson | Steven | Male | 42 |
20 | White | Barbara | Female | 38 |
21 | Harris | Kevin | Male | 29 |
22 | Martin | Lisa | Female | 24 |
23 | Thompson | Brian | Male | 31 |
24 | Garcia | Angela | Female | 26 |
25 | Martinez | Jason | Male | 34 |
26 | Hernandez | Carol | Female | 21 |
27 | Lopez | Scott | Male | 37 |
28 | Gonzalez | Betty | Female | 32 |
29 | Wilson | Frank | Male | 41 |
30 | Anderson | Sharon | Female | 36 |
31 | Thomas | Greg | Male | 48 |
32 | Moore | Deborah | Female | 44 |
33 | Jackson | Ray | Male | 39 |
34 | White | Helen | Female | 43 |
35 | Harris | George | Male | 47 |
36 | Martin | Ruth | Female | 49 |
37 | Thompson | Edward | Male | 52 |
38 | Garcia | Margaret | Female | 53 |
39 | Martinez | Patrick | Male | 54 |
40 | Hernandez | Donna | Female | 56 |
41 | Lopez | Henry | Male | 58 |
42 | Gonzalez | Virginia | Female | 59 |
43 | Wilson | Albert | Male | 61 |
44 | Anderson | Joan | Female | 62 |
45 | Thomas | Arthur | Male | 63 |
46 | Moore | Gloria | Female | 64 |
47 | Jackson | Howard | Male | 65 |
48 | White | Theresa | Female | 66 |
49 | Harris | Louis | Male | 67 |
50 | Martin | Janet | Female | 68 |
Language Replacement
The language object in configuration has options to replace all English strings with the language strings of your choice. This example straight out of Grok, replaces English with Spanish.
language: {
searchLabel: "Buscar", // Replaces "Search"
rangeMinPlaceholder: "Mín ({min})", // Replaces "Min ({min})"
rangeMaxPlaceholder: "Máx ({max})", // Replaces "Max ({max})"
rangeSeparator: "a", // Replaces "to"
enumAllOption: "Todos", // Replaces "All"
rowsPerPageLabel: "Filas por página:",// Replaces "Rows per page:"
paginationPrevious: "Anterior", // Replaces "Previous"
paginationNext: "Siguiente", // Replaces "Next"
paginationAriaLabel: "Paginación de tabla", // Replaces "Table pagination"
sortTitle: "Haga clic para ordenar" // Replaces "Click to sort"
}