"use strict"; const main = document.querySelector('#main'); const menu = document.querySelector('#menu'); const byId = new Map(SIGNS.map(s => [s.id, s])); const byCode = new Map(SIGNS.map(s => [s.code, s])); const groupById = new Map(GROUPS.map(g => [g.id, g])); const esc = text => String(text).replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); const groupSigns = id => SIGNS.filter(s => s.group === id); let currentSign = null; let activeUtterance = null; const synth = 'speechSynthesis' in window ? window.speechSynthesis : null; const imageFor = (code, decorative = false) => `${decorative ? '' : esc(byCode.get(code)?.title || code)}`; const crumbs = (group, title) => ``; menu.innerHTML = GROUPS.map(g => `${imageFor(g.samples[0], true)}${esc(g.short)}`).join(''); function showHome() { document.title = 'KRESZ Táblatanoda – Jelzőtábla csoportok'; main.innerHTML = `

Fedezd fel a közlekedési táblákat!

Melyik tábla mit jelent?

Válassz egy csoportot, nézd meg a táblákat, és hallgasd meg a magyarázatukat!

7 csoport · ${SIGNS.length} tábla
${GROUPS.map((g, i) => `
${g.samples.map(code => imageFor(code, true)).join('')}

${esc(g.name)}

${esc(g.description)}

${groupSigns(g.id).length} tábla felfedezésre vár
`).join('')}

Tanulj hallgatva is! Nyiss meg egy táblát, majd nyomd meg a Felolvasás gombot.

`; } function showGroup(group) { const signs = groupSigns(group.id); document.title = `${group.name} – Táblatanoda`; main.innerHTML = `${crumbs(group)}

${signs.length} megismerhető tábla

${esc(group.name)}

${esc(group.intro)}

${signs.map(s => `${imageFor(s.code, true)}${esc(s.title)}`).join('')}
`; } function showSign(sign) { currentSign = sign; const group = groupById.get(sign.group); const signs = groupSigns(group.id); const index = signs.findIndex(s => s.id === sign.id); document.title = `${sign.title} – Táblatanoda`; main.innerHTML = `${crumbs(group, sign.title)}
${imageFor(sign.code)}Figyeld meg a formát és a színeket!

${esc(group.short)}

${esc(sign.title)}

${esc(sign.meaning)}

Jegyezd meg!

${esc(sign.tip)}

Vissza a csoport összes táblájához`; document.querySelector('#speak').addEventListener('click', toggleSpeech); refreshVoiceStatus(); } function showSources() { document.title = 'Források és tudnivalók – Táblatanoda'; main.innerHTML = `

Háttér a tanuláshoz

Források és tudnivalók

A magyar KRESZ alapján

A csoportosítás és a magyarázatok alapja az 1/1975. (II. 5.) KPM–BM együttes rendelet, különösen a 10–17. § és a 2. számú függelék.

A KRESZ hat alapvető jelzőtábla-csoportot nevez meg. A kiegészítő táblák külön menüpontot kaptak. A megállási és várakozási tilalmak a tilalmi és korlátozó táblák között szerepelnek.

Az oldal ${SIGNS.length} táblát és táblaváltozatot mutat be. Ez tanulást segítő válogatás, nem az összes létező felirat-, méret- és táblaváltozat teljes jegyzéke. A magyarázatok rövidítettek; a részletes szabályok és kivételek a jogszabályban olvashatók.

Ellenőrzés: 2026. szeptember 8. A forrásoldalon jelzett hatályállapot: 2026. április 11-től.

A táblák képei

A színes magyar táblarajzok a Wikimedia Commons magyar KRESZ-tábla gyűjteményéből származnak. Az egyes képek forrásoldala minden táblánál elérhető. A hivatalos jelzések rajzai a gyűjteményben jellemzően PD-HU-exempt közkinccsé minősítéssel szerepelnek.

A képek külső hivatkozással töltődnek be, ezért a megjelenítésükhöz internetkapcsolat szükséges.

A Magyar Közút jelzéskép-gyűjteménye további hivatalos rajzi segédlet. Az ott 2026-ban közzétett új KRESZ-tervezet rajzait a forrás nem hatályosként jelöli; az oldal magyarázatai a fent hivatkozott hatályos rendeleten alapulnak.

Magyar felolvasás

A Felolvasás gomb a böngésző beszédfunkcióját használja. Ugyanazzal a gombbal le is állíthatod. Másik táblára vagy a főoldalra lépve a felolvasás leáll.

A magyar hang elérhetősége a böngészőtől és a készülékre telepített hangoktól függ. Ha nincs magyar hang, ezt az oldal jelzi. A készülék nyelvi vagy beszédbeállításaiban lehet magyar hangot telepíteni. Egyes hangokhoz internet szükséges.

A weblap fájljai

A lap külön hivatkozott stíluslapot és szkriptfájlokat használ: styles.css, assets.js, data.js és app.js. A ZIP kicsomagolása után az index.html fájl böngészőben megnyitható.

↓ A teljes weblap letöltése ZIP-ben
`; } function stopSpeech() { activeUtterance = null; if (synth) synth.cancel(); const button = document.querySelector('#speak'); if (button) { button.innerHTML = ' Felolvasás'; button.setAttribute('aria-pressed','false'); } } function getHungarianVoice() { return synth?.getVoices().find(v => /^hu(?:[-_]|$)/i.test(v.lang)); } function refreshVoiceStatus() { const status = document.querySelector('#voice-status'); const button = document.querySelector('#speak'); if (!status || !button || activeUtterance) return; if (!synth || !('SpeechSynthesisUtterance' in window)) { button.disabled = true; status.textContent = 'Ez a böngésző nem támogatja a felolvasást.'; return; } const voices = synth.getVoices(); if (voices.length && !getHungarianVoice()) { button.disabled = true; status.textContent = 'Nincs elérhető magyar hang. Telepíts magyar beszédhangot a készülék nyelvi beállításaiban.'; } else { button.disabled = false; status.textContent = getHungarianVoice() ? 'Magyar nyelvű felolvasás' : 'A magyar hangot a böngésző választja ki.'; } } function toggleSpeech() { if (!synth || !currentSign) return; if (activeUtterance) { stopSpeech(); refreshVoiceStatus(); return; } synth.cancel(); const utterance = new SpeechSynthesisUtterance(`${currentSign.title}. ${currentSign.meaning} Jegyezd meg! ${currentSign.tip}`); utterance.lang = 'hu-HU'; utterance.rate = .88; utterance.pitch = 1; const voice = getHungarianVoice(); if (voice) utterance.voice = voice; activeUtterance = utterance; const button = document.querySelector('#speak'); const status = document.querySelector('#voice-status'); button.innerHTML = ' Leállítás'; button.setAttribute('aria-pressed','true'); status.textContent = 'A felolvasás indul…'; utterance.onstart = () => { if (activeUtterance === utterance) status.textContent = 'Felolvasás folyamatban…'; }; utterance.onend = () => { if (activeUtterance === utterance) { stopSpeech(); status.textContent = 'A felolvasás véget ért.'; } }; utterance.onerror = event => { if (activeUtterance !== utterance) return; stopSpeech(); status.textContent = event.error === 'language-unavailable' || event.error === 'voice-unavailable' ? 'A magyar beszédhang nem elérhető ezen a készüléken.' : 'A felolvasás nem indult el. Ellenőrizd a hangbeállításokat, majd próbáld újra.'; }; try { synth.speak(utterance); } catch { stopSpeech(); status.textContent = 'A böngésző nem tudta elindítani a felolvasást.'; } } function route(focus = true) { stopSpeech(); currentSign = null; const [page, id] = location.hash.slice(1).split('/'); let selectedGroup = null; if (!page || page === 'main') showHome(); else if (page === 'csoport' && groupById.has(id)) { selectedGroup = id; showGroup(groupById.get(id)); } else if (page === 'tabla' && byId.has(id)) { selectedGroup = byId.get(id).group; showSign(byId.get(id)); } else if (page === 'forrasok') showSources(); else { document.title = 'Nem található – Táblatanoda'; main.innerHTML = '

Ez az oldal nem található.

Válassz egy táblacsoportot a menüből, vagy lépj vissza a főoldalra.

'; } document.querySelectorAll('.menu-link').forEach(link => { const active = link.dataset.group === selectedGroup; link.classList.toggle('active', active); if (active) link.setAttribute('aria-current','true'); else link.removeAttribute('aria-current'); }); const home = document.querySelector('.home-link'); home.classList.toggle('active', !page); if (!page) home.setAttribute('aria-current','page'); else home.removeAttribute('aria-current'); // Failed remote images leave the exact sign name visible and offer its source. main.querySelectorAll('img').forEach(img => img.addEventListener('error', () => { if (img.closest('.detail-art')) { const note = document.createElement('p'); note.className = 'img-error'; note.textContent = 'A táblakép nem tölthető be. Ellenőrizd az internetkapcsolatot; a kép forrása lent megnyitható.'; img.replaceWith(note); } else { img.alt = 'A kép nem tölthető be'; } }, {once:true})); if (focus) { main.focus({preventScroll:true}); window.scrollTo({top:0,behavior:'instant'}); } } window.addEventListener('hashchange', () => route()); window.addEventListener('pagehide', stopSpeech); if (synth) synth.addEventListener('voiceschanged', refreshVoiceStatus); route(false);