| 1 | <!DOCTYPE html>
|
|---|
| 2 | <html lang="nl">
|
|---|
| 3 | <head>
|
|---|
| 4 | <meta charset="utf-8">
|
|---|
| 5 | <meta name="viewport" content="width=device-width, initial-scale=1">
|
|---|
| 6 | <title><%= site.title %> — speler</title>
|
|---|
| 7 | <style>
|
|---|
| 8 | :root { --ac: <%= (site && site.accent) ? site.accent : '#6b8f71' %>; }
|
|---|
| 9 | * { box-sizing: border-box; }
|
|---|
| 10 | html, body { margin: 0; }
|
|---|
| 11 | body { font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; background: #14161a; color: #f2f3f5; }
|
|---|
| 12 | .ep { display: flex; flex-direction: column; height: 100vh; }
|
|---|
| 13 | .ep-now { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-bottom: 1px solid rgba(255,255,255,.08); }
|
|---|
| 14 | .ep-play { flex: 0 0 auto; width: 44px; height: 44px; border-radius: 50%; border: none; background: var(--ac); color: #fff; font-size: 18px; cursor: pointer; display: grid; place-items: center; }
|
|---|
| 15 | .ep-meta { flex: 1 1 auto; min-width: 0; }
|
|---|
| 16 | .ep-title { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|---|
| 17 | .ep-artist { font-size: 12px; opacity: .6; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|---|
| 18 | .ep-bar { height: 4px; background: rgba(255,255,255,.12); cursor: pointer; }
|
|---|
| 19 | .ep-fill { height: 100%; width: 0; background: var(--ac); }
|
|---|
| 20 | .ep-list { flex: 1 1 auto; overflow-y: auto; margin: 0; padding: 0; list-style: none; }
|
|---|
| 21 | .ep-item { display: flex; align-items: center; gap: 10px; padding: 10px 14px; cursor: pointer; border-bottom: 1px solid rgba(255,255,255,.05); }
|
|---|
| 22 | .ep-item:hover { background: rgba(255,255,255,.05); }
|
|---|
| 23 | .ep-item.on { color: var(--ac); }
|
|---|
| 24 | .ep-num { width: 20px; text-align: right; opacity: .5; font-size: 13px; font-variant-numeric: tabular-nums; }
|
|---|
| 25 | .ep-it-title { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 14px; }
|
|---|
| 26 | .ep-dur { opacity: .5; font-size: 12px; font-variant-numeric: tabular-nums; }
|
|---|
| 27 | .ep-foot { padding: 8px 14px; font-size: 11px; opacity: .5; text-align: center; border-top: 1px solid rgba(255,255,255,.08); }
|
|---|
| 28 | .ep-foot a { color: inherit; }
|
|---|
| 29 | .ep-empty { padding: 24px; text-align: center; opacity: .6; }
|
|---|
| 30 | /* Slim, themed scrollbar for the track list (instead of the chunky default). */
|
|---|
| 31 | .ep-list { scrollbar-width: thin; scrollbar-color: rgba(255,255,255,.28) transparent; }
|
|---|
| 32 | .ep-list::-webkit-scrollbar { width: 8px; }
|
|---|
| 33 | .ep-list::-webkit-scrollbar-track { background: transparent; }
|
|---|
| 34 | .ep-list::-webkit-scrollbar-thumb { background-color: rgba(255,255,255,.22); border-radius: 999px; border: 2px solid transparent; background-clip: content-box; }
|
|---|
| 35 | .ep-list::-webkit-scrollbar-thumb:hover { background-color: color-mix(in srgb, var(--ac) 70%, #fff); }
|
|---|
| 36 | </style>
|
|---|
| 37 | </head>
|
|---|
| 38 | <body>
|
|---|
| 39 | <div class="ep">
|
|---|
| 40 | <div class="ep-now">
|
|---|
| 41 | <button class="ep-play" id="ep-play" aria-label="Afspelen">▶</button>
|
|---|
| 42 | <div class="ep-meta">
|
|---|
| 43 | <div class="ep-title" id="ep-title"><%= site.title %></div>
|
|---|
| 44 | <div class="ep-artist" id="ep-artist">Selecteer een nummer</div>
|
|---|
| 45 | </div>
|
|---|
| 46 | </div>
|
|---|
| 47 | <div class="ep-bar" id="ep-bar"><div class="ep-fill" id="ep-fill"></div></div>
|
|---|
| 48 | <% if (!embedTracks.length) { %>
|
|---|
| 49 | <div class="ep-empty">Geen nummers beschikbaar.</div>
|
|---|
| 50 | <% } else { %>
|
|---|
| 51 | <ul class="ep-list" id="ep-list">
|
|---|
| 52 | <% embedTracks.forEach(function(t, i){ %>
|
|---|
| 53 | <li class="ep-item" data-i="<%= i %>">
|
|---|
| 54 | <span class="ep-num"><%= i+1 %></span>
|
|---|
| 55 | <span class="ep-it-title"><%= t.title %><% if (t.artist) { %> — <span style="opacity:.6"><%= t.artist %></span><% } %></span>
|
|---|
| 56 | <span class="ep-dur" data-dur="<%= t.duration || 0 %>"></span>
|
|---|
| 57 | </li>
|
|---|
| 58 | <% }); %>
|
|---|
| 59 | </ul>
|
|---|
| 60 | <% } %>
|
|---|
| 61 | <div class="ep-foot">via <a href="<%= siteUrlBase %>/" target="_blank" rel="noopener"><%= site.title %></a> · Klonkt</div>
|
|---|
| 62 | </div>
|
|---|
| 63 | <audio id="ep-audio" preload="none" playsinline></audio>
|
|---|
| 64 | <script>
|
|---|
| 65 | (function(){
|
|---|
| 66 | var TRACKS = <%- JSON.stringify(embedTracks) %>;
|
|---|
| 67 | var audio = document.getElementById('ep-audio');
|
|---|
| 68 | var playBtn = document.getElementById('ep-play');
|
|---|
| 69 | var titleEl = document.getElementById('ep-title');
|
|---|
| 70 | var artistEl = document.getElementById('ep-artist');
|
|---|
| 71 | var fill = document.getElementById('ep-fill');
|
|---|
| 72 | var bar = document.getElementById('ep-bar');
|
|---|
| 73 | var list = document.getElementById('ep-list');
|
|---|
| 74 | var cur = -1;
|
|---|
| 75 | function fmt(s){ s = parseInt(s,10)||0; var m=Math.floor(s/60), x=s%60; return m+':'+String(x).padStart(2,'0'); }
|
|---|
| 76 | // Vul de duur-labels.
|
|---|
| 77 | document.querySelectorAll('.ep-dur').forEach(function(el){ var d=parseInt(el.getAttribute('data-dur'),10)||0; if(d) el.textContent=fmt(d); });
|
|---|
| 78 | function mark(){ document.querySelectorAll('.ep-item').forEach(function(li){ li.classList.toggle('on', parseInt(li.getAttribute('data-i'),10)===cur); }); }
|
|---|
| 79 | function load(i, play){
|
|---|
| 80 | if(i<0||i>=TRACKS.length) return;
|
|---|
| 81 | cur=i; var t=TRACKS[i];
|
|---|
| 82 | titleEl.textContent=t.title||'Naamloos';
|
|---|
| 83 | artistEl.textContent=t.artist||'';
|
|---|
| 84 | audio.src=t.url;
|
|---|
| 85 | mark();
|
|---|
| 86 | if(play){ audio.play().catch(function(){}); }
|
|---|
| 87 | }
|
|---|
| 88 | playBtn.addEventListener('click', function(){
|
|---|
| 89 | if(cur<0){ load(0, true); return; }
|
|---|
| 90 | if(audio.paused) audio.play().catch(function(){}); else audio.pause();
|
|---|
| 91 | });
|
|---|
| 92 | if(list) list.addEventListener('click', function(e){
|
|---|
| 93 | var li=e.target.closest('.ep-item'); if(!li) return;
|
|---|
| 94 | load(parseInt(li.getAttribute('data-i'),10), true);
|
|---|
| 95 | });
|
|---|
| 96 | audio.addEventListener('play', function(){ playBtn.textContent='⏸'; });
|
|---|
| 97 | audio.addEventListener('pause', function(){ playBtn.textContent='▶'; });
|
|---|
| 98 | audio.addEventListener('timeupdate', function(){ if(audio.duration) fill.style.width=(audio.currentTime/audio.duration*100)+'%'; });
|
|---|
| 99 | audio.addEventListener('ended', function(){ if(cur+1<TRACKS.length) load(cur+1, true); else { playBtn.textContent='▶'; fill.style.width='0'; } });
|
|---|
| 100 | bar.addEventListener('click', function(e){ if(!audio.duration) return; var r=bar.getBoundingClientRect(); audio.currentTime=(e.clientX-r.left)/r.width*audio.duration; });
|
|---|
| 101 | })();
|
|---|
| 102 | </script>
|
|---|
| 103 | </body>
|
|---|
| 104 | </html>
|
|---|