/** * Initialize table selection functionality - GLOBAL REUSABLE VERSION * @param {Object} config - Configuration object * @param {string} config.tableName - jQuery selector for the table (e.g., '#myTable') * @param {Object} config.dataTable - DataTable instance * @param {Object} config.selectedItemsMap - Object to store selected items * @param {string} config.idKey - Property name to use as unique identifier * @param {string} config.idKey2 - Property name to use as secondary identifier * @param {Function} config.updateCountCallback - Callback function to update count display * @param {string} [config.checkboxClass='.selected-Item-checkbox'] - CSS class for item checkboxes * @param {string} [config.selectAllClass='.select-all-checkbox'] - CSS class for select all checkbox * @param {string} [config.selectedRowClass='selected-row'] - CSS class for selected rows */ var selectedProductsMap = {}; function initializeTableSelection(config) { const { tableName, dataTable, selectedItemsMap, idKey, idKey2, updateCountCallback, checkboxClass = '.selected-Item-checkbox', selectAllClass = '.select-all-checkbox', selectedRowClass = 'selected-row' } = config; if (!tableName || !dataTable || !selectedItemsMap || !idKey || !updateCountCallback) { console.error('initializeTableSelection: Missing required configuration parameters'); return; } // Remove any existing event handlers to prevent duplicates $(tableName).off('change', checkboxClass); $(tableName).off('change', selectAllClass); dataTable.off('draw.tableSelection'); // Function to update select all checkbox state based on current page function updateSelectAllCheckboxState() { const $selectAllCheckbox = $(tableName + ' ' + selectAllClass); const $visibleCheckboxes = $(tableName + ' tbody ' + checkboxClass + ':visible'); const checkedCount = $visibleCheckboxes.filter(':checked').length; const totalVisible = $visibleCheckboxes.length; if (totalVisible === 0) { $selectAllCheckbox.prop('indeterminate', false).prop('checked', false); } else if (checkedCount === totalVisible) { $selectAllCheckbox.prop('indeterminate', false).prop('checked', true); } else if (checkedCount > 0) { $selectAllCheckbox.prop('indeterminate', true).prop('checked', false); } else { $selectAllCheckbox.prop('indeterminate', false).prop('checked', false); } } // Function to restore checkbox states when page changes function updateRowStates() { $(tableName + ' tbody tr').each(function () { const $row = $(this); const rowData = dataTable.row($row).data(); if (rowData) { const itemId = idKey2 ? `${rowData[idKey]}|${rowData[idKey2] || ''}` : rowData[idKey]; const $checkbox = $row.find(checkboxClass); if (selectedItemsMap[itemId]) { $checkbox.prop('checked', true); $row.addClass(selectedRowClass); } else { $checkbox.prop('checked', false); $row.removeClass(selectedRowClass); } } }); } // Individual checkbox change handler $(tableName).on('change', checkboxClass, function () { const $row = $(this).closest('tr'); const rowData = dataTable.row($row).data(); if (!rowData) { console.error('No row data found'); return; } const itemId = idKey2 ? `${rowData[idKey]}|${rowData[idKey2] || ''}` : rowData[idKey]; if ($(this).prop('checked')) { $row.addClass(selectedRowClass); selectedItemsMap[itemId] = rowData; } else { $row.removeClass(selectedRowClass); delete selectedItemsMap[itemId]; } updateCountCallback(); updateSelectAllCheckboxState(); }); // Select all checkbox handler - only affects current page $(tableName).on('change', selectAllClass, function () { const isChecked = $(this).prop('checked'); // Only process visible rows on current page $(tableName + ' tbody tr:visible').each(function () { const $row = $(this); const $checkbox = $row.find(checkboxClass); if ($checkbox.length === 0) { console.warn('No checkbox found in row'); return; } const rowData = dataTable.row($row).data(); if (!rowData) { console.warn('No row data found'); return; } const itemId = idKey2 ? `${rowData[idKey]}|${rowData[idKey2] || ''}` : rowData[idKey]; $checkbox.prop('checked', isChecked); if (isChecked) { $row.addClass(selectedRowClass); selectedItemsMap[itemId] = rowData; } else { $row.removeClass(selectedRowClass); delete selectedItemsMap[itemId]; } }); updateCountCallback(); updateSelectAllCheckboxState(); }); // Add event handler for pagination to update select all checkbox and restore states dataTable.on('draw.tableSelection', function () { updateRowStates(); updateSelectAllCheckboxState(); }); // Initial state update setTimeout(() => { updateRowStates(); updateSelectAllCheckboxState(); }, 100); } /** * Get count of selected items - GLOBAL REUSABLE * @param {Object} selectedItemsMap - Map of selected items * @returns {number} Count of selected items */ function getSelectedCount(selectedItemsMap) { return Object.keys(selectedItemsMap).length; } /** * Clear all table selections - GLOBAL REUSABLE * @param {string} tableName - jQuery selector for the table * @param {Object} selectedItemsMap - Map to clear * @param {Function} updateCountCallback - Callback to update count display * @param {string} [selectedRowClass='selected-row'] - CSS class for selected rows * @param {string} [selectAllClass='.select-all-checkbox'] - CSS class for select all checkbox */ function clearTableSelection(tableName, selectedItemsMap, updateCountCallback, selectedRowClass = 'selected-row', selectAllClass = '.select-all-checkbox') { // Clear the map Object.keys(selectedItemsMap).forEach(key => delete selectedItemsMap[key]); // Uncheck all checkboxes and remove selected class $(tableName + ' tbody tr').removeClass(selectedRowClass); $(tableName + ' input[type="checkbox"]').prop('checked', false); $(tableName + ' ' + selectAllClass).prop('checked', false).prop('indeterminate', false); // Update count if (updateCountCallback) { updateCountCallback(); } } /** * Utility function for show/hide elements - GLOBAL REUSABLE * @param {Array} ids - Array of element IDs * @param {string} displayValue - CSS display value ('block', 'none', etc.) */ function setDisplay(ids, displayValue) { ids.forEach(id => { const el = document.getElementById(id); if (el) el.style.display = displayValue; }); }