Skip to content

Commit 5b5b558

Browse files
committed
add a multisearch/filter with example. fixes #399
1 parent 5b78753 commit 5b5b558

File tree

13 files changed

+1422
-17
lines changed

13 files changed

+1422
-17
lines changed

docs/demos/30-custom-search-method/index.html

Lines changed: 1137 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import {DataTable} from "../dist/module.js"
2+
const datatable = new DataTable("#demo-table", {
3+
perPageSelect: [5, 10, 15, ["All", -1]],
4+
columns: [
5+
{
6+
select: 1,
7+
sortable: false,
8+
searchMethod: (terms, cell, row, _column, source) => {
9+
let found
10+
if (source === "class-filter") {
11+
found = terms.find(
12+
// For each of the terms, check if at least one of the class tags in the cell exactly matches the term
13+
term => cell.data.find(span => span.attributes?.class === `class ${term}`)
14+
)
15+
} else {
16+
// This is normal search. We just check if one of the terms is part of the text of the cell
17+
found = terms.find(
18+
term => cell.text.toLowerCase().includes(term.toLowerCase().trim())
19+
)
20+
}
21+
if (found) return true
22+
return false
23+
}
24+
},
25+
{
26+
select: 4,
27+
searchMethod: (terms, cell, row, _column, source) => {
28+
if (source === "completion-filter") {
29+
const cellPercentage = parseInt(cell.data, 10)
30+
const minPercentage = parseInt(terms[0], 10)
31+
if (cellPercentage >= minPercentage) return true
32+
return false
33+
}
34+
// This is normal search. We just check if one of the terms is part of the text of the cell
35+
const found = terms.find(
36+
term => cell.data.includes(term.toLowerCase().trim())
37+
)
38+
39+
if (found) return true
40+
return false
41+
}
42+
}
43+
]
44+
})
45+
46+
47+
// Multi-select dropdown
48+
let isDropdownOpen = false
49+
50+
const toggleDropdown = () => {
51+
const checkboxes = document.getElementById("checkboxes")
52+
if (isDropdownOpen) {
53+
checkboxes.style.display = "none"
54+
isDropdownOpen = false
55+
} else {
56+
checkboxes.style.display = "block"
57+
isDropdownOpen = true
58+
}
59+
}
60+
61+
document.querySelector(".select-box").addEventListener("click", toggleDropdown)
62+
// Close the dropdown if the user clicks outside of it
63+
window.onclick = function(event) {
64+
if (!event.target.matches(".select-box") && !event.target.matches(".over-select") && !event.target.closest("#checkboxes")) {
65+
const checkboxes = document.getElementById("checkboxes")
66+
checkboxes.style.display = "none"
67+
isDropdownOpen = false
68+
}
69+
if (event.target.closest("#checkboxes label")) {
70+
// Change in checked classes, restart search
71+
// Get all checked checkboxes
72+
const checked = Array.from(document.querySelectorAll("#checkboxes input:checked")).map(checkbox => checkbox.value)
73+
if (!checked.length) {
74+
// Don't allow deselecting the last checkbox.
75+
event.target.closest("#checkboxes label").querySelector("input").checked = true
76+
return
77+
}
78+
datatable.multiSearch([
79+
{terms: checked,
80+
columns: [1]}
81+
], "class-filter")
82+
}
83+
84+
}
85+
86+
const updateSliderValue = value => {
87+
document.getElementById("slider-value").innerHTML = `${value}%`
88+
datatable.multiSearch([
89+
{terms: [value],
90+
columns: [4]}
91+
], "completion-filter")
92+
}
93+
94+
document.querySelector("#percentage-slider").addEventListener("input", function() {
95+
updateSliderValue(this.value)
96+
})
97+
98+
99+
window.dt = datatable
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
span.class {
2+
display: inline-block;
3+
padding: 5px 10px;
4+
margin: 3px;
5+
border-radius: 12px;
6+
font-size: 14px;
7+
font-weight: 500;
8+
color: white;
9+
}
10+
11+
/* Pastel colors for different subjects */
12+
.math {
13+
background-color: #a3d8f4; /* pastel blue */
14+
color: #1d4e89;
15+
}
16+
17+
.history {
18+
background-color: #f9c6c9; /* pastel pink */
19+
color: #87373f;
20+
}
21+
22+
.english {
23+
background-color: #c6e1bc; /* pastel green */
24+
color: #2b5d2e;
25+
}
26+
27+
.physics {
28+
background-color: #f6d8ac; /* pastel yellow */
29+
color: #8a5e11;
30+
}
31+
32+
.chemistry {
33+
background-color: #f3bbd3; /* pastel magenta */
34+
color: #73234a;
35+
}
36+
37+
.biology {
38+
background-color: #b7e0e5; /* pastel teal */
39+
color: #1b5b5e;
40+
}
41+
42+
.french {
43+
background-color: #ecd9f2; /* pastel purple */
44+
color: #562e6d;
45+
}
46+
47+
.german {
48+
background-color: #f2d3a1; /* pastel orange */
49+
color: #9b6c22;
50+
}
51+
52+
/* Style for the dropdown and the checkboxes */
53+
.multiselect {
54+
position: relative;
55+
width: 200px;
56+
}
57+
58+
.select-box {
59+
position: relative;
60+
display: block;
61+
border: 1px solid #aaa;
62+
padding: 8px;
63+
background-color: #fff;
64+
cursor: pointer;
65+
}
66+
67+
.select-box select {
68+
width: 100%;
69+
border: none;
70+
outline: none;
71+
background: none;
72+
font-size: 16px;
73+
}
74+
75+
.over-select {
76+
position: absolute;
77+
left: 0;
78+
right: 0;
79+
top: 0;
80+
bottom: 0;
81+
cursor: pointer;
82+
}
83+
84+
.checkboxes {
85+
display: none;
86+
border: 1px solid #aaa;
87+
padding: 10px;
88+
background-color: #f9f9f9;
89+
position: absolute;
90+
z-index: 1;
91+
width: 100%;
92+
}
93+
94+
.checkboxes label {
95+
display: block;
96+
margin-bottom: 5px;
97+
cursor: pointer;
98+
}
99+
100+
.checkboxes input[type="checkbox"] {
101+
margin-right: 10px;
102+
}
103+
104+
/* Additional styling */
105+
.select-box:hover {
106+
background-color: #e9e9e9;
107+
}

