PageSourceSearch

https://2pipe.app/table.js

js 2pipe.app collected 2026-10-03 21:37:06 UTC 14,607 bytes, 321 lines download raw bytes

1// Table functionality
2document.addEventListener('DOMContentLoaded', function() {
3    const tableSection = document.getElementById('table-section');
4    const tableContainer = document.getElementById('table-container');
5    const tableBtn = document.getElementById('table-btn');
6    const closeTableBtn = document.getElementById('close-table-btn');
7
8    if (!tableSection || !tableContainer || !tableBtn || !closeTableBtn) {
9        console.error('Required table elements not found');
10        return;
11    }
12
13    // Configuration
14    const COLUMNS_PER_PAGE = 7; // Number of columns to show per page (including pipeline name)
15    let currentPage = 0;
16    const filterValues = {}; // Store filter values for each column
17    let currentTableEl = null; // reference to the currently rendered table element
18
19    // Function to reset all filters
20    function resetFilters() {
21        if (!currentTableEl) return;
22        // Clear all filter inputs
23        const filterInputs = currentTableEl.querySelectorAll('.filter-input');
24        filterInputs.forEach(input => {
25            input.value = '';
26            const th = input.closest('th');
27            if (th && th.dataset.columnIndex) {
28                filterValues[th.dataset.columnIndex] = '';
29            }
30        });
31
32        // Show all rows
33        const rows = currentTableEl.querySelectorAll('tbody tr');
34        rows.forEach(row => {
35            row.style.display = '';
36        });
37
38        // Reset current page to first page
39        currentPage = 0;
40        updatePageDisplay();
41    }
42
43    // Initialize back to top button
44    const backToTopBtn = initializeBackToTopButton(tableSection);
45
46    // Function to create table
47    function createTable() {
48        // Clear existing content
49        tableContainer.innerHTML = '';
50        
51        // Create table header
52        const table = document.createElement('table');
53        table.className = 'pipeline-table';
54        currentTableEl = table;
55        
56        // Create header row
57        const thead = document.createElement('thead');
58        const headerRow = document.createElement('tr');
59        
60        // Define headers and their corresponding attributes
61        const columnDefinitions = [
62            { header: 'Number', attribute: 'index', noFilter: true },
63            { header: 'Pipeline Name', attribute: null },
64            { header: 'Category', attribute: 'category' },
65            { header: 'Read Types', attribute: 'readTypes' },
66            { header: 'Multiple Samples', attribute: 'multiSample' },
67            { header: 'Co-assembly and/or \nCo-binning', attribute: 'coAssemblyCoBinning' },
68            { header: 'GUI', attribute: 'GUI' },
69            { header: 'Adapted to cloud\nenviroments (i.e. AWS, Azure)', attribute: 'Cloud' },
70            { header: 'Workflow Manager', attribute: 'workflowManager' },
71            { header: 'Bin Refinement', attribute: 'binRefinement' },
72            { header: 'External Computational Resources \n(i.e. Galaxy, MGnify)', attribute: 'externalComputationalResources' },
73            { header: 'Execution Options', attribute: 'executionOptions' },
74            { header: 'Special Features', attribute: 'specialOptions' },
75            { header: 'Last update', attribute: 'update' },
76            { header: 'License', attribute: 'license' },
77            { header: 'Number of citations', attribute: 'citations' }
78            //{ header: 'Last Commit (GitHub)', attribute: 'lastCommit', custom: true },
79            //{ header: 'Clones (GitHub)', attribute: 'clones', custom: true }
80        ];
81        
82        // Create navigation controls
83        const navigationControls = document.createElement('div');
84        navigationControls.className = 'table-navigation';
85        
86        const prevButton = document.createElement('button');
87        prevButton.className = 'nav-control-btn';
88        prevButton.textContent = '← Previous Features';
89        prevButton.addEventListener('click', () => changePage(-1));
90        
91        const nextButton = document.createElement('button');
92        nextButton.className = 'nav-control-btn';
93        nextButton.textContent = 'More Features →';
94        nextButton.addEventListener('click', () => changePage(1));
95        
96        const pageInfo = document.createElement('span');
97        pageInfo.className = 'page-info';
98        
99        navigationControls.appendChild(prevButton);
100        navigationControls.appendChild(pageInfo);
101        navigationControls.appendChild(nextButton);
102        
103        tableContainer.appendChild(navigationControls);
104        
105        // Create header cells with filter inputs
106        columnDefinitions.forEach((col, index) => {
107            const th = document.createElement('th');
108            th.dataset.columnIndex = index;
109            
110            // Create header text
111            const headerText = document.createElement('div');
112            headerText.textContent = col.header;
113            th.appendChild(headerText);
114            
115            // Add filter input for all columns except index
116            if (!col.noFilter) {
117                const filterInput = document.createElement('input');
118                filterInput.type = 'text';
119                filterInput.className = 'filter-input';
120                filterInput.placeholder = 'Filter...';
121                filterInput.addEventListener('input', filterTable);
122                th.appendChild(filterInput);
123            }
124            
125            headerRow.appendChild(th);
126        });
127        
128        thead.appendChild(headerRow);
129        table.appendChild(thead);
130        
131        // Create table body
132        const tbody = document.createElement('tbody');
133        
134        // Add rows for each pipeline (sorted alphabetically by name)
135        const sortedPipelines = [...preLoadedObjects].sort((a, b) => a.name.localeCompare(b.name, undefined, { sensitivity: 'base' }));
136        sortedPipelines.forEach((pipeline, index) => {
137            const row = document.createElement('tr');
138            
139            // Add cells for each column
140            columnDefinitions.forEach((col, colIndex) => {
141                const cell = document.createElement('td');
142                cell.dataset.columnIndex = colIndex;
143                
144                if (col.attribute === 'index') {
145                    // Index column
146                    cell.textContent = index + 1;
147                } else if (col.attribute === null) {
148                    // Pipeline name column
149                    const nameLink = document.createElement('a');
150                    nameLink.href = '#';
151                    nameLink.addEventListener('click', (e) => {
152                        e.preventDefault();
153                        // Hide table section
154                        hideTable();
155                        
156                        // Show workflow section
157                        const workflowSection = document.getElementById('workflow-section');
158                        workflowSection.style.display = 'block';
159                        
160                        // Select the pipeline in the dropdown
161                        const pipelineSelect = document.getElementById('pipeline-select');
162                        pipelineSelect.value = pipeline.id;
163                        
164                        // Trigger the change event to display the workflow
165                        const event = new Event('change');
166                        pipelineSelect.dispatchEvent(event);
167                    });
168                    nameLink.textContent = pipeline.name;
169                    cell.appendChild(nameLink);
170                } else if (col.custom) {
171                    // GitHub metrics columns
172                    const metrics = (window.PIPELINE_GITHUB_METRICS || {})[pipeline.name];
173                    if (col.attribute === 'lastCommit') {
174                        cell.textContent = metrics && metrics.lastCommit ? metrics.lastCommit : '-';
175                    } else if (col.attribute === 'clones') {
176                        cell.textContent = metrics && typeof metrics.clones !== 'undefined' ? metrics.clones : '-';
177                    }
178                } else if (col.attribute === 'specialOptions' || col.attribute === 'executionOptions' || col.attribute === 'readTypes') {
179                    // Special handling for multi-select options
180                    const value = pipeline.attributes[col.attribute] && pipeline.attributes[col.attribute].length > 0 ? 
181                        pipeline.attributes[col.attribute].join(', ') : '';
182                    cell.textContent = value;
183                } else if (col.attribute === 'workflowManager') {
184                    // Special handling for workflow manager
185                    const value = pipeline.attributes[col.attribute] && pipeline.attributes[col.attribute].length > 0 ? 
186                        pipeline.attributes[col.attribute].join(', ') : '';
187                    cell.textContent = value;
188                } else {
189                    // Regular attribute columns (binary options)
190                    const value = pipeline.attributes[col.attribute] && pipeline.attributes[col.attribute].length > 0 ? 
191                        pipeline.attributes[col.attribute][0] : '';
192                    cell.textContent = value;
193                }
194                
195                row.appendChild(cell);
196            });
197            
198            tbody.appendChild(row);
199        });
200        
201        table.appendChild(tbody);
202        tableContainer.appendChild(table);
203        
204        // Initialize page display
205        updatePageDisplay();
206    }
207
208    // Function to change page
209    function changePage(delta) {
210        const totalColumns = currentTableEl ? currentTableEl.querySelectorAll('th').length : 0;
211        const totalPages = Math.ceil((totalColumns - 2) / (COLUMNS_PER_PAGE - 2)); // Subtract 2 for pipeline name and index columns
212        
213        currentPage = Math.max(0, Math.min(currentPage + delta, totalPages - 1));
214        updatePageDisplay();
215    }
216
217    // Function to update page display
218    function updatePageDisplay() {
219        const totalColumns = currentTableEl ? currentTableEl.querySelectorAll('th').length : 0;
220        const totalPages = Math.ceil((totalColumns - 2) / (COLUMNS_PER_PAGE - 2)); // Subtract 2 for pipeline name and index columns
221        
222        // Update page info
223        const pageInfo = document.querySelector('.page-info');
224        pageInfo.textContent = `Page ${currentPage + 1} of ${totalPages}`;
225        
226        // Show/hide columns based on current page
227        const startCol = currentPage * (COLUMNS_PER_PAGE - 2); // Subtract 2 for pipeline name and index columns
228        const endCol = Math.min(startCol + (COLUMNS_PER_PAGE - 2), totalColumns - 1); // Subtract 2 for pipeline name and index columns
229        
230        // Always show first two columns (index and pipeline name)
231        if (!currentTableEl) return;
232        currentTableEl.querySelectorAll('th, td').forEach(element => {
233            const colIndex = parseInt(element.dataset.columnIndex);
234            if (colIndex <= 1) {
235                element.style.display = '';
236            } else if (colIndex > startCol + 1 && colIndex <= endCol + 1) {
237                element.style.display = '';
238                // Restore filter value if it exists
239                if (element.classList.contains('filter-input')) {
240                    element.value = filterValues[colIndex] || '';
241                }
242            } else {
243                // Save filter value before hiding
244                if (element.classList.contains('filter-input')) {
245                    filterValues[colIndex] = element.value;
246                }
247                element.style.display = 'none';
248            }
249        });
250        
251        // Update navigation buttons
252        const prevButton = tableContainer.querySelector('.nav-control-btn:first-child');
253        const nextButton = tableContainer.querySelector('.nav-control-btn:last-child');
254        
255        prevButton.disabled = currentPage === 0;
256        nextButton.disabled = currentPage === totalPages - 1;
257    }
258
259    // Function to filter table
260    function filterTable() {
261        if (!currentTableEl) return;
262        const rows = currentTableEl.querySelectorAll('tbody tr');
263        const allColumns = Array.from(currentTableEl.querySelectorAll('th'))
264            .map(th => parseInt(th.dataset.columnIndex));
265        
266        // Get filter values for all columns, not just visible ones
267        const filters = allColumns.map(colIndex => {
268            const filterInput = currentTableEl.querySelector(`th[data-column-index="${colIndex}"] .filter-input`);
269            if (filterInput) {
270                filterValues[colIndex] = filterInput.value; // Store the filter value
271                return filterInput.value.toLowerCase();
272            }
273            return filterValues[colIndex] ? filterValues[colIndex].toLowerCase() : '';
274        });
275        
276        rows.forEach(row => {
277            const cells = Array.from(row.cells);
278            let show = true;
279            
280            // Check all columns, not just visible ones
281            allColumns.forEach((colIndex, filterIndex) => {
282                const cell = cells[colIndex];
283                const cellText = cell.textContent.toLowerCase();
284                const filterText = filters[filterIndex];
285                
286                if (filterText && !cellText.includes(filterText)) {
287                    show = false;
288                }
289            });
290            
291            row.style.display = show ? '' : 'none';
292        });
293    }
294
295    // Function to show table
296    function showTable() {
297        tableSection.style.display = 'block';
298        document.body.style.overflow = 'hidden';
299        // Reset filters when showing the table
300        resetFilters();
301    }
302
303    // Function to hide table
304    function hideTable() {
305        tableSection.style.display = 'none';
306        document.body.style.overflow = 'auto';
307        // Reset filters when hiding the table
308        resetFilters();
309    }
310
311    // Event listeners
312    tableBtn.addEventListener('click', showTable);
313    closeTableBtn.addEventListener('click', hideTable);
314
315    // Make functions globally available
316    window.showTable = showTable;
317    window.hideTable = hideTable;
318
319    // Initialize table
320    createTable();
321}); 

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.