dokuwiki-datatables/script.js

199 lines
7.6 KiB
JavaScript

/* global JSINFO */
/**
* DokuWiki DataTables Plugins
*
* Home http://dokuwiki.org/template:bootstrap3
* Author Giuseppe Di Terlizzi <giuseppe.diterlizzi@gmail.com>
* 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('<thead>');
$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('<tr class="dt-column-filters"></tr>');
// Add filter for each column
table.columns().every(function(index) {
const column = this;
const $th = jQuery('<th></th>');
// Create container for input and select
const $filterContainer = jQuery('<div class="dt-filter-container"></div>');
// Create search input for filtering dropdown options
const $searchInput = jQuery('<input type="text" class="dt-filter-search" placeholder="Suchen..." />');
// Create select dropdown
const $select = jQuery('<select class="dt-filter-select"><option value="">Alle anzeigen</option></select>');
// 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('<div>').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('<option value="' + jQuery('<div>').text(value).html() + '">' + value + '</option>');
});
// 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('<tfoot></tfoot>');
$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);
});
}
});