/* global JSINFO */ /** * DokuWiki DataTables Plugins * * Home http://dokuwiki.org/template:bootstrap3 * Author Giuseppe Di Terlizzi * License GPL 2 (http://www.gnu.org/licenses/gpl.html) * Copyright (C) 2015-2020, Giuseppe Di Terlizzi */ jQuery(document).ready(function () { const WRAP_TABLES_SELECTOR = '.page div.dt-wrapper table'; const ALL_TABLES_SELECTOR = '.page table thead'; /** * Initialize DataTables on the given table * * @param {jQuery} $target_table * @param {object} dt_config DataTable configuration */ function init_datatables($target_table, dt_config) { console.debug(dt_config); // adjust header rows if requested let headerRows = dt_config.headerRows; if (headerRows) { const $tbody = jQuery('tbody', $target_table); // if table heade ismissing, create it let $thead = jQuery('thead', $target_table); if ($thead.length === 0) { $thead = jQuery(''); $target_table.prepend($thead); } // move the first rows from tbody to thead headerRows -= $thead.children().length; while (headerRows > 0) { headerRows--; $thead.append($tbody.children().first()); } } // initialize, unless there are colspans or rowspans if ( jQuery('thead > tr', $target_table).length && !jQuery('tbody', $target_table).find('[rowspan], [colspan]').length ) { $target_table.attr('width', '100%'); const table = $target_table.DataTable(dt_config); // Add column filters if enabled if (JSINFO.plugin.datatables.enableColumnFilters) { addColumnFilters(table, $target_table); } } } /** * Add column filters to DataTable * * @param {DataTable} table DataTable instance * @param {jQuery} $target_table Table jQuery object */ function addColumnFilters(table, $target_table) { const position = JSINFO.plugin.datatables.columnFiltersPosition || 'header'; const $thead = $target_table.find('thead'); // Create filter row const $filterRow = jQuery(''); // Add filter for each column table.columns().every(function(index) { const column = this; const $th = jQuery(''); // Create container for input and select const $filterContainer = jQuery('
'); // Create search input for filtering dropdown options const $searchInput = jQuery(''); // Create select dropdown const $select = jQuery(''); // Get unique values from column const uniqueValues = []; const uniqueTexts = new Set(); column.data().each(function(d) { if (d) { // Extract text content if it contains HTML const text = jQuery('
').html(d).text().trim(); if (text && !uniqueTexts.has(text)) { uniqueTexts.add(text); uniqueValues.push(text); } } }); // Sort unique values uniqueValues.sort(); // Populate select with unique values uniqueValues.forEach(function(value) { $select.append(''); }); // Filter dropdown options AND table based on search input $searchInput.on('keyup', function() { const searchTerm = jQuery(this).val(); // Filter dropdown options const searchTermLower = searchTerm.toLowerCase(); $select.find('option').each(function() { const optionText = jQuery(this).text().toLowerCase(); if (optionText.indexOf(searchTermLower) > -1 || jQuery(this).val() === '') { jQuery(this).show(); } else { jQuery(this).hide(); } }); // Filter table column if (searchTerm) { const escapedVal = searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); column.search(escapedVal, true, false).draw(); } else { column.search('').draw(); } // Reset dropdown selection when typing $select.val(''); }); // Filter table when dropdown changes $select.on('change', function() { const val = jQuery(this).val(); if (val) { // Escape special regex characters and search for exact match const escapedVal = val.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // Search using regex that matches the text anywhere in the cell column.search(escapedVal, true, false).draw(); } else { // Clear search column.search('').draw(); } }); // Add elements to container $filterContainer.append($searchInput); $filterContainer.append($select); $th.append($filterContainer); $filterRow.append($th); }); // Add filter row to table if (position === 'header') { $thead.append($filterRow); } else { // Create tfoot if it doesn't exist let $tfoot = $target_table.find('tfoot'); if ($tfoot.length === 0) { $tfoot = jQuery(''); $target_table.append($tfoot); } $tfoot.append($filterRow); } } // MAIN // check if plugin is configured if (!('plugin' in JSINFO) || !('datatables' in JSINFO.plugin)) return; // initialize on all tables, unless they have our wrapper (using default config) if (JSINFO.plugin.datatables.enableForAllTables) { jQuery(ALL_TABLES_SELECTOR).each(function () { const $target_table = jQuery(this).parent(); if (!$target_table.parents('.dt-wrapper').length) { init_datatables($target_table, JSINFO.plugin.datatables.config); } }); } // initialize on all tables with our wrapper (using default config + wrapper config) const $wrap_tables = jQuery(WRAP_TABLES_SELECTOR); if ($wrap_tables.length) { $wrap_tables.each(function () { const $target_table = jQuery(this); const wrap_config = jQuery(this).parents('.dt-wrapper').data(); const dt_config = jQuery.extend(JSINFO.plugin.datatables.config, wrap_config); init_datatables($target_table, dt_config); }); } });