function setActiveFilterButton(type) { filterBtns.forEach(btn => { const btnType = btn.getAttribute("data-type"); if (btnType === type) { btn.classList.add("active"); } else { btn.classList.remove("active"); } }); }
// simple XSS escape function escapeHtml(str) { return str.replace(/[&<>]/g, function(m) { if (m === '&') return '&'; if (m === '<') return '<'; if (m === '>') return '>'; return m; }).replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, function(c) { return c; }); }
/* loading + error */ .loading-state, .error-state, .no-results { text-align: center; padding: 3rem; font-size: 1.2rem; background: rgba(0,0,0,0.3); border-radius: 2rem; margin-top: 1rem; } .error-state { color: #ffae70; } footer { text-align: center; margin-top: 2.5rem; font-size: 0.75rem; color: #6f8f92; border-top: 1px solid #ffcf7a30; padding-top: 1.5rem; } @media (max-width: 680px) { .archive-feature { padding: 1.2rem; } .title-area h1 { font-size: 1.8rem; } } </style> </head> <body> <div class="archive-feature"> <div class="jeannie-header"> <div class="title-area"> <h1>I Dream of Jeannie · Archive</h1> <div class="sub">classic episodes · promos · nostalgic media from the Internet Archive</div> </div> <div class="archive-badge"> 📀 powered by <a href="https://archive.org" target="_blank" rel="noopener">archive.org</a> metadata </div> </div> i dream of jeannie archive.org
function filterItems() { let filtered = [...masterItems]; // apply type filter if (currentFilter !== "all") { filtered = filtered.filter(item => item.type === currentFilter); } // apply search text if (currentSearch.trim() !== "") { const searchLower = currentSearch.trim().toLowerCase(); filtered = filtered.filter(item => item.searchText.includes(searchLower)); } return filtered; }
// state let currentFilter = "all"; let currentSearch = ""; function setActiveFilterButton(type) { filterBtns
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> <title>I Dream of Jeannie · Archive Explorer</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; }
function renderCards() { const filtered = filterItems(); resultCountSpan.innerText = `✨ ${filtered.length} magical item${filtered.length !== 1 ? 's' : ''} found from archive.org`; { const btnType = btn.getAttribute("data-type")
/* header with genie flair */ .jeannie-header { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-end; gap: 1rem; margin-bottom: 2rem; border-bottom: 2px solid #ffcf7a; padding-bottom: 1.2rem; } .title-area h1 { font-size: 2.7rem; font-weight: 700; background: linear-gradient(135deg, #FFE6B0, #FFB347); background-clip: text; -webkit-background-clip: text; color: transparent; letter-spacing: -0.5px; display: inline-flex; align-items: center; gap: 12px; } .title-area h1::before { content: "🧞♀️"; font-size: 2.5rem; background: none; color: #f7c56e; } .sub { color: #cbd5e1; margin-top: 0.4rem; font-size: 1rem; border-left: 3px solid #f3b33d; padding-left: 0.8rem; } .archive-badge { background: #2c3e2f; padding: 0.5rem 1.2rem; border-radius: 60px; font-weight: 500; font-size: 0.85rem; backdrop-filter: blur(4px); background: rgba(0,0,0,0.5); border: 1px solid #ffcf7a60; } .archive-badge a { color: #ffdd99; text-decoration: none; font-weight: 500; } .archive-badge a:hover { text-decoration: underline; }
/* search & filter row */ .search-panel { background: rgba(0, 0, 0, 0.45); border-radius: 2rem; padding: 1.2rem 1.5rem; margin-bottom: 2rem; display: flex; flex-wrap: wrap; gap: 1rem; align-items: center; justify-content: space-between; backdrop-filter: blur(8px); } .search-wrapper { flex: 3; min-width: 200px; position: relative; } .search-wrapper input { width: 100%; padding: 0.85rem 1.2rem; border-radius: 60px; border: none; background: #1e2b2f; color: #f0ede8; font-size: 1rem; outline: none; transition: 0.2s; border: 1px solid #ffcf7a40; } .search-wrapper input:focus { border-color: #f3b33d; box-shadow: 0 0 0 3px rgba(243,179,61,0.3); } .filter-group { display: flex; gap: 0.7rem; flex-wrap: wrap; } .filter-btn { background: #2d3e3f; border: none; padding: 0.6rem 1.2rem; border-radius: 40px; font-weight: 500; color: #e2e8f0; cursor: pointer; transition: all 0.2s; font-size: 0.85rem; } .filter-btn.active { background: #f3b33d; color: #1e2a2e; box-shadow: 0 2px 8px rgba(243,179,61,0.4); } .filter-btn:hover:not(.active) { background: #4a6b6e; }