Files
Levyraati26_go/templates/partials/player.html
T
Esa Kataja a9776c6dde Follow the song in the lyrics
Synced LRC highlights the playing line, keeps it centred and seeks on click.
Plain text scrolls continuously with a nudge knob instead — a highlight on
guessed timings turns guaranteed drift into what looks like a bug. Seuraa
kappaletta turns following off without losing the highlight, and scrolling by
hand turns it off too.

Fixes the scroll landing in the wrong place (offsetTop measured from a
different coordinate space than the box it was applied to) and the fader
shifting the deck sideways at score 100 (auto-sized grid columns plus a
readout spanning both).
2026-08-01 00:45:40 +03:00

66 lines
2.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{{/* Two shapes, because timed lyrics and guessed lyrics deserve different treatment.
Synced: one element per line with its own timestamp, highlighted as it comes.
Plain: one block that scrolls continuously, with a nudge knob, because a highlight on evenly
guessed timings turns guaranteed drift into what looks like a bug. */}}
{{define "lyricsview"}}
<span class="cap">Sanoitukset</span>
{{$lines := .LyricLines}}
{{if $lines}}
<div class="lyricsbox synced" data-song="{{.ID}}">
{{range $lines}}<p class="lline" data-t="{{.At}}">{{if .Text}}{{.Text}}{{else}}&nbsp;{{end}}</p>{{end}}
</div>
<label class="follow">
<input type="checkbox" checked> Seuraa kappaletta
<span class="muted small">— korostus jatkuu, sivu ei vieri</span>
</label>
{{else}}
<div class="lyricsbox plain" data-duration="{{.Duration}}" data-song="{{.ID}}">
<div class="lscroll">{{lyricstext .Lyrics}}</div>
</div>
<label class="nudge">
Ajoitus
<input type="range" min="-10" max="10" step="0.5" value="0" aria-label="Ajoituksen siirto sekunteina">
<output>0 s</output>
</label>
{{end}}
{{end}}
{{define "player"}}
<!-- Ships with native controls; player.js removes them and drives the same element. No JS means
the browser's own player, which is plain but complete. -->
<div class="playerwrap" data-duration="{{.Duration}}">
<audio controls preload="none" src="/audio/{{.ID}}" class="player"></audio>
</div>
{{end}}
{{define "songcard"}}
<a class="songcard{{if and (not .Own) (not .Reviewed)}} unreviewed{{end}}" href="/songs/{{.ID}}">
{{if .Average}}<span class="scorebadge">{{score .Average}}</span>
{{else if .ReviewCount}}<span class="scorebadge sealed" title="Pisteet paljastuvat kun arvostelet"></span>{{end}}
<span class="title">{{.Title}}</span>
<span class="artist">{{.Artist}}</span>
<span class="meta">
<span class="badge genre">{{.GenreLabel}}</span>
<span>{{.Length}}</span>
<span>{{.Submitter}}</span>
{{if .Own}}<span class="badge admin">oma</span>
{{else if .Reviewed}}<span class="badge reviewed">arvosteltu</span>
{{else}}<span class="badge pending">arvostelematta</span>{{end}}
{{if .ReviewCount}}<span>{{.ReviewCount}} arvostelua</span>{{end}}
</span>
</a>
{{end}}
{{define "fader"}}
<!-- A native range input turned vertical: keyboard, form submission and the value all stay free. -->
<div class="fader">
<span class="ticks" aria-hidden="true">
<span>100</span><span>75</span><span>50</span><span>25</span><span>1</span>
</span>
<input type="range" name="score" min="1" max="100" value="{{.}}"
aria-label="Pisteet 1100"
oninput="this.closest('.fader').querySelector('output').value = this.value">
<output class="readout">{{.}}</output>
</div>
{{end}}