Welcome — choose a page above to manage players or demand lists.
+Welcome
+Use the top navigation to view players or demand lists. This UI follows a compact table-first layout for quick browsing.
+diff --git a/app.js b/app.js index e7374f0..2ef653f 100644 --- a/app.js +++ b/app.js @@ -29,7 +29,7 @@ // Lists page if(page==='lists'){ const levelsEl = qs('levels'); const listArea = qs('list-area'); const titleEl = qs('list-title'); - // Load hard-coded data file data.txt (level|position|title|url per line) + // Load hard-coded data file data.txt (category|position|title|url per line) function loadData(){ fetch('data.txt').then(r=>r.text()).then(txt=>{ const lines = txt.split(/\r?\n/).map(l=>l.trim()).filter(Boolean); @@ -41,40 +41,96 @@ }).catch(err=>{listArea.innerHTML='
Failed to load data.txt — run via a local server.
'; console.error(err)}); } + function computeCategories(items){ + const max = items.reduce((m,it)=>Math.max(m, Number(it.position)||0), 0); + const cats = ['Full List']; + for(let i=1;i<=max;i+=10){ + const start = i; const end = Math.min(i+9, max); + cats.push(`Top ${start}-${end}`); + } + return cats; + } + function setupLevels(items){ - const levels = [...new Set(items.map(i=>i.level))]; - levelsEl.innerHTML=''; levels.forEach(l=>{ - const a=document.createElement('a'); a.href='#'; a.textContent=l; a.className='level-link'; a.onclick=(e)=>{e.preventDefault(); selectLevel(l,items,a)}; levelsEl.appendChild(a); + const categories = computeCategories(items); + levelsEl.innerHTML=''; + const filterSelect = qs('level-filter'); + filterSelect.innerHTML = ''; + categories.forEach(cat=>{ + const li = document.createElement('li'); + const btn = document.createElement('button'); + btn.type = 'button'; + btn.textContent = cat; + btn.className = 'level-link'; + btn.addEventListener('click', ()=> { + selectLevel(cat, items, btn); + filterSelect.value = cat; + }); + li.appendChild(btn); + levelsEl.appendChild(li); + + const opt = document.createElement('option'); opt.value = cat; opt.textContent = cat; filterSelect.appendChild(opt); }); - // default select first - if(levels.length) selectLevel(levels[0],items,levelsEl.querySelector('.level-link')); + // search and filter handlers + qs('search').addEventListener('input', ()=> renderTable(items)); + filterSelect.addEventListener('change', ()=> renderTable(items)); + // default select Full List + selectLevel('Full List', items, levelsEl.querySelector('.level-link')); } function selectLevel(level, items, linkEl){ - // mark active levelsEl.querySelectorAll('.level-link').forEach(a=>a.classList.remove('active')); if(linkEl) linkEl.classList.add('active'); - titleEl.textContent = level + ' Videos'; - const filtered = items.filter(it=>it.level===level).sort((a,b)=> (a.position||0)-(b.position||0)); - listArea.innerHTML = ''; - filtered.forEach(it=>{ - const card = document.createElement('div'); card.className='video-card'; - const h = document.createElement('h3'); h.textContent = `${it.position} — ${it.title}`; - card.appendChild(h); - const url = it.url; - if(/youtube\.com|youtu\.be/.test(url)){ - const id = extractYouTubeID(url); - const iframe = document.createElement('iframe'); iframe.src = `https://www.youtube.com/embed/${id}`; iframe.allow='accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture'; iframe.allowFullscreen = true; - card.appendChild(iframe); - } else if(url){ - const a = document.createElement('a'); a.href = url; a.textContent = url; a.target='_blank'; card.appendChild(a); - } else { - const p = document.createElement('p'); p.textContent = 'No URL'; card.appendChild(p); + qs('level-filter').value = level; + renderTable(items); + } + + function renderTable(items){ + const q = (qs('search') && qs('search').value || '').toLowerCase(); + const levelFilter = (qs('level-filter') && qs('level-filter').value) || 'all'; + const filtered = items.filter(it=>{ + // apply level / category filter (support range categories like "Top 1-10") + if(levelFilter && levelFilter!=='all' && levelFilter!=='Full List'){ + const m = levelFilter.match(/Top\s*(\d+)-(\d+)/i); + if(m){ + const s = Number(m[1]); const e = Number(m[2]); const pos = Number(it.position)||0; + if(pos < s || pos > e) return false; + } } - listArea.appendChild(card); + if(!q) return true; + return (it.title||'').toLowerCase().includes(q) || (it.level||'').toLowerCase().includes(q); + }).sort((a,b)=> (Number(a.position)||0)-(Number(b.position)||0)); + + const tbody = qs('list-area'); tbody.innerHTML=''; + filtered.forEach(it=>{ + const tr = document.createElement('tr'); + const tdNum = document.createElement('td'); tdNum.textContent = it.position; + const tdTitle = document.createElement('td'); tdTitle.textContent = it.title; + const tdAct = document.createElement('td'); + const a = document.createElement('a'); a.textContent='Open'; a.href='#'; a.className='btn'; + a.addEventListener('click', (e)=>{e.preventDefault(); openVideo(it.url)}); + tdAct.appendChild(a); + tr.appendChild(tdNum); tr.appendChild(tdTitle); tr.appendChild(tdAct); + tbody.appendChild(tr); }); } + function openVideo(url){ + if(!url) return; const id = extractYouTubeID(url); + if(!id){ window.open(url,'_blank'); return } + let modal = document.querySelector('.video-modal'); + if(!modal){ + modal = document.createElement('div'); modal.className='video-modal'; + const inner = document.createElement('div'); inner.className='inner'; + const close = document.createElement('button'); close.textContent='Close'; close.className='btn'; close.style.float='right'; close.onclick=()=>modal.remove(); + inner.appendChild(close); + const iframe = document.createElement('iframe'); iframe.allow='accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture'; iframe.allowFullscreen=true; + inner.appendChild(iframe); modal.appendChild(inner); document.body.appendChild(modal); + } + modal.querySelector('iframe').src = `https://www.youtube.com/embed/${id}`; + modal.style.display = 'flex'; + } + function extractYouTubeID(url){ const m = url.match(/(?:v=|\/embed\/|youtu\.be\/)([A-Za-z0-9_-]{6,})/); return m?m[1]:''; } diff --git a/data.txt b/data.txt index 4add1a7..e1ec169 100644 --- a/data.txt +++ b/data.txt @@ -1,7 +1,50 @@ -Easy|1|Beginner Tutorial|https://www.youtube.com/watch?v=dQw4w9WgXcQ -Easy|2|Simple Level Showcase|https://www.youtube.com/watch?v=V-_O7nl0Ii0 -Normal|1|Intermediate Run|https://www.youtube.com/watch?v=3JZ_D3ELwOQ -Hard|1|Hard Demon Playthrough|https://www.youtube.com/watch?v=fJ9rUzIMcZQ -Insane|1|Insane Demon Compilation|https://www.youtube.com/watch?v=L_jWHffIx5E -new|1|Insane Demon Compilation|https://www.youtube.com/watch?v=L_jWHffIx5E -cool|1|Insane Demon Compilation|https://www.youtube.com/watch?v=L_jWHffIx5E +new|1|Flamewall|https://youtu.be/x4Io4zkWVRw?si=tf0DBaWahOPPEWxO +new|2|Thinking Space II|https://youtu.be/CELNmHwln_c?si=soP6SzRn92G1vKbl +new|4|Amethyst|https://youtu.be/4lfkzz1VCbA?si=6NNeWiH-nnwu21Cb +new|3|Tidal Wave|https://youtu.be/9fsZ014qB3s?si=oj4E4ceyNtRVcDvd +new|5|Orbit|https://youtu.be/QKcv8DkNPd0?si=cKBFqp7GRqmfupgJ +new|6|BOOBAWAMBA|https://youtu.be/20fYiqLAo_E?si=QSSixz31rWeeQ_8B +new|7|Nullscapes|https://youtu.be/EztneTPp5CU?si=ljn-S_bnGYwOoUyV +new|8|Quantuese Processing|https://youtu.be/j5NC0u1Q91Q?si=FvUEY2kdDtNMqWSD +new|9|Subsuming Vortex|https://youtu.be/0eYG1ogJpIQ?si=7XRxfDsmMVb0G9Si +new|10|Andromeda|https://youtu.be/mk3TDemdkC0?si=va13_RKAJUyFvhcv +new|11|Every End|https://youtu.be/AO--mVVFtKI?si=gIT5vxyc1FZ4_8Jj +new|12|Silent Clubstep|https://youtu.be/GR4OMkS3SN8?si=CMNz8bPBaUU94wiy +new|13|Anathema|https://youtu.be/_uKwmjHmySI?si=PgXwX7Z--wCay34b +new|14|Acheron|https://youtu.be/sBKR6aUorzA?si=0A9S2_W8gi1awZ81 +new|15|Ashley Wave Trials|https://youtu.be/aTxt76U3e2Q?si=RVcEcOTOfs7NGWRi +new|16|Avernus|https://youtu.be/16Zh8jssanc?si=0o6d2dH4p_J7UjKB +new|17|Menace|https://youtu.be/nnkgghxxsEE?si=OuUQfD7WbXVooYyX +new|18|Spectre|https://youtu.be/MzsSLKJrLSI?si=-bXtr_jG96kTCzy4 +new|19|Abyss Of Darkness|https://youtu.be/ejJkpqcMMCY?si=Rpp4HEi1kOMh-p0h +new|20|Defeated Circles|https://youtu.be/nU5AQPzd2YA?si=6eKDMPh-2QjDBBOF +new|21|Tunnel Of Despair|https://youtu.be/LpS4JREhW98?si=Z6_DRV5YZTEA0TeQ +new|22|Subterminal Point|https://youtu.be/h2wmRMgACH4?si=nDD0-bmLqPgcdVJP +new|23|KOCMOC|https://youtu.be/2CxE-UWCIG4?si=9xz4hBjtNKe8Rcbs +new|24|Slaughterhouse|https://youtu.be/kpcF1-QAHQc?si=7ybF9EbcjqHzloLM +new|25|Kyouki|https://youtu.be/KDa5c0CJTHs?si=WU0sPusFLB7Jtkam +new|26|The Lightning Rod|https://youtu.be/nQDTi077O6M?si=Kqp2Od3lJx1YWTDB +new|27|Based After Based|https://youtu.be/yQBFyUvB3lY?si=Cmxbc5jrTrNlcmG5 +new|28|CHIL|https://youtu.be/DROMiCc2ZRM?si=_bR8CCnqJGVCex9F +new|29|Sakupen Circles|https://youtu.be/ofG2mJi9kEA?si=3yv78_jxidKPhtL5 +new|30|Deimos (ItsHybrid)|https://youtu.be/b2yHaIk5zio?si=AMIuVFR-EW4CK8_P +new|31|Eyes In The Water|https://youtu.be/yvLwiOy3KEA?si=1991xs25WTEoTbE0 +new|32|Voltage|https://youtu.be/wBRvBN9tmlc?si=GU2md9I7ZnUV7Rfr +new|33|Firework|https://youtu.be/QBe5x2o9v2w?si=dhPg9YcCRjwngxU9 +new|34|Silentlocked|https://youtu.be/O-IQeUdEGvI?si=KeSHH6kwZoSVGINT +new|35|poocubed|https://youtu.be/fzL31vai1ms?si=9Gwk7RDtbEFxOJ6t +new|36|KOSETSU|https://youtu.be/hZ8vFX8z_BU?si=P6fFal0yazJbje2O +new|37|Through The Gates|https://youtu.be/4yHA6jux5UI?si=nstk3A6FDN3QR-qm +new|38|Saul Goodman|https://youtu.be/hjs5PjUaw9k?si=qJpGrru21d50gO5R +new|39|The Salt Factory|https://youtu.be/lQ7M-Sgov24?si=nXYVL0XGy5NOJLXn +new|40|Snowbound|https://youtu.be/cjHwgbtAkXU?si=ghJbRJCkN-m0zu60 +new|41|CONVOLSION|https://youtu.be/qeRKuyU3eGI?si=UPaem0b3V8fX0L1r +new|42|The Apocalyptic Trilogy|https://youtu.be/RUBbpsTR5eU?si=mEsPtyMLrQgP5fWl +new|43|MINUSdry|https://youtu.be/YvA8ehhzz0Q?si=DT6DfrXOQ41swSIR +new|44|Sevvend Clubstep|https://youtu.be/TvA8EJTJFCc?si=Rm9HyExGYpeGn4qs +new|45|Edge Of Destiny|https://youtu.be/rUphe3H59yU?si=dZ8LgDyqif1ET_k1 +new|46|The Halucination|https://youtu.be/tYbXsNkO9HE?si=b8hmXS98BAjDlPzF +new|47|CONVULSION|https://youtu.be/qeRKuyU3eGI?si=qJN026t6RcGjU3iW +new|48|Solar Flare|https://youtu.be/eHQNgty8ypY?si=ZdUIODdeDYLAXeHI +new|49|LIMBO|https://youtu.be/kXYMbaMVOZg?si=fWm4ngeSxBhFZadA +new|50|The Catacombs|https://youtu.be/T9-75lfKVQg?si=zEH6vP1617n5666I \ No newline at end of file diff --git a/index.html b/index.html index 16bb632..0212b33 100644 --- a/index.html +++ b/index.html @@ -15,7 +15,17 @@Welcome — choose a page above to manage players or demand lists.
+Use the top navigation to view players or demand lists. This UI follows a compact table-first layout for quick browsing.
+