Laboratorium HTML+JS – Rozwiązania zadań praktycznych
Poniżej znajdują się kompletne rozwiązania wszystkich 10 zadań z laboratorium HTML+JS.
Każde rozwiązanie zostało przetestowane i powinno działać poprawnie w nowoczesnych przeglądarkach.
Wszystkie zadania wykorzystują JavaScript w standardzie ES6+ oraz CSS3.
Zadanie 1: Interaktywny formularz kontaktowy
Rozwiązanie:
Formularz kontaktowy z wielopoziomową walidacją danych i komunikatami błędów wyświetlanymi dynamicznie pod każdym polem.
Opis działania:
- Struktura dokumentu HTML wykorzystuje semantyczne elementy
<form>, <input>, <label> zapewniające dostępność dla czytników ekranu
- Walidacja HTML5 realizowana jest przez atrybuty:
required (pole obowiązkowe), minlength (minimalna długość), type="email" (format adresu), pattern (wyrażenie regularne dla telefonu)
- Dodatkowa walidacja JavaScript wykonywana jest na zdarzenie
blur (utrata fokusu) sprawdzająca dane po opuszczeniu pola
- Pole
name wymaga minimum 2 znaków weryfikowanych przez value.length >= 2
- Walidacja email wykorzystuje wyrażenie regularne
/^[^\s@]+@[^\s@]+\.[^\s@]+$/ sprawdzające format nazwa@domena.rozszerzenie
- Walidacja telefonu używa wzorca
pattern="[0-9]{9}" wymagającego dokładnie 9 cyfr
- Pole wiadomości
minlength="10" wymaga co najmniej 10 znaków treści
- Komunikaty błędów wyświetlane są dynamicznie przez elementy
<span class="error"> umieszczane pod każdym polem
- Obsługa wysłania formularza przez zdarzenie
submit z event.preventDefault() zapobiegającym przeładowaniu strony
- Symulacja wysłania danych realizowana jest przez funkcję asynchroniczną z
setTimeout imitującym opóźnienie sieci
- Po poprawnej walidacji wyświetlany jest komunikat sukcesu bez przeładowania strony
- Style CSS zapewniają czytelność formularza z wyraźnymi etykietami i komunikatami błędów w kolorze czerwonym
- Responsywny układ dostosowuje formularz do urządzeń mobilnych
Plik rozwiązania:
Otwórz 06_html_z01.html
Testowanie:
- Wypełnij wszystkie pola prawidłowymi danymi i sprawdź komunikat sukcesu
- Zostaw puste pole i kliknij wyślij - zobaczysz komunikat "Pole wymagane"
- Wpisz nieprawidłowy email bez @ - zobaczysz błąd walidacji
- Wpisz zbyt krótką wiadomość (poniżej 10 znaków) - zobaczysz błąd walidacji
Zadanie 2: Dynamiczna galeria obrazów
Rozwiązanie:
Galeria obrazów z dynamicznym generowaniem miniaturek, filtrowaniem kategorii i funkcją lightbox.
Opis działania:
- Dane obrazów przechowywane są w tablicy obiektów
const images = [{id, src, thumbnail, category, title}, ...]
- Generowanie galerii realizowane jest przez metodę
map() na tablicy images tworzącą elementy DOM dynamicznie
- Każdy obraz otrzymuje atrybut
data-category umożliwiający późniejsze filtrowanie
- Przyciski filtrów (
.filter-btn) nasłuchują zdarzenia click i filtrują widoczne elementy
- Filtrowanie wykorzystuje metodę
querySelectorAll('.gallery-item') i warunkowe style.display
- Usługa obrazów testowych
picsum.photos dostarcza losowe fotografie dla każdego zadania
- Lightbox implementowany jest przez ukryty element
.lightbox wyświetlany po kliknięciu w miniaturę
- Zamknięcie lightbox realizowane jest przez trzy metody: przycisk X, klawisz Escape, kliknięcie poza obrazkiem
- Nasłuchiwanie na klawiaturę wykorzystuje zdarzenie
keydown z sprawdzeniem e.key === 'Escape'
- Zamknięcie kliknięciem poza obrazkiem sprawdza
e.target === lightbox
- Animacja lightbox wykorzystuje CSS
opacity i transform dla płynnego wejścia
- Style CSS zapewniają responsywny układ galerii z siatką miniaturek dostosowującą się do szerokości ekranu
- Kategorie: przyroda, krajobrazy, portrety - każda z własnymi obrazami
Plik rozwiązania:
Otwórz 06_html_z02.html
Testowanie:
- Kliknij w miniaturkę - otworzy się lightbox z pełnowymiarowym obrazem
- Naciśnij Escape aby zamknąć lightbox
- Kliknij poza obrazkiem aby zamknąć lightbox
- Kliknij przyciski kategorii aby filtrować galerię
- Zobacz jak zmienia się liczba wyświetlanych miniaturek
Zadanie 3: Todo list z localStorage
Rozwiązanie:
Aplikacja do zarządzania zadaniami z trwałym zapisem w localStorage i filtrowaniem.
Opis działania:
- Dane zadań przechowywane są w localStorage pod kluczem
'zadania' w formacie JSON
- Początkowe wczytanie realizowane jest przez
JSON.parse(localStorage.getItem('zadania')) z wartością domyślną pustej tablicy
- Dodawanie zadań wykorzystuje formularz z nasłuchem
submit i event.preventDefault()
- Każde zadanie ma unikalny identyfikator generowany przez
Date.now()
- Struktura obiektu zadania:
{id, tekst, ukonczone}
- Oznaczanie jako ukończone realizowane jest przez checkbox ze zdarzeniem
change i aktualizacją stanu
- Stylizacja ukończonych zadań wykorzystuje klasę CSS z
text-decoration: line-through
- Usuwanie zadań wykonuje funkcja
deleteZadanie(id) filtrująca tablicę i zapisując do localStorage
- Licznik zadań do zrobienia obliczany jest przez
zadania.filter(z => !z.ukonczone).length
- Filtrowanie realizowane jest przez przyciski: wszystkie, ukończone, do ukończenia
- Stan aktywnego filtra przechowywany jest w zmiennej
aktualnyFiltr
- Funkcja
renderujZadania() generuje HTML na podstawie stanu i filtra
- Zapis do localStorage wykonywany jest po każdej operacji przez
localStorage.setItem('zadania', JSON.stringify(zadania))
Plik rozwiązania:
Otwórz 06_html_z03.html
Testowanie:
- Dodaj nowe zadanie wpisując tekst i klikając przycisk
- Zaznacz checkbox przy zadaniu aby oznaczyć jako ukończone
- Usuń zadanie klikając przycisk X
- Odśwież stronę - zadania powinny zostać zachowane
- Kliknij filtry aby zobaczyć różne widoki
- Sprawdź licznik "Do zrobienia"
Zadanie 4: Kalkulator BMI z wykresem
Rozwiązanie:
Kalkulator obliczający wskaźnik masy ciała z wizualną interpretacją wyniku na pasku gradientowym.
Opis działania:
- Pobieranie danych wejściowych realizowane jest przez
document.getElementById('weight').value i height
- Wzór na BMI:
bmi = waga / (wzrost/100)^2 gdzie wzrost jest w centymetrach
- Obliczenia wykonywane są z użyciem
parseFloat() dla obsługi liczb zmiennoprzecinkowych
- Wynik zaokrąglany jest do 1 miejsca po przecinku przez
.toFixed(1)
- Interpretacja wyników zgodna z klasyfikacją WHO:
- niedowaga: BMI < 18.5
- prawidłowa waga: 18.5 ≤ BMI ≤ 24.9
- nadwaga: 25 ≤ BMI ≤ 29.9
- otyłość: BMI ≥ 30
- Kolory dla kategorii: niedowaga (#17a2b8 - niebieski), prawidłowa (#28a745 - zielony), nadwaga (#fd7e14 - pomarańczowy), otyłość (#dc3545 - czerwony)
- Pasek gradientowy wykorzystuje CSS
background: linear-gradient() z wieloma kolorami
- Wskaźnik pozycjonowany jest przez
left: X% gdzie X obliczane jest proporcjonalnie do BMI
- Walidacja danych sprawdza czy waga i wzrost są większe od 0
- Wyświetlanie wyniku dynamicznie aktualizuje zawartość elementów HTML
- Stylizacja wizualna zapewnia czytelność z wyraźnymi etykietami i kolorami
Plik rozwiązania:
Otwórz 06_html_z04.html
Testowanie:
- Wpisz wagę 70 i wzrost 175 - sprawdź wynik BMI
- Zmień wartości aby uzyskać wynik w każdej kategorii
- Zobacz jak wskaźnik przesuwa się na pasku
- Sprawdź nieprawidłowe dane (np. ujemne wartości)
- Zwróć uwagę na kolory dla różnych kategorii
Zadanie 5: Modal logowania z animacją
Rozwiązanie:
Okno modalne logowania z animacją wejścia/wyjścia i symulacją uwierzytelniania.
Opis działania:
- Struktura modala składa się z nakładki
.modal-overlay i kontenera .modal-content
- Początkowy stan ukrycia realizowany jest przez CSS
opacity: 0; pointer-events: none
- Otwarcie modala wykonywane jest przez przycisk "Zaloguj" z nasłuchem
click
- Animacja wejścia dodaje klasę
active zmieniającą opacity na 1 i pointer-events na auto
- Animacja wykorzystuje CSS transition na właściwościach opacity i transform przez 0.3s
- Walidacja pól sprawdza czy login i hasło nie są puste przez
value.trim() !== ''
- Dane testowe: login
admin, hasło admin123 porównywane przez ===
- Symulacja logowania realizowana jest przez
setTimeout z 2000ms imitującym czas odpowiedzi serwera
- Podczas ładowania wyświetlany jest komunikat "Logowanie..." z wyłączonym przyciskiem
- Po sukcesie wyświetlany jest komunikat zielony "Zalogowano pomyślnie!"
- Przy błędzie wyświetlany jest komunikat czerwony "Nieprawidłowy login lub hasło"
- Zamknięcie modala realizowane jest przez: przycisk X, klawisz Escape, kliknięcie poza modalem
- Zdarzenie
keydown sprawdza e.key === 'Escape' dla obsługi klawisza
- Zdarzenie
click na overlay sprawdza e.target === modalOverlay
- Po zamknięciu formularz jest resetowany przez
form.reset()
Plik rozwiązania:
Otwórz 06_html_z05.html
Testowanie:
- Kliknij przycisk "Zaloguj" aby otworzyć modal
- Spróbuj wysłać puste pola - zobaczysz błąd walidacji
- Wpisz błędne dane i kliknij Zaloguj - zobaczysz komunikat błędu po 2 sekundach
- Wpisz admin/admin123 - zobaczysz sukces
- Naciśnij Escape aby zamknąć modal
- Kliknij poza modalem aby zamknąć
Zadanie 6: Tabela z sortowaniem i wyszukiwaniem
Rozwiązanie:
Tabela użytkowników z funkcją wyszukiwania w czasie rzeczywistym i sortowaniem kolumn.
Opis działania:
- Dane użytkowników przechowywane są w tablicy obiektów
users = [{id, name, email, role, status}, ...]
- Generowanie wierszy tabeli realizowane jest przez metodę
map() z tworzeniem elementów TR
- Wyszukiwarka wykorzystuje pole input z nasłuchem
input na zdarzenie zmiany tekstu
- Filtrowanie wykonywane jest przez metodę
filter() sprawdzającą czy tekst zawiera frazę wyszukiwania
- Sortowanie nagłówków realizowane jest przez nasłuch
click na elementach TH
- Zmienna
sortColumn przechowuje aktualnie sortowaną kolumnę
- Zmienna
sortDirection określa kierunek sortowania ('asc' lub 'desc')
- Sortowanie tekstu wykorzystuje
a[key].localeCompare(b[key]) dla poprawnej kolejności
- Ikony sortowania wyświetlane są przez dodawanie klas CSS (strzałka w górę/dół)
- Licznik wyników aktualizowany jest po każdym filtrowaniu przez
filteredUsers.length
- Style dla ról: Admin (czerwony), User (niebieski), Moderator (zielony)
- Style dla statusów: Aktywny (zielony), Nieaktywny (szary), Zawieszony (czerwony)
- Responsywny układ zapewnia czytelność na różnych urządzeniach
Plik rozwiązania:
Otwórz 06_html_z06.html
Testowanie:
- Wpisz w wyszukiwarce "admin" - zobaczysz filtrowane wyniki
- Kliknij nagłówek kolumny - dane posortują się rosnąco
- Kliknij ponownie - sortowanie zmieni się na malejące
- Zobacz jak zmienia się licznik wyników
- Zwróć uwagę na kolory ról i statusów
Zadanie 7: Zegar światowy z strefami czasowymi
Rozwiązanie:
Aplikacja wyświetlająca aktualny czas w różnych strefach czasowych z aktualizacją w czasie rzeczywistym.
Opis działania:
- Strefy czasowe zdefiniowane są w tablicy obiektów z nazwą miasta i identyfikatorem IANA
- Strefy: Warszawa (Europe/Warsaw), Nowy Jork (America/New_York), Tokio (Asia/Tokyo), Sydney (Australia/Sydney)
- Formatowanie daty i czasu wykorzystuje obiekt
Intl.DateTimeFormat z opcjami konfiguracji
- Opcje formatowania:
{timeZone, hour: '2-digit', minute: '2-digit', second: '2-digit', weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'}
- Aktualizacja czasu realizowana jest przez
setInterval(updateClocks, 1000) wywoływany co sekundę
- Pierwsze wyświetlenie wykonywane jest od razu przy starcie strony przez wywołanie
updateClocks()
- Dla każdej strefy tworzony jest osobny element HTML z czasem, datą i dniem tygodnia
- Struktura kart wykorzystuje Flexbox dla responsywnego układu
- Karty automatycznie układają się w wiersze na mniejszych ekranach
- Stylizacja zapewnia czytelność z wyraźnymi informacjami o czasie
- Synchronizacja z czasem systemowym przeglądarki zapewnia dokładność
Plik rozwiązania:
Otwórz 06_html_z07.html
Testowanie:
- Obserwuj jak sekundy zmieniają się co sekundę
- Porównaj czas w różnych strefach - różnice wynikają ze stref czasowych
- Zobacz datę i dzień tygodnia dla każdego miasta
- Zwróć uwagę na różnicę czasu między Tokio a Nowym Jorkiem
Zadanie 8: Quiz interaktywny z punktacją
Rozwiązanie:
Quiz z 5 pytaniami o HTML i JavaScript z automatycznym sprawdzaniem odpowiedzi i podsumowaniem wyników.
Opis działania:
- Pytania przechowywane są w tablicy obiektów z strukturą:
{question, answers: [], correct: index}
- Quiz zawiera 5 pytań o HTML i JavaScript z 4 wariantami odpowiedzi każde
- Wyświetlanie pytań realizowane jest przez generowanie elementów HTML dla każdego pytania
- Obsługa wyboru odpowiedzi wykorzystuje zdarzenie
click na przyciskach odpowiedzi
- Po wyborze odpowiedzi sprawdzane jest
answerIndex === question.correct
- Podświetlenie poprawnej odpowiedzi realizowane jest przez dodanie klasy CSS
correct (zielony)
- Podświetlenie błędnej odpowiedzi wykonane jest przez klasę
wrong (czerwony)
- Automatyczne przejście do następnego pytania realizowane jest przez
setTimeout(nextQuestion, 1000)
- Licznik pytań aktualizowany jest po każdym pytaniu przez zmienną
currentQuestion
- Zliczanie punktów wykonywane jest przez inkrementację zmiennej
score przy poprawnej odpowiedzi
- Podsumowanie wyświetlane jest po ostatnim pytaniu z: liczbą punktów, procentem, komunikatem
- Komunikaty: 0-40% "Spróbuj jeszcze raz!", 60-80% "Dobra robota!", 100% "Wspaniałe!"
- Przycisk "Zagraj ponownie" resetuje stan i rozpoczyna quiz od nowa
- Blokada ponownego wyboru odpowiedzi zapobiega wielokrotnemu punktowaniu
Plik rozwiązania:
Otwórz 06_html_z08.html
Testowanie:
- Kliknij odpowiedź - zobaczysz podświetlenie (zielony/czerwony)
- Po 1 sekundzie automatycznie przejdziesz do następnego pytania
- Po 5 pytaniach zobaczysz podsumowanie z punktami
- Kliknij "Zagraj ponownie" aby zrestartować quiz
- Spróbuj odpowiedzieć poprawnie na wszystkie pytania
Zadanie 9: Sklep - koszyk zakupowy
Rozwiązanie:
Prosta aplikacja koszyka zakupowego z dodawaniem produktów, zmianą ilości i trwałym zapisem.
Opis działania:
- Produkty zdefiniowane są w tablicy obiektów:
{id, name, price, image}
- Wyświetlanie produktów realizowane jest przez mapowanie tablicy na elementy HTML
- Dodawanie do koszyka wykorzystuje funkcję
addToCart(productId)
- Koszyk przechowywany jest w stanie jako tablica obiektów:
{productId, quantity}
- Sprawdzenie czy produkt już istnieje w koszyku wykonywane jest przez
find()
- Jeśli produkt istnieje, zwiększana jest ilość przez
quantity++
- Jeśli nie istnieje, dodawany jest nowy obiekt z
quantity: 1
- Zwiększanie ilości realizowane jest przez funkcję
increaseQuantity(id)
- Zmniejszanie ilości wykonywane jest przez funkcję
decreaseQuantity(id)
- Przy ilości 0 produkt jest usuwany z koszyka przez
filter()
- Suma do zapłaty obliczana jest przez reduce:
cart.reduce((sum, item) => sum + item.price * item.quantity, 0)
- Przycisk "Wyczyść koszyk" resetuje stan koszyka do pustej tablicy
- Zapis w localStorage wykonywany jest po każdej zmianie koszyka
- Wczytanie z localStorage realizowane jest przy starcie strony
- Stylizacja zapewnia czytelność z wyraźnymi przyciskami i cenami
Plik rozwiązania:
Otwórz 06_html_z09.html
Testowanie:
- Kliknij "Dodaj" przy produkcie - produkt pojawi się w koszyku
- Kliknij + aby zwiększyć ilość, - aby zmniejszyć
- Gdy ilość dojdzie do 0, produkt zniknie z koszyka
- Obserwuj jak suma do zapłaty się zmienia
- Kliknij "Wyczyść koszyk" - wszystko zniknie
- Odśwież stronę - koszyk powinien się zachować
Zadanie 10: Notatnik z kolorowaniem składni
Rozwiązanie:
Edytor kodu JavaScript z podświetlaniem składni na żywo i możliwością wykonania kodu.
Opis działania:
- Edytor wykorzystuje dwa elementy: textarea do wprowadzania i div do wyświetlania pokolorowanego kodu
- Okno wyjścia (output) służy do wyświetlania wyników wykonania kodu
- Słowa kluczowe JavaScript definiowane są w tablicy:
['var', 'let', 'const', 'function', 'if', 'else', 'for', 'while', 'return', 'true', 'false', 'null', 'undefined', 'console', 'log']
- Kolorowanie realizowane jest przez zamianę tekstu na HTML z elementami
<span class="keyword">
- Wyrażenia regularne używane są do identyfikacji: słów kluczowych, napisów (pojedyncze i podwójne cudzysłowy), komentarzy (
// i /* */), liczb
- Kolejność kolorowania: napisy -> komentarze -> słowa kluczowe -> liczby zapewniająca poprawne pokrycie
- Zdarzenie
input na textarea wywołuje funkcję kolorującą w czasie rzeczywistym
- Synchronizacja przewijania:
output.scrollTop = input.scrollTop
- Funkcja "Uruchom" wykorzystuje
eval() do wykonania wprowadzonego kodu
- Przechwytywanie console.log realizowane jest przez nadpisanie metody
console.log
- Błędy wyłapywane są przez blok try-catch i wyświetlane w output na czerwono
- Ostrzeżenie wyświetlane jest przy próbie uruchomienia przypominające o niebezpieczeństwie eval()
- Kolory CSS dla składni:
- słowa kluczowe: niebieski (#569cd6)
- stringi: jasny zielony (#ce9178)
- liczby: jasny zielony (#b5cea8)
- komentarze: szary (#6a9955)
- Wyczyszczenie output realizowane jest przez
output.innerHTML = ''
Plik rozwiązania:
Otwórz 06_html_z10.html
Testowanie:
- Wpisz kod JS i obserwuj kolorowanie na żywo
- Spróbuj:
console.log("Hello")
- Spróbuj:
for(let i=0; i<3; i++) console.log(i)
- Wpisz błędny kod i zobacz komunikat błędu
- Kliknij "Wyczyść" aby wyczyścić edytor
- Kliknij "Uruchom" aby wykonać kod