/* ============================================================ library.js — Papers 탭 (논문 테이블 + 발굴 신규 논문) ============================================================ */ (function () { 'use strict'; let papers = [], filtered = [], page = 1, sortCol = 'pubYear', sortDir = -1; let paperTargets = {}; const PAGE = 20; function el(id) { return document.getElementById(id); } function init() { papers = (Store.analysis && Store.analysis.papers) || []; // 논문 → 표적 단백질 역색인 (카탈로그 근거 기반) Store.catalog.proteins.forEach(p => (p.evidence_paper_ids || []).forEach(id => { (paperTargets[id] = paperTargets[id] || []).push(p.gene); })); const disSel = el('filter-disease'), ySel = el('filter-year'); [...new Set(papers.map(p => p.disease).filter(Boolean))].sort().forEach(d => disSel.add(new Option(d, d))); [...new Set(papers.map(p => p.pubYear).filter(y => /^\d{4}$/.test(y)))].sort().reverse().forEach(y => ySel.add(new Option(y, y))); el('search-input').addEventListener('input', apply); disSel.addEventListener('change', apply); ySel.addEventListener('change', apply); document.querySelectorAll('#tab-papers .sortable').forEach(th => th.onclick = () => { const c = th.dataset.col; if (sortCol === c) sortDir *= -1; else { sortCol = c; sortDir = 1; } apply(); }); el('btn-prev').onclick = () => { if (page > 1) { page--; renderTable(); } }; el('btn-next').onclick = () => { if (page * PAGE < filtered.length) { page++; renderTable(); } }; renderNewPapers(); apply(); } function apply() { const q = el('search-input').value.trim().toLowerCase(); const dis = el('filter-disease').value, yr = el('filter-year').value; filtered = papers.filter(p => { if (dis && p.disease !== dis) return false; if (yr && p.pubYear !== yr) return false; if (q && !((p.title || '').toLowerCase().includes(q) || (p.abstract || '').toLowerCase().includes(q))) return false; return true; }); filtered.sort((a, b) => { const x = (a[sortCol] || ''), y = (b[sortCol] || ''); return (x < y ? -1 : x > y ? 1 : 0) * sortDir; }); page = 1; renderTable(); } function renderTable() { el('table-count').textContent = filtered.length; const start = (page - 1) * PAGE; const rows = filtered.slice(start, start + PAGE); el('papers-tbody').innerHTML = rows.length ? rows.map(p => { const tg = (paperTargets[p.id] || []).slice(0, 6); return `