144 lines
5.5 KiB
JavaScript
144 lines
5.5 KiB
JavaScript
// Nauka Czytania
|
|
;(function () {
|
|
// ms between line advances for each speed level (0 = manual)
|
|
const SPEEDS_MS = [0, 3500, 2000, 1000]
|
|
const SPEED_LABELS = ['Pauza', 'Wolno', 'Średnio', 'Szybko']
|
|
|
|
let yOffset = 0
|
|
let lineH = 80 // recalculated after render
|
|
let maxOffset = 0
|
|
let speedIdx = 0
|
|
let autoTimer = null
|
|
|
|
const listWrap = document.getElementById('list-wrap')
|
|
const readWrap = document.getElementById('read-wrap')
|
|
const textList = document.getElementById('text-list')
|
|
const customInput = document.getElementById('custom-input')
|
|
const customStartBtn = document.getElementById('custom-start-btn')
|
|
const readBackBtn = document.getElementById('read-back-btn')
|
|
const readTitleEl = document.getElementById('read-title')
|
|
const speedBtn = document.getElementById('speed-btn')
|
|
const readViewport = document.getElementById('read-viewport')
|
|
const readTextEl = document.getElementById('read-text')
|
|
const nextLineBtn = document.getElementById('next-line-btn')
|
|
let progressBar = null
|
|
|
|
// ── Load text list from dyktanda.json ────────────────────────────────────
|
|
fetch('json/dyktanda.json')
|
|
.then(r => r.json())
|
|
.then(data => {
|
|
data.forEach(item => {
|
|
const btn = document.createElement('button')
|
|
btn.className = 'list-item-btn'
|
|
btn.textContent = item.name
|
|
btn.addEventListener('click', () => startReading(item.name, item.text))
|
|
textList.appendChild(btn)
|
|
})
|
|
})
|
|
.catch(() => {
|
|
textList.innerHTML = '<p style="color:var(--muted);padding:8px 0">Nie udało się wczytać tekstów.</p>'
|
|
})
|
|
|
|
customStartBtn.addEventListener('click', () => {
|
|
const txt = customInput.value.trim()
|
|
if (!txt) return
|
|
startReading('Własny', txt)
|
|
})
|
|
|
|
// ── Start reading ─────────────────────────────────────────────────────────
|
|
function startReading(title, text) {
|
|
yOffset = 0
|
|
speedIdx = 0
|
|
clearInterval(autoTimer)
|
|
autoTimer = null
|
|
|
|
if (!readTitleEl || !readTextEl || !speedBtn || !readWrap || !listWrap) {
|
|
console.warn('czytanie: missing DOM elements', { readTitleEl, readTextEl, speedBtn, readWrap, listWrap })
|
|
}
|
|
|
|
if (readTitleEl) readTitleEl.textContent = title
|
|
if (readTextEl) readTextEl.textContent = text
|
|
if (readTextEl) readTextEl.style.transform = 'translateY(0)'
|
|
if (speedBtn) speedBtn.textContent = SPEED_LABELS[0]
|
|
if (!progressBar) progressBar = document.getElementById('read-progress-bar-inner')
|
|
if (progressBar) progressBar.style.width = '0%'
|
|
|
|
listWrap.classList.add('hidden')
|
|
readWrap.classList.remove('hidden')
|
|
|
|
// measure real line height after layout
|
|
requestAnimationFrame(() => {
|
|
requestAnimationFrame(() => {
|
|
const cs = getComputedStyle(readTextEl)
|
|
const lhVal = cs.lineHeight
|
|
lineH = (lhVal === 'normal')
|
|
? parseFloat(cs.fontSize) * 1.35
|
|
: parseFloat(lhVal)
|
|
|
|
maxOffset = Math.max(0, readTextEl.offsetHeight - lineH)
|
|
updateNextBtn()
|
|
updateProgressBar()
|
|
})
|
|
})
|
|
}
|
|
|
|
// ── Back to list ──────────────────────────────────────────────────────────
|
|
readBackBtn.addEventListener('click', () => {
|
|
const active = yOffset > 0 || autoTimer !== null
|
|
if (active && !confirm('Wrócić do listy tekstów?')) return
|
|
clearInterval(autoTimer)
|
|
autoTimer = null
|
|
readWrap.classList.add('hidden')
|
|
listWrap.classList.remove('hidden')
|
|
// Reset speed to manual on exit
|
|
speedIdx = 0;
|
|
})
|
|
|
|
// ── Speed selector ────────────────────────────────────────────────────────
|
|
speedBtn.addEventListener('click', () => {
|
|
clearInterval(autoTimer)
|
|
autoTimer = null
|
|
speedIdx = (speedIdx + 1) % SPEEDS_MS.length
|
|
speedBtn.textContent = SPEED_LABELS[speedIdx]
|
|
if (SPEEDS_MS[speedIdx] > 0 && yOffset < maxOffset) {
|
|
autoTimer = setInterval(advanceLine, SPEEDS_MS[speedIdx])
|
|
}
|
|
})
|
|
|
|
// ── Manual line advance ───────────────────────────────────────────────────
|
|
nextLineBtn.addEventListener('click', advanceLine)
|
|
|
|
// ── Core scroll logic ─────────────────────────────────────────────────────
|
|
function advanceLine() {
|
|
if (yOffset >= maxOffset) {
|
|
stopAutoAtEnd()
|
|
return
|
|
}
|
|
yOffset = Math.min(yOffset + lineH, maxOffset)
|
|
readTextEl.style.transform = `translateY(${-yOffset}px)`
|
|
updateNextBtn()
|
|
updateProgressBar()
|
|
if (yOffset >= maxOffset) stopAutoAtEnd()
|
|
}
|
|
|
|
function stopAutoAtEnd() {
|
|
if (autoTimer !== null) {
|
|
clearInterval(autoTimer)
|
|
autoTimer = null
|
|
speedIdx = 0
|
|
speedBtn.textContent = SPEED_LABELS[0]
|
|
}
|
|
updateNextBtn()
|
|
}
|
|
|
|
function updateNextBtn() {
|
|
nextLineBtn.disabled = yOffset >= maxOffset
|
|
}
|
|
|
|
function updateProgressBar() {
|
|
const progress = maxOffset > 0 ? (yOffset / maxOffset) * 100 : 100
|
|
if (!progressBar) progressBar = document.getElementById('read-progress-bar-inner')
|
|
if (progressBar) progressBar.style.width = `${progress}%`
|
|
}
|
|
})()
|