docs/demos/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ <h2>Demos</h2>
4646
<a href="27-load-json/">Load JSON</a>
4747
<a href="28-sort-order-attribute/">Sort order attribute</a>
4848
<a href="29-responsive-layout/">Responsive layout</a>
49+
<a href="30-custom-search-method/">Custom search method</a>
4950
</nav>
5051
</body>
5152
</html>

docs/documentation/Options.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ let dataTable = new DataTable(myTable, options);
4848
* [searchable](searchable)
4949
* [sensitivity](columns#sensitivity)
5050
* [searchQuerySeparator](searchQuerySeparator)
51+
* [searchMethod](searchMethod)
5152
### Sorting
5253
* [sortable](sortable)
5354
* [locale](columns#locale)

docs/documentation/columns.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,21 @@ When set to `false` the column(s) cannot be searched.
5151

5252
Default: `""`. Influences searching in that cell content will be split with this value by default when searching for content. Specifying `searchItemSeparator` as part of the table's configuration will define a default for all search boxes.
5353

54+
#### `searchMethod`
55+
56+
A custom search method to be used for the column(s). The function should take 5 arguments:
57+
`terms` (an array of strings representing the search terms),
58+
`cell` (the cell that is to be checked for the search terms),
59+
`row` (the data row that the cell is part of),
60+
`column` (the id of the column of the cell),
61+
`source` (a unique string given to a particular search interface so that multiple search itnerfaces can be used simultaneously).
62+
63+
It should return `true` if the search string is found in the data, `false` otherwise.
64+
65+
The default is that it simply checks for the presence of a particular search term in the cell content.
66+
67+
Defining a `searchMethod` as part of the table's configuration will define a default for all columns.
68+
5469
#### `select`
5570

5671
An integer or array of integers representing the column(s) to be manipulated.
@@ -100,7 +115,7 @@ You can either return a string representing the cells content, you can modify th
100115
=>
101116
render: function(value, td, rowIndex, cellIndex) {
102117

103-
}
118+
}
104119

105120
```
106121

docs/documentation/multiSearch().md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Filter the table based on multiple queries.
77
```javascript
88
/**
99
* @param { { terms: String[], columns=: Number[] }[] } queries Queries including search term and columns (optional)
10+
* @param {str} source Source of the search. (optional, used to invalidate search rows later on)
1011
* @return {void}
1112
*/
1213
datatable.multiSearch(queries);

docs/documentation/search().md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Filter the table based on a single query.
88
/**
99
* @param {str} term Search term
1010
* @param {int[]} columns Columns to be searched (optional)
11+
* @param {str} source Source of the search. (optional, used to invalidate search rows later on)
1112
* @return {void}
1213
*/
1314
datatable.search(term, columns);

docs/documentation/searchMethod.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
### `searchMethod`
2+
#### Type: `function`
3+
#### Default: `undefined`
4+
5+
A custom search method to be used for the column(s). The function should take 5 arguments:
6+
`terms` (an array of strings representing the search terms),
7+
`cell` (the cell that is to be checked for the search terms),
8+
`row` (the data row that the cell is part of),
9+
`column` (the id of the column of the cell),
10+
`source` (a unique string given to a particular search interface so that multiple search itnerfaces can be used simultaneously).
11+
12+
It should return `true` if the search string is found in the data, `false` otherwise.
13+
14+
The default is that it simply checks for the presence of a particular search term in the cell content.
15+
16+
A `searchMethod` can also be defined for individual columns. If a `searchMethod` is defined for a column, it will override the
17+
default `searchMethod` defined for the table.

src/column_settings.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ export const readColumnSettings = (columnOptions = [], defaultType, defaultForma
7979
}
8080
}
8181

82+
if (data.searchMethod) {
83+
column.searchMethod = data.searchMethod
84+
}
85+
8286
if (data.hidden) {
8387
column.hidden = true
8488
}

0 commit comments

Comments
 (0)