Skip to content

Latest commit

 

History

History
259 lines (215 loc) · 6 KB

File metadata and controls

259 lines (215 loc) · 6 KB
layout default
title PubMed Search Tool

PubMed Literature Search

Search Term:
<div class="input-group">
  <label for="api-key">API Key (optional):</label>
  <input type="password" id="api-key" placeholder="Leave blank to use default">
</div>

<button id="search-button">Search PubMed</button>

Search Results

<script> // Default configuration const DEFAULT_API_KEY = '3834945c08440921ade60d29a8bdd9553808'; const BATCH_SIZE = 50; const BASE_URL = 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/'; // Main search function async function searchPubMed() { const searchTerm = document.getElementById('search-term').value.trim(); let apiKey = document.getElementById('api-key').value.trim(); if (!apiKey) { apiKey = DEFAULT_API_KEY; console.log("Using default API key"); } if (!searchTerm) { alert("Please enter a search term"); return; } // Show loading state const resultsContainer = document.getElementById('results-container'); const progressBar = document.getElementById('progress-bar'); const resultsTable = document.getElementById('results-table'); resultsContainer.style.display = 'block'; progressBar.innerHTML = '

Searching PubMed...

'; resultsTable.innerHTML = ''; try { // Step 1: Search for PMIDs progressBar.innerHTML = '

Finding articles...

'; const pmids = await searchPMIDs(apiKey, searchTerm); if (pmids.length === 0) { progressBar.innerHTML = '

No articles found for this search term.

'; return; } // Step 2: Fetch metadata progressBar.innerHTML = `

Fetching details for ${pmids.length} articles...

`; const metadata = await fetchMetadata(apiKey, pmids); // Step 3: Display results displayResults(metadata); progressBar.innerHTML = `

Found ${Object.keys(metadata).length} articles

`; } catch (error) { progressBar.innerHTML = `

Error: ${error.message}

`; console.error(error); } } // API functions async function searchPMIDs(apiKey, searchTerm) { const params = new URLSearchParams({ db: 'pubmed', term: searchTerm, retmax: 100000, retmode: 'json', api_key: apiKey }); const response = await fetch(`${BASE_URL}esearch.fcgi?${params}`); const data = await response.json(); return data.esearchresult.idlist || []; } async function fetchMetadata(apiKey, pmids) { const allData = {}; for (let i = 0; i < pmids.length; i += BATCH_SIZE) { const batch = pmids.slice(i, i + BATCH_SIZE); const ids = batch.join(','); const params = new URLSearchParams({ db: 'pubmed', id: ids, retmode: 'json', api_key: apiKey }); const response = await fetch(`${BASE_URL}esummary.fcgi?${params}`); const data = await response.json(); for (const pid of batch) { if (data.result[pid]) { allData[pid] = data.result[pid]; } } // Update progress const progress = Math.min(i + BATCH_SIZE, pmids.length); document.getElementById('progress-bar').innerHTML = `

Processed ${progress}/${pmids.length} records...

`; // Rate limiting await new Promise(resolve => setTimeout(resolve, 400)); } return allData; } // Display results in HTML table function displayResults(metadata) { const resultsTable = document.getElementById('results-table'); let html = ` `; Object.entries(metadata).forEach(([pmid, meta]) => { // Format authors let authors = []; try { const authorsList = typeof meta.authors === 'string' ? JSON.parse(meta.authors) : meta.authors || []; authors = authorsList .filter(a => a.authtype === 'Author') .map(a => a.name) .slice(0, 3); } catch (e) { console.error("Error parsing authors", e); } // Format year let year = ''; if (meta.pubdate) { const yearMatch = meta.pubdate.match(/\d{4}/); year = yearMatch ? yearMatch[0] : ''; } html += ` `; }); html += `
PMID Title Authors Year Journal
${pmid} ${meta.title || ''} ${authors.join(', ')}${authors.length > 3 ? '...' : ''} ${year} ${meta.source || ''}
`; resultsTable.innerHTML = html; } // Event listener document.getElementById('search-button').addEventListener('click', searchPubMed); </script> <style> #pubmed-search-app { max-width: 1000px; margin: 0 auto; padding: 20px; font-family: Arial, sans-serif; } .input-section { background: #f5f5f5; padding: 20px; border-radius: 5px; margin-bottom: 20px; } .input-group { margin-bottom: 15px; } .input-group label { display: block; margin-bottom: 5px; font-weight: bold; } .input-group input { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; } #search-button { background: #2c82c9; color: white; border: none; padding: 10px 15px; border-radius: 4px; cursor: pointer; font-size: 16px; } #search-button:hover { background: #1a6cb3; } .table-responsive { overflow-x: auto; } table { width: 100%; border-collapse: collapse; } th, td { padding: 8px 12px; border: 1px solid #ddd; text-align: left; } th { background: #f0f0f0; } .error { color: #d9534f; } </style>