PageSourceSearch

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

js 2pipe.app collected 2026-10-03 21:37:07 UTC 9,742 bytes, 235 lines download raw bytes

1// Tools Table built from MAG_PIPELINES, similar layout/UX to table.js
2document.addEventListener('DOMContentLoaded', function() {
3    const section = document.getElementById('tools-table-section');
4    const container = document.getElementById('tools-table-container');
5    const openBtn = document.getElementById('tools-table-btn');
6    const closeBtn = document.getElementById('close-tools-table-btn');
7
8    if (!section || !container || !openBtn || !closeBtn) {
9        return;
10    }
11
12    // Config
13    const COLUMNS_PER_PAGE = 5; // show fewer because cells are longer text
14    let currentPage = 0;
15    const filterValues = {};
16
17    // Back to top
18    const backToTopBtn = initializeBackToTopButton(section);
19
20    // Column definitions mapped to MAG_PIPELINES keys
21    const columnDefinitions = [
22        { header: 'Number', key: 'index', noFilter: true },
23        { header: 'Pipeline Name', key: 'name' },
24        { header: 'QC', key: 'qc' },
25        { header: 'Assembly', key: 'assembly' },
26        { header: 'Binning', key: 'binning' },
27        { header: 'Quality Assessment', key: 'qualityAssessment' },
28        { header: 'Refinement', key: 'refinement' },
29        { header: 'Taxonomy', key: 'taxonomy' },
30        { header: 'Functional Annotation', key: 'functionalAnnotation' },
31        { header: 'Other', key: 'other' }
32    ];
33
34    function createTable() {
35        container.innerHTML = '';
36
37        const navigationControls = document.createElement('div');
38        navigationControls.className = 'table-navigation';
39
40        const prevButton = document.createElement('button');
41        prevButton.className = 'nav-control-btn';
42        prevButton.textContent = '← Previous Features';
43        prevButton.addEventListener('click', () => changePage(-1));
44
45        const nextButton = document.createElement('button');
46        nextButton.className = 'nav-control-btn';
47        nextButton.textContent = 'More Features →';
48        nextButton.addEventListener('click', () => changePage(1));
49
50        const pageInfo = document.createElement('span');
51        pageInfo.className = 'page-info';
52
53        navigationControls.appendChild(prevButton);
54        navigationControls.appendChild(pageInfo);
55        navigationControls.appendChild(nextButton);
56        container.appendChild(navigationControls);
57
58        const table = document.createElement('table');
59        table.className = 'pipeline-table';
60
61        const thead = document.createElement('thead');
62        const headerRow = document.createElement('tr');
63
64        columnDefinitions.forEach((col, index) => {
65            const th = document.createElement('th');
66            th.dataset.columnIndex = index;
67
68            const headerText = document.createElement('div');
69            headerText.textContent = col.header;
70            th.appendChild(headerText);
71
72            if (!col.noFilter) {
73                const filterInput = document.createElement('input');
74                filterInput.type = 'text';
75                filterInput.className = 'filter-input';
76                filterInput.placeholder = 'Filter...';
77                filterInput.addEventListener('input', filterTable);
78                th.appendChild(filterInput);
79            }
80
81            headerRow.appendChild(th);
82        });
83
84        thead.appendChild(headerRow);
85        table.appendChild(thead);
86
87        const tbody = document.createElement('tbody');
88
89        const DATA = (typeof window.MAG_PIPELINES_XLSX !== 'undefined') ? window.MAG_PIPELINES_XLSX : (typeof window.MAG_PIPELINES !== 'undefined' ? window.MAG_PIPELINES : []);
90        const sorted = [...DATA].sort((a, b) => (a.name || '').localeCompare(b.name || '', undefined, { sensitivity: 'base' }));
91        sorted.forEach((p, index) => {
92            const row = document.createElement('tr');
93            columnDefinitions.forEach((col, colIndex) => {
94                const cell = document.createElement('td');
95                cell.dataset.columnIndex = colIndex;
96
97                if (col.key === 'index') {
98                    cell.textContent = index + 1;
99                } else if (col.key === 'name') {
100                    const nameLink = document.createElement('a');
101                    nameLink.href = '#';
102                    nameLink.textContent = p.name || '';
103                    nameLink.addEventListener('click', (e) => {
104                        e.preventDefault();
105                        hideToolsTable();
106                        const workflowSection = document.getElementById('workflow-section');
107                        const pipelineSelect = document.getElementById('pipeline-select');
108                        if (workflowSection && pipelineSelect) {
109                            workflowSection.style.display = 'block';
110                            const id = mapNameToId(p.name);
111                            if (id) {
112                                pipelineSelect.value = id;
113                                const event = new Event('change');
114                                pipelineSelect.dispatchEvent(event);
115                            }
116                        }
117                    });
118                    cell.appendChild(nameLink);
119                } else {
120                    const arr = p.attributes && Array.isArray(p.attributes[col.key]) ? p.attributes[col.key] : [];
121                    cell.textContent = arr.length ? arr.join(', ') : '';
122                }
123
124                row.appendChild(cell);
125            });
126            tbody.appendChild(row);
127        });
128
129        table.appendChild(tbody);
130        container.appendChild(table);
131
132        updatePageDisplay();
133    }
134
135    function mapNameToId(name) {
136        if (typeof preLoadedObjects !== 'undefined') {
137            const match = preLoadedObjects.find(o => o.name.toLowerCase() === name.toLowerCase());
138            return match ? match.id : '';
139        }
140        return '';
141    }
142
143    function changePage(delta) {
144        const totalColumns = document.querySelectorAll('#tools-table-section .pipeline-table th').length;
145        const totalPages = Math.ceil((totalColumns - 2) / (COLUMNS_PER_PAGE - 2));
146        currentPage = Math.max(0, Math.min(currentPage + delta, totalPages - 1));
147        updatePageDisplay();
148    }
149
150    function updatePageDisplay() {
151        const tableEl = section.querySelector('.pipeline-table');
152        if (!tableEl) return;
153        const totalColumns = tableEl.querySelectorAll('th').length;
154        const totalPages = Math.ceil((totalColumns - 2) / (COLUMNS_PER_PAGE - 2));
155
156        const pageInfo = section.querySelector('.page-info');
157        if (pageInfo) pageInfo.textContent = `Page ${currentPage + 1} of ${totalPages}`;
158
159        const startCol = currentPage * (COLUMNS_PER_PAGE - 2);
160        const endCol = Math.min(startCol + (COLUMNS_PER_PAGE - 2), totalColumns - 1);
161
162        section.querySelectorAll('.pipeline-table th, .pipeline-table td').forEach(element => {
163            const colIndex = parseInt(element.dataset.columnIndex);
164            if (colIndex <= 1) {
165                element.style.display = '';
166            } else if (colIndex > startCol + 1 && colIndex <= endCol + 1) {
167                element.style.display = '';
168                if (element.classList && element.classList.contains('filter-input')) {
169                    element.value = filterValues[colIndex] || '';
170                }
171            } else {
172                if (element.classList && element.classList.contains('filter-input')) {
173                    filterValues[colIndex] = element.value;
174                }
175                element.style.display = 'none';
176            }
177        });
178
179        const prevButton = section.querySelector('.nav-control-btn:first-child');
180        const nextButton = section.querySelector('.nav-control-btn:last-child');
181        if (prevButton) prevButton.disabled = currentPage === 0;
182        if (nextButton) nextButton.disabled = currentPage === totalPages - 1;
183    }
184
185    function filterTable() {
186        const tableEl = section.querySelector('.pipeline-table');
187        if (!tableEl) return;
188        const rows = tableEl.querySelectorAll('tbody tr');
189        const allColumns = Array.from(tableEl.querySelectorAll('th')).map(th => parseInt(th.dataset.columnIndex));
190
191        const filters = allColumns.map(colIndex => {
192            const filterInput = tableEl.querySelector(`th[data-column-index="${colIndex}"] .filter-input`);
193            if (filterInput) {
194                filterValues[colIndex] = filterInput.value;
195                return filterInput.value.toLowerCase();
196            }
197            return filterValues[colIndex] ? filterValues[colIndex].toLowerCase() : '';
198        });
199
200        rows.forEach(row => {
201            const cells = Array.from(row.cells);
202            let show = true;
203            allColumns.forEach((colIndex, filterIndex) => {
204                const cell = cells[colIndex];
205                const cellText = (cell.textContent || '').toLowerCase();
206                const filterText = filters[filterIndex];
207                if (filterText && !cellText.includes(filterText)) show = false;
208            });
209            row.style.display = show ? '' : 'none';
210        });
211    }
212
213    function showToolsTable() {
214        section.style.display = 'block';
215        document.body.style.overflow = 'hidden';
216        // Reset state
217        currentPage = 0;
218        Object.keys(filterValues).forEach(k => delete filterValues[k]);
219        createTable();
220    }
221
222    function hideToolsTable() {
223        section.style.display = 'none';
224        document.body.style.overflow = 'auto';
225    }
226
227    openBtn.addEventListener('click', showToolsTable);
228    closeBtn.addEventListener('click', hideToolsTable);
229
230    // Export
231    window.showToolsTable = showToolsTable;
232    window.hideToolsTable = hideToolsTable;
233});
234
235

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.