1// ============================================================ 2// nlpfin.github.io â publications live search & filter 3// Renders the complete list in the original section order: 4// Latest, Book, Conference (grouped by year), Journal, 5// Preprint, Overview, Workshop. 6// Requires: assets/js/publications-data.js (const PUBLICATIONS) 7// ============================================================ 8(function () { 9 'use strict'; 10 11 document.addEventListener('DOMContentLoaded', function () { 12 if (typeof PUBLICATIONS === 'undefined') return; 13 14 var listEl = document.getElementById('pub-list'); 15 var emptyEl = document.getElementById('pub-empty'); 16 var searchEl = document.getElementById('pub-search-input'); 17 var typeRow = document.getElementById('filter-types'); 18 19 var state = { q: '', type: 'All' }; 20 21 var SECTION_ORDER = ['Latest', 'Book', 'Conference', 'Journal', 'Preprint', 'Overview', 'Workshop']; 22 var SECTION_LABEL = { 23 Latest: 'Latest', 24 Book: 'Book', 25 Conference: 'Peer-Reviewed Conference Papers', 26 Journal: 'Journal Articles', 27 Preprint: 'Preprints', 28 Overview: 'Research Agenda / Tutorial / Shared Task Overview Papers', 29 Workshop: 'Workshop Papers' 30 }; 31 var TYPE_ORDER = ['All'].concat(SECTION_ORDER); 32 var TYPE_LABEL = { 33 All: 'All', Latest: 'Latest', Conference: 'Conference', Journal: 'Journal', 34 Book: 'Book', Overview: 'Agenda & Overview', Workshop: 'Workshop', Preprint: 'Preprint' 35 }; 36 37 TYPE_ORDER.forEach(function (t, idx) { 38 var b = document.createElement('button'); 39 b.className = 'chip' + (idx === 0 ? ' on' : ''); 40 b.type = 'button'; 41 b.textContent = TYPE_LABEL[t]; 42 b.addEventListener('click', function () { 43 state.type = t; 44 typeRow.querySelectorAll('.chip').forEach(function (c) { c.classList.remove('on'); }); 45 b.classList.add('on'); 46 render(); 47 }); 48 typeRow.appendChild(b); 49 }); 50 51 var debounce; 52 if (searchEl) { 53 searchEl.addEventListener('input', function () { 54 clearTimeout(debounce); 55 debounce = setTimeout(function () { 56 state.q = searchEl.value.trim().toLowerCase(); 57 render(); 58 }, 120); 59 }); 60 } 61 62 function matches(p) { 63 if (state.type !== 'All' && p.s !== state.type) return false; 64 if (state.q) { 65 var hay = p.x.toLowerCase(); 66 var terms = state.q.split(/\s+/); 67 for (var i = 0; i < terms.length; i++) { 68 if (hay.indexOf(terms[i]) === -1) return false; 69 } 70 } 71 return true; 72 } 73 74 function esc(s) { 75 return String(s || '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); 76 } 77 78 function fmt(p) { 79 var t = esc(p.x).replace(/Chung-Chi Chen/g, '<strong>Chung-Chi Chen</strong>'); 80 // trim trailing bare link words (the links themselves are shown below) 81 t = t.replace(/\s+(pdf|dataset|website|site|code|Open Access|Proceedings|slides)(\s+(pdf|dataset|website|site|code|Open Access|Proceedings|slides))*\s*$/i, ''); 82 return t; 83 } 84 85 function itemNode(p) { 86 var d = document.createElement('article'); 87 d.className = 'pub-item'; 88 var linksHtml = ''; 89 Object.keys(p.l || {}).forEach(function (k) { 90 var url = p.l[k]; 91 if (!url) return; 92 linksHtml += '<a href="' + esc(url) + '" target="_blank" rel="noopener">' + esc(k) + ' â</a>'; 93 }); 94 d.innerHTML = 95 '<p class="pub-title" style="font-weight: 500; font-family: var(--font-body); font-size: .98rem;">' + fmt(p) + '</p>' + 96 (linksHtml ? '<div class="pub-links">' + linksHtml + '</div>' : ''); 97 return d; 98 } 99 100 function render() { 101 var filtered = PUBLICATIONS.filter(matches); 102 listEl.innerHTML = ''; 103 if (emptyEl) emptyEl.style.display = filtered.length ? 'none' : 'block'; 104 105 SECTION_ORDER.forEach(function (sec) { 106 var items = filtered.filter(function (p) { return p.s === sec; }); 107 if (!items.length) return; 108 109 var h = document.createElement('h2'); 110 h.className = 'pub-year-header'; 111 h.textContent = SECTION_LABEL[sec]; 112 listEl.appendChild(h); 113 114 if (sec === 'Conference') { 115 // group by year, descending, preserving order within each year 116 var years = [];
117 items.forEach(function (p) { 118 var y = p.y || 'Other'; 119 if (years.indexOf(y) === -1) years.push(y); 120 }); 121 years.sort(function (a, b) { 122 if (a === 'Other') return 1; if (b === 'Other') return -1; 123 return b.localeCompare(a); 124 }); 125 years.forEach(function (y) { 126 var yh = document.createElement('h3'); 127 yh.style.cssText = 'font-family: var(--font-head); font-size: 1.15rem; font-weight: 700; color: var(--primary-deep); margin: 1.3rem 0 .8rem;'; 128 yh.textContent = y; 129 listEl.appendChild(yh); 130 items.forEach(function (p) { 131 if ((p.y || 'Other') === y) listEl.appendChild(itemNode(p)); 132 }); 133 }); 134 } else { 135 items.forEach(function (p) { listEl.appendChild(itemNode(p)); }); 136 } 137 }); 138 } 139 140 render(); 141 }); 142})();
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.