Przyciski miesięcy, weekendy i klikanie w dni
Praktyka: kalendarz - JavaScript od podstaw: konsola (HTML/CSS/JS)
Kalendarz ożywa. Przyciski `#prev` i `#next` zmieniają miesiąc (przejście przez grudzień zwiększa rok), a funkcja `show` usuwa starą tabelę `replaceChildren()` i podpina nową. Komórki sobót i niedziel dostają klasę `weekend` (`classList.add`), a styl CSS koloruje je bez dotykania skryptu. Klikanie obsługuje JEDEN nasłuchiwacz na rodzicu (`#calendar`): zdarzenie z komórki "wypływa" do rodzica, a `e.target.closest('td')` mówi, którą komórkę kliknięto. To delegowanie zdarzeń: działa także dla tabel zbudowanych później.
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="utf-8">
<title>Kalendarz: miesiące i zdarzenia</title>
<style>
table { border-collapse: collapse; font-family: sans-serif; }
th, td { border: 1px solid #94a3b8; width: 2.5em; height: 2em; text-align: center; }
th { background: #e0e7ff; color: #1e1b4b; }
td.weekend { background: #fee2e2; color: #991b1b; }
td:hover { outline: 2px solid #6366f1; cursor: pointer; }
</style>
</head>
<body>
<button id="prev"><</button>
<strong id="title"></strong>
<button id="next">></button>
<div id="calendar"></div>
<p id="selected">Kliknij dzień.</p>
<script>
const MONTHS = ['styczeń', 'luty', 'marzec', 'kwiecień', 'maj', 'czerwiec',
'lipiec', 'sierpień', 'wrzesień', 'październik', 'listopad', 'grudzień'];
const DAYS = ['Pn', 'Wt', 'Śr', 'Cz', 'Pt', 'So', 'Nd'];
function buildWeeks(year, month) {
const first = (new Date(year, month - 1, 1).getDay() + 6) % 7;
const days = new Date(year, month, 0).getDate();
const cells = [];
for (let i = 0; i < first; i++) cells.push(null);
for (let d = 1; d <= days; d++) cells.push(d);
while (cells.length % 7 !== 0) cells.push(null);
const weeks = [];
for (let i = 0; i < cells.length; i += 7) {
weeks.push(cells.slice(i, i + 7));
}
return weeks;
}
let year = 2026;
let month = 11;
function renderTable(year, month) {
const table = document.createElement('table');
const head = document.createElement('tr');
for (const name of DAYS) {
const th = document.createElement('th');
th.textContent = name;
head.appendChild(th);
}
table.appendChild(head);
for (const week of buildWeeks(year, month)) {
const tr = document.createElement('tr');
week.forEach((day, i) => {
const td = document.createElement('td');
td.textContent = day === null ? '' : day;
if (i >= 5) td.classList.add('weekend');
tr.appendChild(td);
});
table.appendChild(tr);
}
return table;
}
function show() {
document.getElementById('title').textContent = `${MONTHS[month - 1]} ${year}`;
document.getElementById('calendar').replaceChildren(renderTable(year, month));
}
document.getElementById('prev').addEventListener('click', () => {
month--;
if (month === 0) {
month = 12;
year--;
}
show();
});
document.getElementById('next').addEventListener('click', () => {
month++;
if (month === 13) {
month = 1;
year++;
}
show();
});
document.getElementById('calendar').addEventListener('click', e => {
const td = e.target.closest('td');
if (!td || td.textContent === '') return;
document.getElementById('selected').textContent =
`Wybrano: ${td.textContent} ${MONTHS[month - 1]} ${year}`;
});
show();
</script>
</body>
</html>Ładowanie interaktywnego edytora... Jeśli się nie pojawi, włącz JavaScript.
Wszystkie lekcje kursu JavaScript od podstaw: konsola·Zaloguj się, aby zapisać postęp na koncie.