@@ -8,6 +8,12 @@ new BadgerAccordion(".js-badger-accordion", {
8
8
openHeadersOnLoad : [ 0 ]
9
9
} ) ;
10
10
11
+ function removeAllChildNodes ( parent ) {
12
+ while ( parent . firstChild ) {
13
+ parent . removeChild ( parent . firstChild ) ;
14
+ }
15
+ }
16
+
11
17
document . addEventListener ( "DOMContentLoaded" , function ( ) {
12
18
// Basic attempt to obfuscate emails
13
19
Array . from ( document . querySelectorAll ( "[data-mail]" ) ) . map ( function ( el ) {
@@ -18,6 +24,91 @@ document.addEventListener("DOMContentLoaded", function() {
18
24
} , { once : true } ) ;
19
25
} ) ;
20
26
27
+ // Make tables filterable
28
+ Array . from ( document . querySelectorAll ( "[data-sort-filter]" ) ) . map ( function ( el ) {
29
+ const widget = {
30
+ options : { } ,
31
+ filters : { }
32
+ } ;
33
+
34
+ // Checks if row matches against filter
35
+ function isFilterMatch ( row ) {
36
+ for ( let index in widget . filters ) {
37
+ const filter = widget . filters [ index ] . toLowerCase ( ) ;
38
+ const rowValue = row . columns [ index ] . toLowerCase ( ) ;
39
+ if ( rowValue . indexOf ( filter ) === - 1 ) {
40
+ return false ;
41
+ }
42
+ }
43
+ return true ;
44
+ }
45
+
46
+ // Create datalist that input can use for suggetions
47
+ function setupDatalist ( el , label , idx ) {
48
+ widget . options [ idx ] = document . createElement ( 'datalist' ) ;
49
+ widget . options [ idx ] . setAttribute ( 'id' , 'opts_for_' + label ) ;
50
+ widget . options [ idx ] . _options = [ ]
51
+ el . appendChild ( widget . options [ idx ] ) ;
52
+ }
53
+
54
+ // Add input for filtering
55
+ function addInput ( el , label , idx ) {
56
+ const input = document . createElement ( 'input' ) ;
57
+ input . addEventListener ( "change" , function ( e ) {
58
+ widget . filters [ idx ] = e . target . value ;
59
+ removeAllChildNodes ( tbody ) ;
60
+ rows . filter ( isFilterMatch ) . map ( r => {
61
+ tbody . appendChild ( r . el )
62
+ } ) ;
63
+ } ) ;
64
+ input . setAttribute ( 'style' , 'width:100%;display:block' )
65
+ input . setAttribute ( 'type' , 'text' ) ;
66
+ input . setAttribute ( 'name' , 'filter_' + label ) ;
67
+ input . setAttribute ( 'list' , 'opts_for_' + label ) ;
68
+ el . appendChild ( input ) ;
69
+ }
70
+ const tbody = el . querySelector ( 'tbody' ) ;
71
+ const headings = Array . from ( el . querySelectorAll ( 'thead th' ) ) . map ( ( el , idx ) => {
72
+ const isSuggested = el . getAttribute ( "data-suggest" ) !== null ;
73
+ const label = el . innerText . toLowerCase ( ) ;
74
+ el . appendChild ( document . createElement ( 'br' ) ) ;
75
+ addInput ( el , label , idx ) ;
76
+
77
+ if ( isSuggested ) {
78
+ setupDatalist ( el , label , idx ) ;
79
+ }
80
+ return { idx, isSuggested, label} ;
81
+ } ) ;
82
+
83
+ const rows = Array . from ( el . querySelectorAll ( 'tbody tr' ) ) . map ( tr => {
84
+ const columns = Array . from ( tr . querySelectorAll ( 'td' ) ) . map ( ( c , idx ) => {
85
+ // For columns that match the index of the `data-suggest` headers
86
+ // ... add the text value to options
87
+ if ( widget . options [ idx ] ) {
88
+ widget . options [ idx ] . _options . push ( c . innerText )
89
+ }
90
+ return c . innerText ;
91
+ } ) ;
92
+ return {
93
+ el : tr , // Needed for writing to dom
94
+ columns, // Needed for filtered
95
+ } ;
96
+ } ) ;
97
+
98
+ // Go through options elements and populate lists with column aggregates
99
+ // gathered in previous loop
100
+ Object . entries ( widget . options ) . map ( pair => {
101
+ const [ idx , el ] = pair ;
102
+ const opts = [ ...new Set ( el . _options ) ] ;
103
+ opts . sort ( ( a , b ) => a . length - b . length ) ;
104
+ opts . map ( o => {
105
+ const ol = document . createElement ( 'option' ) ;
106
+ ol . innerText = o ;
107
+ return ol ;
108
+ } ) . map ( ol => el . appendChild ( ol ) ) ;
109
+ } ) ;
110
+ } ) ;
111
+
21
112
function clearFilter ( menu ) {
22
113
menu . classList . remove ( "is-filtering" ) ;
23
114
Array . from ( menu . getElementsByTagName ( 'li' ) ) . map ( function ( el ) {
0 commit comments