diff --git a/Examples/Example-TableColumnHighlight/Example-SearchBuilder.ps1 b/Examples/Example-TableColumnHighlight/Example-SearchBuilder.ps1 new file mode 100644 index 00000000..0b7d1782 --- /dev/null +++ b/Examples/Example-TableColumnHighlight/Example-SearchBuilder.ps1 @@ -0,0 +1,39 @@ +Import-Module .\PSWriteHTML.psd1 -Force + +$ProcessesAll = Get-Process | Select-Object -First 1 #-Property Name, Id, StartTime + +New-HTML -TitleText 'Title' -Online -FilePath $PSScriptRoot\Example-SearchBuilder.html -ShowHTML { + #New-HTMLTableStyle -BackgroundColor Blue -Type RowSelected + #New-HTMLTableStyle -BackgroundColor Yellow -Type RowHover + #New-HTMLTableStyle -BackgroundColor Yellow -Type RowHoverSelected + + New-HTMLSection -HeaderText 'Search Builder 1' { + New-HTMLTable -DataTable $ProcessesAll -SearchBuilder -Buttons excelHtml5, copyHtml5, csvHtml5 { + #New-HTMLTableContent -ColumnName 'PriorityClass' -BackgroundColor Salmon + #New-HTMLTableContent -ColumnName 'Company' -BackgroundColor Salmon + New-HTMLTableCondition -ColumnName 'Name' -BackgroundColor Salmon -Value '1Password' + } + } + # New-HTMLSection -HeaderText 'Search Builder as button' { + # New-HTMLTable -DataTable $ProcessesAll + # } + # # This won't really work - button + searchBuilder + # New-HTMLSection -HeaderText 'Search Builder + button' { + # # Search Builder will be disabled, button will work + # New-HTMLTable -DataTable $ProcessesAll -SearchBuilder + # } +} + +# New-HTML -TitleText 'Title' -FilePath $PSScriptRoot\Example-SearchBuilder2.html { +# New-HTMLSection -HeaderText 'Search Builder 1' { +# New-HTMLTable -DataTable $ProcessesAll -Filtering -ScrollX -SearchBuilder -Buttons excelHtml5, copyHtml5, csvHtml5 +# } +# New-HTMLSection -HeaderText 'Search Builder as button' { +# New-HTMLTable -DataTable $ProcessesAll +# } +# # This won't really work - button + searchBuilder +# New-HTMLSection -HeaderText 'Search Builder + button' { +# # Search Builder will be disabled, button will work +# New-HTMLTable -DataTable $ProcessesAll -SearchBuilder +# } +# } -ShowHTML \ No newline at end of file diff --git a/Examples/Example-TableColumnHighlight/README-ColumnHighlighter.md b/Examples/Example-TableColumnHighlight/README-ColumnHighlighter.md new file mode 100644 index 00000000..0999dc23 --- /dev/null +++ b/Examples/Example-TableColumnHighlight/README-ColumnHighlighter.md @@ -0,0 +1,206 @@ +# DataTables Column Highlighter + +A reusable JavaScript library for highlighting specific columns in DataTables responsive child rows based on configurable conditions. + +## Usage + +### 1. Include the library +```html + +``` + +### 2. Configure highlighting rules + +```javascript +const highlightConfig = [ + { + condition: { anyColumn: true, value: '1Password' }, + targets: [ + { + column: 'Company', + backgroundColor: '#fa8072', + textColor: '#000000' + }, + { + column: 'Product', + backgroundColor: '#87ceeb', + textColor: '#000000' + } + ] + } +]; +``` + +### 3. Initialize after creating your DataTable + +```javascript +// Create your DataTable +var table = $('#myTable').DataTable({ + // your DataTable configuration +}); + +// Setup column highlighting +setupColumnHighlighting('myTable', highlightConfig, table); +``` + +## Configuration Options + +### Condition Types + +#### Any Column Match +```javascript +condition: { anyColumn: true, value: 'SearchValue' } +``` +Matches if any column in the row contains the specified value. + +#### Specific Column Match +```javascript +condition: { column: 0, value: 'SearchValue' } +``` +Matches if the specified column index contains the value. + +#### No Condition (Always Apply) +```javascript +condition: null +``` +Always applies the styling (useful for global styling). + +### Target Options + +#### Basic Styling +```javascript +{ + column: 'Company', // Column name to target + backgroundColor: '#fa8072', // Background color + textColor: '#000000' // Text color +} +``` + +#### Advanced Styling +```javascript +{ + column: 'Company', + backgroundColor: '#fa8072', + textColor: '#ffffff', + css: { // Custom CSS properties + 'font-weight': 'bold', + 'border': '2px solid #000' + }, + highlightParent: true // Also highlight parent element +} +``` + +## Examples + +### Example 1: Single Row, Multiple Columns +```javascript +const config = [ + { + condition: { anyColumn: true, value: '1Password' }, + targets: [ + { column: 'Company', backgroundColor: '#fa8072' }, + { column: 'Product', backgroundColor: '#87ceeb' }, + { column: 'Description', backgroundColor: '#98fb98' } + ] + } +]; +``` + +### Example 2: Multiple Conditions +```javascript +const config = [ + { + condition: { anyColumn: true, value: '1Password' }, + targets: [ + { column: 'Company', backgroundColor: '#fa8072' } + ] + }, + { + condition: { anyColumn: true, value: 'Chrome' }, + targets: [ + { column: 'Company', backgroundColor: '#4285f4', textColor: '#ffffff' } + ] + } +]; +``` + +### Example 3: Global Highlighting +```javascript +const config = [ + { + condition: null, // Always apply + targets: [ + { column: 'CPU', backgroundColor: '#fffacd' }, + { column: 'Memory', backgroundColor: '#f0f8ff' } + ] + } +]; +``` + +### Example 4: Column Index Based +```javascript +const config = [ + { + condition: { column: 0, value: 'SpecificProcess' }, // First column + targets: [ + { column: 'Status', backgroundColor: '#90ee90' } + ] + } +]; +``` + +## Advanced Usage + +### Custom CSS +```javascript +{ + column: 'Priority', + css: { + 'background': 'linear-gradient(45deg, #ff6b6b, #ee5a52)', + 'color': 'white', + 'font-weight': 'bold', + 'border-radius': '4px', + 'padding': '4px 8px' + } +} +``` + +### Conditional Styling Based on Values +You can create multiple configurations for different scenarios: + +```javascript +const config = [ + { + condition: { column: 2, value: 'High' }, // Priority column + targets: [ + { column: 'Status', backgroundColor: '#ff4444', textColor: '#ffffff' } + ] + }, + { + condition: { column: 2, value: 'Medium' }, + targets: [ + { column: 'Status', backgroundColor: '#ffaa00', textColor: '#000000' } + ] + }, + { + condition: { column: 2, value: 'Low' }, + targets: [ + { column: 'Status', backgroundColor: '#44ff44', textColor: '#000000' } + ] + } +]; +``` + +## Minimal Setup Example + +For a quick setup with minimal code in your table: + +```javascript +// After your DataTable is created +setupColumnHighlighting('myTableId', [ + { + condition: { anyColumn: true, value: 'TargetValue' }, + targets: { column: 'ColumnName', backgroundColor: '#color' } + } +], table); +``` \ No newline at end of file diff --git a/Examples/Example-TableColumnHighlight/datatables-column-highlighter.js b/Examples/Example-TableColumnHighlight/datatables-column-highlighter.js new file mode 100644 index 00000000..8e0fc7f1 --- /dev/null +++ b/Examples/Example-TableColumnHighlight/datatables-column-highlighter.js @@ -0,0 +1,189 @@ +/** + * DataTables Column Highlighter for Responsive Child Rows + * Allows highlighting specific columns in expanded child rows based on configuration + */ + +// Main highlighting system +window.DataTablesColumnHighlighter = { + // Storage for table configurations + configurations: {}, + + /** + * Initialize highlighting for a table + * @param {string} tableId - The ID of the DataTable + * @param {Array} config - Array of column highlighting configurations + * @param {Object} table - The DataTable instance + */ + init: function(tableId, config, table) { + console.log('Initializing DataTables Column Highlighter for:', tableId); + + // Store configuration + this.configurations[tableId] = { + config: config, + table: table + }; + + // Set up event handlers + this.setupEventHandlers(tableId, table); + }, + + /** + * Set up event handlers for the table + */ + setupEventHandlers: function(tableId, table) { + const self = this; + + // Method 1: DataTables API event handler + table.on('click', 'td.dtr-control', function (e) { + console.log('Expand button clicked via DataTables API'); + let tr = e.target.closest('tr'); + let row = table.row(tr); + + setTimeout(function() { + if (row.child.isShown()) { + console.log('Row expanded, applying highlighting...'); + self.applyHighlighting(tableId, $(tr), row.data()); + } + }, 100); + }); + + // Method 2: jQuery fallback event handler + $(`#${tableId} tbody`).on('click', 'td.dtr-control, td.dt-control, .dtr-control, .dt-control', function () { + console.log('Expand button clicked via jQuery fallback'); + let $tr = $(this).closest('tr'); + + setTimeout(function() { + let childRow = $tr.next('tr.child'); + if (childRow.length > 0) { + console.log('Child row found, applying highlighting...'); + // Get row data from the DOM since we don't have the DataTables row object + let rowData = []; + $tr.find('td').each(function(index) { + if (!$(this).hasClass('dtr-control') && !$(this).hasClass('dt-control')) { + rowData.push($(this).text().trim()); + } + }); + self.applyHighlighting(tableId, $tr, rowData); + } + }, 100); + }); + }, + + /** + * Apply highlighting based on configuration + */ + applyHighlighting: function(tableId, $parentRow, rowData) { + const config = this.configurations[tableId].config; + const childRow = $parentRow.next('tr.child'); + + if (childRow.length === 0) { + console.log('No child row found'); + return; + } + + console.log('Applying highlighting with config:', config); + console.log('Row data:', rowData); + + // Process each configuration rule + config.forEach(rule => { + this.processRule(rule, childRow, rowData); + }); + }, + + /** + * Process a single highlighting rule + */ + processRule: function(rule, childRow, rowData) { + console.log('Processing rule:', rule); + + // Check if the condition matches + if (this.matchesCondition(rule.condition, rowData)) { + console.log('Condition matched, applying styling...'); + + // Apply styling to target columns + rule.targets.forEach(target => { + this.applyColumnStyling(childRow, target); + }); + } + }, + + /** + * Check if a condition matches the row data + */ + matchesCondition: function(condition, rowData) { + if (!condition) return true; // No condition means always apply + + // Support different condition types + if (condition.column !== undefined && condition.value !== undefined) { + // Column index-based condition + if (typeof condition.column === 'number') { + return rowData[condition.column] === condition.value; + } + // Column name-based condition would require header mapping + } + + if (condition.anyColumn && condition.value !== undefined) { + // Check if any column contains the value + return rowData.some(cellValue => cellValue === condition.value); + } + + return false; + }, + + /** + * Apply styling to a specific column in the child row + */ + applyColumnStyling: function(childRow, target) { + console.log('Applying styling to column:', target.column); + + // Find the target column in the child row + childRow.find('*').each(function() { + const $elem = $(this); + const text = $elem.text().trim(); + + if (text === target.column) { + console.log('Found target column element:', target.column); + + // Apply styling to the data element + const $dataElem = $elem.siblings('.dtr-data').length > 0 ? + $elem.siblings('.dtr-data') : + $elem.next(); + + if (target.backgroundColor) { + $dataElem.css('background-color', target.backgroundColor); + } + + if (target.textColor) { + $dataElem.css('color', target.textColor); + } + + if (target.css) { + $dataElem.css(target.css); + } + + // Also try parent element in case structure is different + if (target.highlightParent) { + $elem.parent().css('background-color', target.backgroundColor); + if (target.textColor) { + $elem.parent().css('color', target.textColor); + } + } + } + }); + }, + + /** + * Helper method to create simple configuration + */ + createConfig: function(conditions, targets) { + return [{ + condition: conditions, + targets: Array.isArray(targets) ? targets : [targets] + }]; + } +}; + +// Helper function for easy setup +window.setupColumnHighlighting = function(tableId, config, table) { + DataTablesColumnHighlighter.init(tableId, config, table); +}; \ No newline at end of file