PageSourceSearch

https://synergyhub.ai/js/dataTableFilters.js?v=1

js synergyhub.ai collected 2026-10-04 21:51:29 UTC 8,028 bytes, 219 lines download raw bytes

1
2//Data tables default settings
3$.extend( true, $.fn.dataTable.defaults, {
4    processing: true,
5    "language": {
6        "processing": `<div style="padding:30px 50px;background:#F9F9F9EC;border:1px solid #0003;position:absolute;z-index:999;">
7            Processing ...
8        </div>`,
9    }
10} );
11
12// Options pre-processor
13function dt_getOptions(options, dt_serverCall, server, filters) {
14    // Common settings
15    options["orderCellsTop"] = true;
16
17    // Check for server-loading
18    if(server || 'sAjaxSource' in options) {
19        // console.log("DataTable"+(filters?"Filters":"")+": server-side load")
20        options["bProcessing"] = true;
21        options["bServerSide"] = true;
22        options["fnServerData"] = dt_serverCall;
23    }
24    else  {
25        // console.log("DataTable"+(filters?"Filters":"")+": client-side load")
26        options["bProcessing"] = false;
27        options["bServerSide"] = false;
28        options["fnServerData"] = null;
29    } 
30
31    if(options["bProcessing"] && filters) {
32        // add flag for datatablefilters
33        options["sAjaxSource"] += "&dataTableFilters=true";
34    }
35
36    // Return processed options
37    return options;
38}
39/* 
40* Initiates dataTable for Server-Loading
41*/
42$.fn.DataTableServer = function(options = {}) {
43    function dt_serverCall(sSource, aoData, fnCallback) {
44        // console.log("sSource: ", sSource, " aoData: ", aoData)
45        $.ajax({
46            url: sSource,
47            type: 'GET',
48            data: aoData, // Data to send to server
49            dataType: 'json',
50            success: function(response) {
51                // console.log("response: ", response)
52                if(response.success) {
53                    fnCallback(response.success) // Pass the server data back to DataTables
54                } else {
55                    console.error(response)
56                }                    
57            }, 
58            error: function(response) {
59                console.error(response)
60            }
61        });
62    }
63
64    var _this = this,
65        _options = dt_getOptions(options, dt_serverCall, true, false)
66
67    // Create DataTables
68    var _table = new DataTable(_this, _options);
69}
70/* 
71* Creates the DataTable with filters
72*/
73$.fn.DataTableFilters = function(options = {}) {
74    function dt_serverCall(sSource, aoData, fnCallback) {
75        // Add selected filters to ajax
76        var selectedFilters = {};
77        $('.column_filter').each(function( i ) {
78            const columnIdx = $(this).data("column");
79            $(`select[data-column='${columnIdx}'] :selected`).each(function( i ) {
80                const vals = $(this).data("values");
81                if(!selectedFilters[columnIdx]) selectedFilters[columnIdx] = []
82                selectedFilters = {...selectedFilters, [columnIdx]: [...selectedFilters[columnIdx], vals]};
83            })
84        })
85        aoData.push({
86            "name": "selectedFilters", 
87            "value": JSON.stringify(selectedFilters)
88        });
89    
90        $.ajax({
91            url: sSource,
92            type: 'GET',
93            data: aoData, // Data to send to server
94            dataType: 'json',
95            success: function(response) {
96                if(response.success) {
97                    fnCallback(response.success) // Pass the server data back to DataTables
98                    loadColumns(response.success.columns);
99                } else {
100                    console.error(response)
101                }                    
102            }, 
103            error: function(response) {
104                console.error(response)
105            }
106        });
107    }
108
109    // Init
110    var _this = this,
111        _options = dt_getOptions(options, dt_serverCall, null, true),
112        _isServerSideLoad = _options["bServerSide"],
113        _hasInitColumns = false;
114
115    // Create DataTables
116    var _table = new DataTable(_this, _options);
117
118    // Create filter dropdowns
119    function initColumns() {
120        if(!_hasInitColumns) {
121            _hasInitColumns = true;
122
123            // Create filter row
124            var row = `<tr class="dataTable-filterRow">`;
125            $("#" + _this.attr('id') + ' thead tr th').each(function (i) {
126                var thCol = $(this);
127                // append column filter to row
128                row +=
129                    (`<th class="sorting_disabled">` +
130                        (thCol.hasClass("sorting_disabled")
131                            ? ``
132                            : `<select class="column_filter select2" data-column="${i}" multiple>
133                                    <option value="">All</option>
134                                </select>`
135                        ) +
136                    `</th>`);
137            })
138            row += "</tr>";
139            // append row to thead
140            _this.find('thead').append($(row));
141
142            // Initialize Select2 on the filter dropdowns
143            $('.select2').select2({
144                placeholder: "Select values",
145                allowClear: true,
146                width: 'resolve'
147            });
148        }
149    }
150    initColumns();
151
152
153    // Dynamic column loading
154    function loadColumns(serverColumnData = null) {
155        if(!_hasInitColumns) initColumns();
156
157        // If client-side loading
158        if(!_isServerSideLoad) {
159            // Populate the dropdowns dynamically with distinct plain text column values
160            _table.columns().every(function() {
161                var column = this;
162                var columnIndex = column.index();
163
164                var uniqueValues = {}; // Object to track unique values and avoid duplicates
165                
166                // Iterate through each cell and extract the plain text content
167                column.nodes().each(function(node) {
168                    var plainText = $(node).text().trim(); // Extract text without HTML tags
169
170                    // Add to select only if it is not already added
171                    if (plainText && !uniqueValues[plainText]) {
172                        $('select[data-column="' + columnIndex + '"]').append('<option value="' + plainText + '">' + plainText + '</option>');
173                        uniqueValues[plainText] = true; // Mark value as added
174                    }
175                });
176            });
177        }
178        // Else server-loading, if column data is included
179        else if(serverColumnData) {
180            Object.entries(serverColumnData).forEach(([columnIndex, columnData]) => {
181                Object.entries(columnData).forEach(([optionIndex, {result, values}]) => {
182                    $(`select[data-column='${columnIndex}']`).append(
183                        $(`<option></option>`).data("values", values).val(result).html(result)
184                    );
185                })
186            })
187        } 
188    };
189    loadColumns();
190
191
192    // Apply individual column filters using Select2
193    $('.column_filter').on('change', function() {
194        var column_filter = $(this);
195        var columnIndex = column_filter.attr('data-column');
196        var selectedValues = column_filter.val(); // Get selected values
197        
198        // If there are selected values, filter the table
199        if (selectedValues && selectedValues.length > 0) {
200            // escape any special regex characters
201            selectedValues = selectedValues.map(val => val.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')) 
202
203            /// create regex for literal search terms
204            var regexLiteral = '(((?<!.)(' + selectedValues.join(')(?!.))|((?<!.)(') + ')(?!.)))';
205            // create regex for search term wrapped in html tags
206            var regexHTML = '((' + selectedValues.join(')|(') + ')(\s)*[^\w]+)';
207            // create final regex
208            var searchRegex = regexLiteral + "|" + regexHTML;
209
210            // search and re-draw
211            _table
212                .column(columnIndex)
213                .search(searchRegex, true, false)
214                .draw();
215        } else {
216            _table.column(columnIndex).search('').draw(); // Clear the filter if nothing is selected
217        }
218    });
219};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.