PageSourceSearch

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

js 2pipe.app collected 2026-10-03 21:37:08 UTC 11,040 bytes, 238 lines download raw bytes

1// Papers Gallery functionality (similar to pipeline gallery)
2document.addEventListener('DOMContentLoaded', function() {
3    const papersSection = document.getElementById('papers-section');
4    const papersContainer = document.getElementById('papers-container');
5    const papersBtn = document.getElementById('papers-btn');
6    const closePapersBtn = document.getElementById('close-papers-btn');
7
8    if (!papersSection || !papersContainer || !papersBtn || !closePapersBtn || typeof window.PAPERS_REVIEW === 'undefined') {
9        return;
10    }
11
12    // Create category navigation menu (reuse styles)
13    const categoryNav = document.createElement('div');
14    categoryNav.className = 'category-nav';
15    const categoryMenu = document.createElement('div');
16    categoryMenu.className = 'category-menu';
17    categoryNav.appendChild(categoryMenu);
18    papersSection.insertBefore(categoryNav, papersContainer);
19
20    // Ensure a brief description card exists inside the container
21    function ensureDescription() {
22        let desc = document.getElementById('papers-description');
23        if (!desc) {
24            desc = document.createElement('div');
25            desc.id = 'papers-description';
26            desc.className = 'workflow-info-content';
27            desc.innerHTML = `
28                <h3 style="color: var(--accent-color); margin-top: 0;">Important information</h3>
29                <p style="font-size: 1.1rem; line-height: 1.6;">
30                    This page lists benchmark studies and key literature relevant to MAG reconstruction.
31                    When clicking on any paper, a view of its summary or an excerpt that describes the study, plus a key-figure, will be displayed.
32                    Please keep in mind that this is not a comprehensive list, and you are invited to check the suggested papers completely to have a better overview of the work.
33                </p>
34            `;
35            // Insert inside the container so it shares the same width as sections
36            desc.style.gridColumn = '1 / -1';
37            desc.style.width = '100%';
38        }
39        // Attach to top of container
40        if (papersContainer.firstChild !== desc) {
41            papersContainer.insertBefore(desc, papersContainer.firstChild);
42        }
43        return desc;
44    }
45
46    // Back to top button
47    const backToTopBtn = initializeBackToTopButton(papersSection);
48
49    function handleScroll() {
50        const nav = papersSection.querySelector('.category-nav');
51        const scrollPosition = papersSection.scrollTop;
52        if (scrollPosition > 300) nav.classList.add('hidden'); else nav.classList.remove('hidden');
53        updateActiveCategory();
54    }
55    papersSection.addEventListener('scroll', handleScroll);
56
57    // Build categories from data
58    const categories = Array.from(new Set(PAPERS_REVIEW.map(p => p.category))).sort((a, b) => a.localeCompare(b));
59
60    let currentDetailCategory = null;
61
62    function createCategoryNav() {
63        categoryMenu.innerHTML = '';
64        categories.forEach(category => {
65            const menuItem = document.createElement('a');
66            menuItem.href = `#${category.toLowerCase().replace(/\s+/g, '-')}`;
67            menuItem.textContent = category;
68            menuItem.addEventListener('click', (e) => {
69                e.preventDefault();
70                // If in detail view, rebuild list and expand the chosen category
71                if (currentDetailCategory !== null) {
72                    createPapersItems(category);
73                    currentDetailCategory = null;
74                }
75                // Scroll to the category header
76                setTimeout(() => {
77                    const targetCategory = papersContainer.querySelector(`.gallery-category-header[data-category="${category}"]`);
78                    if (targetCategory) {
79                        targetCategory.scrollIntoView({ behavior: 'smooth' });
80                        categoryMenu.querySelectorAll('a').forEach(link => link.classList.remove('active'));
81                        menuItem.classList.add('active');
82                    }
83                }, 0);
84            });
85            categoryMenu.appendChild(menuItem);
86        });
87    }
88
89    function updateActiveCategory() {
90        const headers = papersContainer.querySelectorAll('.gallery-category-header');
91        const scrollPosition = papersSection.scrollTop;
92        headers.forEach(header => {
93            const category = header.dataset.category;
94            const headerTop = header.offsetTop - categoryNav.offsetHeight;
95            const headerBottom = headerTop + header.offsetHeight;
96            if (scrollPosition >= headerTop && scrollPosition < headerBottom) {
97                const menuItem = categoryMenu.querySelector(`a[href="#${category.toLowerCase().replace(/\s+/g, '-')}"]`);
98                if (menuItem) {
99                    categoryMenu.querySelectorAll('a').forEach(link => link.classList.remove('active'));
100                    menuItem.classList.add('active');
101                }
102            }
103        });
104    }
105
106    function createPapersItems(expandCategoryName) {
107        papersContainer.innerHTML = '';
108        ensureDescription();
109        // Group by category and sort by name
110        const byCategory = {};
111        const sorted = [...PAPERS_REVIEW].sort((a, b) => (a.name || '').localeCompare(b.name || '', undefined, { sensitivity: 'base' }));
112        sorted.forEach(paper => {
113            const category = paper.category || 'Other';
114            if (!byCategory[category]) byCategory[category] = [];
115            byCategory[category].push(paper);
116        });
117
118        categories.forEach(category => {
119            if (byCategory[category] && byCategory[category].length > 0) {
120                // Category header with collapse/expand
121                const categoryHeader = document.createElement('div');
122                categoryHeader.className = 'gallery-category-header';
123                categoryHeader.dataset.category = category;
124                categoryHeader.innerHTML = `<h3>${category} <span class="category-hint" style="font-weight:400; opacity:0.8; font-size:0.9rem;">(click to expand)</span></h3>`;
125                papersContainer.appendChild(categoryHeader);
126
127                const listContainer = document.createElement('div');
128                listContainer.className = 'papers-list-container';
129                listContainer.style.display = 'none';
130                // Make the list span the full gallery width
131                listContainer.style.gridColumn = '1 / -1';
132                listContainer.style.width = '100%';
133                papersContainer.appendChild(listContainer);
134
135                // Toggle category visibility when header clicked
136                categoryHeader.style.cursor = 'pointer';
137                categoryHeader.addEventListener('click', () => {
138                    const isHidden = listContainer.style.display === 'none';
139                    listContainer.style.display = isHidden ? 'block' : 'none';
140                });
141
142                // Build a simple list of paper titles
143                const ul = document.createElement('ul');
144                ul.style.listStyle = 'none';
145                ul.style.padding = '0';
146                ul.style.margin = '0';
147                ul.style.width = '100%';
148                byCategory[category].forEach(paper => {
149                    const li = document.createElement('li');
150                    li.style.margin = '0.25rem 0';
151                    li.style.width = '100%';
152                    const btn = document.createElement('button');
153                    btn.textContent = paper.name;
154                    btn.style.width = '100%';
155                    btn.style.textAlign = 'left';
156                    btn.style.padding = '0.75rem 1rem';
157                    btn.style.border = '1px solid var(--border-color)';
158                    btn.style.background = 'var(--container-bg)';
159                    btn.style.color = 'var(--text-color)';
160                    btn.style.borderRadius = '8px';
161                    btn.style.cursor = 'pointer';
162                    btn.style.fontSize = '1.1rem';
163                    btn.addEventListener('mouseover', () => { btn.style.borderColor = 'var(--accent-color)'; });
164                    btn.addEventListener('mouseout', () => { btn.style.borderColor = 'var(--border-color)'; });
165                    btn.addEventListener('click', () => {
166                        showPaperDetail(paper, category);
167                    });
168                    li.appendChild(btn);
169                    ul.appendChild(li);
170                });
171                listContainer.appendChild(ul);
172
173                if (expandCategoryName && expandCategoryName === category) {
174                    listContainer.style.display = 'block';
175                }
176            }
177        });
178    }
179
180    function showPaperDetail(paper, categoryToExpand) {
181        currentDetailCategory = categoryToExpand;
182        papersContainer.innerHTML = '';
183        const detailWrapper = document.createElement('div');
184        detailWrapper.className = 'gallery-item';
185        const card = document.createElement('div');
186        card.className = 'gallery-card';
187        const content = document.createElement('div');
188        content.className = 'gallery-content';
189        content.innerHTML = `
190            <h3>
190${paper.name}</h3>
191            <p style="margin:0 0 1rem 0;">${paper.abstract}</p>
192            <a href="${paper.link}" target="_blank" class="workflow-link"><i class="fas fa-external-link-alt"></i> Read paper</a>
193        `;
194        const img = document.createElement('img');
195        img.src = `papers/${paper.id}.png`;
196        img.alt = paper.name;
197        img.className = 'paper-detail-image';
198        img.onerror = function() { this.src = 'images/default-pipeline.png'; };
199
200        const backBtn = document.createElement('a');
201        backBtn.href = '#';
202        backBtn.className = 'workflow-link';
203        backBtn.style.marginTop = '1rem';
204        backBtn.innerHTML = '<i class="fas fa-arrow-left"></i> Back to list';
205        backBtn.addEventListener('click', (e) => {
206            e.preventDefault();
207            createPapersItems(categoryToExpand);
208            const header = papersContainer.querySelector(`.gallery-category-header[data-category="${categoryToExpand}"]`);
209            if (header) header.scrollIntoView({ behavior: 'smooth' });
210        });
211
212        card.appendChild(content);
213        card.appendChild(img);
214        card.appendChild(backBtn);
215        detailWrapper.appendChild(card);
216        papersContainer.appendChild(detailWrapper);
217    }
218
219    function showPapers() {
220        papersSection.style.display = 'block';
221        document.body.style.overflow = 'hidden';
222        createPapersItems();
223    }
224
225    function hidePapers() {
226        papersSection.style.display = 'none';
227        document.body.style.overflow = 'auto';
228    }
229
230    papersBtn.addEventListener('click', showPapers);
231    closePapersBtn.addEventListener('click', hidePapers);
232
233    // Initialize
234    createCategoryNav();
235    createPapersItems();
236});
237
238

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.