@@ -1239,18 +1239,47 @@ <h4 style="margin-bottom: 10px; color: var(--dark); font-size: 0.95rem;">${micro
12391239 let html = `
12401240 <div style="margin-bottom: 20px;">
12411241 <h3 style="color: var(--primary); margin-bottom: 10px;">${ context . title } </h3>
1242- <p style="color: #64748b; font-size: 0.9rem; margin-bottom: 10px;">${ context . subtitle } </p>
1242+ <p style="color: #64748b; font-size: 0.9rem; margin-bottom: 15px;">${ context . subtitle } </p>
1243+
1244+ <!-- Search Bar -->
1245+ <div style="margin-bottom: 15px;">
1246+ <input type="text"
1247+ id="paperSearch"
1248+ placeholder="🔍 Search papers by title, abstract, or keywords..."
1249+ class="search-box"
1250+ oninput="filterPapers()"
1251+ style="width: 100%; padding: 12px 20px; border: 2px solid var(--border); border-radius: 10px; font-size: 1rem;">
1252+ </div>
1253+
1254+ <!-- Filters and Sort -->
12431255 <div style="display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 15px;">
1256+ <!-- Sort Options -->
12441257 <button onclick="sortPapers('citations')" class="filter-btn" style="padding: 6px 12px; font-size: 0.9rem;">
1245- Sort by Citations
1258+ 📊 Sort by Citations
12461259 </button>
12471260 <button onclick="sortPapers('year-desc')" class="filter-btn" style="padding: 6px 12px; font-size: 0.9rem;">
1248- Sort by Year ( Newest)
1261+ 📅 Newest First
12491262 </button>
12501263 <button onclick="sortPapers('year-asc')" class="filter-btn" style="padding: 6px 12px; font-size: 0.9rem;">
1251- Sort by Year (Oldest)
1264+ 📅 Oldest First
1265+ </button>
1266+
1267+ <!-- Export Options -->
1268+ <button onclick="exportPapers('csv')" class="filter-btn" style="padding: 6px 12px; font-size: 0.9rem; margin-left: auto;">
1269+ 💾 Export CSV
1270+ </button>
1271+ <button onclick="exportPapers('bibtex')" class="filter-btn" style="padding: 6px 12px; font-size: 0.9rem;">
1272+ 📚 Export BibTeX
1273+ </button>
1274+ <button onclick="exportPapers('json')" class="filter-btn" style="padding: 6px 12px; font-size: 0.9rem;">
1275+ 📋 Export JSON
12521276 </button>
12531277 </div>
1278+
1279+ <!-- Results Count -->
1280+ <p id="resultsCount" style="color: #64748b; font-size: 0.9rem; margin-bottom: 10px;">
1281+ Showing ${ papers . length } paper${ papers . length !== 1 ? 's' : '' }
1282+ </p>
12541283 </div>
12551284 <div id="papersList">
12561285 ` ;
@@ -1261,8 +1290,15 @@ <h3 style="color: var(--primary); margin-bottom: 10px;">${context.title}</h3>
12611290 ? `<a href="${ doiLink } " target="_blank" rel="noopener noreferrer" style="color: var(--dark); text-decoration: none;">${ paper . title } </a>`
12621291 : paper . title ;
12631292
1293+ const searchableText = `${ paper . title } ${ paper . abstract || '' } ${ paper . l1Label || '' } ${ paper . l3Label || '' } ` . toLowerCase ( ) ;
1294+
12641295 html += `
1265- <div class="paper-item" style="margin-bottom: 15px; padding: 15px; background: #f8fafc; border-radius: 8px; border-left: 3px solid var(--primary);" data-year="${ paper . year } " data-citations="${ paper . citations } ">
1296+ <div class="paper-item"
1297+ style="margin-bottom: 15px; padding: 15px; background: #f8fafc; border-radius: 8px; border-left: 3px solid var(--primary);"
1298+ data-year="${ paper . year } "
1299+ data-citations="${ paper . citations } "
1300+ data-journal="${ paper . journal } "
1301+ data-searchable="${ searchableText } ">
12661302 <div style="font-weight: 600; margin-bottom: 8px; font-size: 1.05rem;">
12671303 ${ idx + 1 } . ${ titleHtml }
12681304 </div>
@@ -1284,9 +1320,10 @@ <h3 style="color: var(--primary); margin-bottom: 10px;">${context.title}</h3>
12841320 html += '</div>' ;
12851321 container . innerHTML = html ;
12861322
1287- // Store current papers and context for sorting
1323+ // Store current papers and context for sorting/filtering
12881324 window . currentPapers = papers ;
12891325 window . currentContext = context ;
1326+ window . allCurrentPapers = papers ; // Keep original unfiltered list
12901327 }
12911328
12921329 // Sort papers in the current view
@@ -1308,6 +1345,101 @@ <h3 style="color: var(--primary); margin-bottom: 10px;">${context.title}</h3>
13081345 // Reload with new sort
13091346 displayPaperList ( papers , window . currentContext ) ;
13101347 }
1348+
1349+ // Filter papers based on search query
1350+ function filterPapers ( ) {
1351+ const searchInput = document . getElementById ( 'paperSearch' ) ;
1352+ if ( ! searchInput || ! window . allCurrentPapers ) return ;
1353+
1354+ const query = searchInput . value . toLowerCase ( ) . trim ( ) ;
1355+
1356+ if ( ! query ) {
1357+ // Show all papers if search is empty
1358+ window . currentPapers = window . allCurrentPapers ;
1359+ displayPaperList ( window . allCurrentPapers , window . currentContext ) ;
1360+ return ;
1361+ }
1362+
1363+ // Filter papers by search query
1364+ const filtered = window . allCurrentPapers . filter ( paper => {
1365+ const searchableText = `${ paper . title } ${ paper . abstract || '' } ${ paper . l1Label || '' } ${ paper . l3Label || '' } ` . toLowerCase ( ) ;
1366+ return searchableText . includes ( query ) ;
1367+ } ) ;
1368+
1369+ window . currentPapers = filtered ;
1370+ displayPaperList ( filtered , window . currentContext ) ;
1371+ }
1372+
1373+ // Export papers in different formats
1374+ function exportPapers ( format ) {
1375+ if ( ! window . currentPapers || window . currentPapers . length === 0 ) {
1376+ alert ( 'No papers to export!' ) ;
1377+ return ;
1378+ }
1379+
1380+ const papers = window . currentPapers ;
1381+ const context = window . currentContext || { title : 'Papers' } ;
1382+ const filename = `papers_${ context . title . replace ( / [ ^ a - z 0 - 9 ] / gi, '_' ) . toLowerCase ( ) } _${ new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] } ` ;
1383+
1384+ if ( format === 'csv' ) {
1385+ exportCSV ( papers , filename ) ;
1386+ } else if ( format === 'bibtex' ) {
1387+ exportBibTeX ( papers , filename ) ;
1388+ } else if ( format === 'json' ) {
1389+ exportJSON ( papers , filename ) ;
1390+ }
1391+ }
1392+
1393+ function exportCSV ( papers , filename ) {
1394+ const headers = [ 'Title' , 'Authors' , 'Year' , 'Journal' , 'Citations' , 'DOI' , 'Abstract' , 'Stream' , 'Subtopic' ] ;
1395+ const rows = papers . map ( p => [
1396+ `"${ ( p . title || '' ) . replace ( / " / g, '""' ) } "` ,
1397+ `"${ ( p . authors || '' ) . replace ( / " / g, '""' ) } "` ,
1398+ p . year || '' ,
1399+ `"${ ( p . journal || '' ) . replace ( / " / g, '""' ) } "` ,
1400+ p . citations || 0 ,
1401+ p . doi || '' ,
1402+ `"${ ( p . abstract || '' ) . replace ( / " / g, '""' ) } "` ,
1403+ `"${ ( p . l1Label || '' ) . replace ( / " / g, '""' ) } "` ,
1404+ `"${ ( p . l3Label || '' ) . replace ( / " / g, '""' ) } "`
1405+ ] . join ( ',' ) ) ;
1406+
1407+ const csv = [ headers . join ( ',' ) , ...rows ] . join ( '\\n' ) ;
1408+ downloadFile ( csv , `${ filename } .csv` , 'text/csv' ) ;
1409+ }
1410+
1411+ function exportBibTeX ( papers , filename ) {
1412+ const bibtex = papers . map ( ( paper , idx ) => {
1413+ const key = `${ ( paper . authors || 'unknown' ) . split ( ',' ) [ 0 ] . toLowerCase ( ) . replace ( / [ ^ a - z ] / g, '' ) } ${ paper . year || '' } ${ paper . title . split ( ' ' ) [ 0 ] . toLowerCase ( ) } ` ;
1414+ return `@article{${ key } ,
1415+ title = {${ paper . title } },
1416+ author = {${ paper . authors || 'Unknown' } },
1417+ journal = {${ paper . journal } },
1418+ year = {${ paper . year } },
1419+ doi = {${ paper . doi || '' } },
1420+ note = {Citations: ${ paper . citations } }
1421+ }` ;
1422+ } ) . join ( '\\n\\n' ) ;
1423+
1424+ downloadFile ( bibtex , `${ filename } .bib` , 'text/plain' ) ;
1425+ }
1426+
1427+ function exportJSON ( papers , filename ) {
1428+ const json = JSON . stringify ( papers , null , 2 ) ;
1429+ downloadFile ( json , `${ filename } .json` , 'application/json' ) ;
1430+ }
1431+
1432+ function downloadFile ( content , filename , mimeType ) {
1433+ const blob = new Blob ( [ content ] , { type : mimeType } ) ;
1434+ const url = URL . createObjectURL ( blob ) ;
1435+ const a = document . createElement ( 'a' ) ;
1436+ a . href = url ;
1437+ a . download = filename ;
1438+ document . body . appendChild ( a ) ;
1439+ a . click ( ) ;
1440+ document . body . removeChild ( a ) ;
1441+ URL . revokeObjectURL ( url ) ;
1442+ }
13111443
13121444 // Initialize
13131445 document . addEventListener ( 'DOMContentLoaded' , function ( ) {
0 commit comments