Laboratorium HTML+JS – Zadania praktyczne
Poniżej znajduje się 10 zadań laboratoryjnych z zakresu programowania w HTML i JavaScript. Każde zadanie jest zaprojektowane tak,
aby zajmowało około 25-30 minut wykonania. Zadania obejmują różne tematy poznane na wykładzie, od podstaw
tworzenia stron HTML, przez manipulację DOM i obsługę formularzy, aż po zaawansowane
przetwarzanie danych i interaktywne aplikacje webowe.
Zadanie 1: Interaktywny formularz kontaktowy
Cel:
Stwórz stronę HTML z formularzem kontaktowym zawierającym walidację po stronie klienta.
Scenariusz:
Pracujesz jako frontend developer w agencji interaktywnej. Klient zamówił formularz kontaktowy na stronę firmową. Formularz powinien zawierać pola: imię (wymagane, min 2 znaki), email (wymagany, poprawny format), telefon (opcjonalny, format polski), wiadomość (wymagana, min 10 znaków). Po wysłaniu formularza wyświetl komunikat potwierdzający lub błędy walidacji bez przeładowania strony. Użyj wbudowanej walidacji HTML5 oraz dodatkowej walidacji JavaScript.
Wskazówki do wykonania:
- Użyj semantycznych znaczników HTML5:
<form>, <label>, <input>, <textarea>
- Dodaj atrybuty walidacji HTML5:
required, minlength, type="email"
- Użyj atrybutu
pattern dla numeru telefonu: pattern="[0-9]{3}-[0-9]{3}-[0-9]{3}"
- Nasłuchuj zdarzenia
submit na formularzu za pomocą addEventListener
- Użyj
e.preventDefault() aby zapobiec domyślnemu wysłaniu formularza
- Pobierz wartości pól używając
document.getElementById() lub querySelector
- Sprawdź warunki walidacji i wyświetl komunikaty błędów w elemencie
<div> z id komunikatu
- Użyj klas CSS do wyświetlania błędów (np.
.error z czerwonym obramowaniem)
- Wyświetl komunikat sukcesu w formacie:
"Dziękujemy, [imię]! Twoja wiadomość została wysłana."
- Przetestuj walidację dla wszystkich przypadków: puste pola, niepoprawny email, zbyt krótka wiadomość
- Dodaj stylistykę CSS aby formularz wyglądał profesjonalnie
Zadanie 2: Dynamiczna galeria obrazów
Cel:
Stwórz stronę z dynamiczną galerią obrazów z funkcją filtrowania i lightboxem.
Scenariusz:
Tworzysz stronę portfolio dla fotografa. Potrzebujesz galerii zdjęć z możliwością filtrowania według kategorii (przyroda, krajobrazy, portrety) oraz funkcją podglądu (lightbox) po kliknięciu w miniaturę. Dane obrazów (src, alt, kategoria) mają być przechowywane w tablicy obiektów JavaScript, a galeria generowana dynamicznie. Kliknięcie w miniaturę otwiera powiększony obraz w overlayu. Uruchom stronę i przetestuj filtrowanie oraz lightbox.
Wskazówki do wykonania:
- Zdefiniuj tablicę obiektów z danymi obrazów:
const galeria = [{ src: 'obraz1.jpg', alt: '...', kategoria: 'przyroda' }, ...]
- Użyj metody
map() lub forEach() do generowania elementów galerii
- Twórz elementy DOM używając
document.createElement() i appendChild()
- Dodaj przyciski filtrowania z atrybutami
data-kategoria
- Nasłuchuj kliknięć na przyciskach i filtruj tablicę używając
filter()
- Po filtrowaniu wyczyść galerię i wygeneruj nowe elementy
- Dodaj nasłuchiwacz
click na miniaturach do otwierania lightboxa
- Lightbox to element
<div> z klasą .lightbox (domyślnie ukryty)
- Pokaż lightbox zmieniając
style.display na 'block'
- Zamknij lightbox klikając w przycisk X lub poza obrazem
- Dodaj CSS dla efektu hover i płynnego przejścia
Zadanie 3: Todo list z użyciem localStorage
Cel:
Stwórz aplikację Todo list z trwałym zapisem danych w localStorage.
Scenariusz:
Budujesz osobistą aplikację do zarządzania zadaniami. Aplikacja powinna mieć pole tekstowe do wpisywania nowego zadania, listę wyświetlającą wszystkie zadania z możliwością oznaczania jako ukończone, przycisk usuwania, licznik zadań do zrobienia i opcję filtrowania (wszystkie/ukończone/do ukończenia). Zadania mają być zapisywane w localStorage, aby przetrwały przeładowanie strony. Po odświeżeniu strony lista ma być automatycznie wypełniana z localStorage. Uruchom aplikację i przetestuj dodawanie, oznaczanie i usuwanie zadań.
Wskazówki do wykonania:
- Zdefiniuj funkcję do pobierania zadań z localStorage:
JSON.parse(localStorage.getItem('zadania'))
- Zdefiniuj funkcję do zapisywania:
localStorage.setItem('zadania', JSON.stringify(zadania))
- Początkowa struktura zadania:
{ id: Date.now(), tekst: '...', ukonczone: false }
- Nasłuchuj submit na formularzu dodawania zadań
- Po dodaniu nowego zadania dodaj obiekt do tablicy i zapisz w localStorage
- Użyj metody
render() do wyświetlania listy zadań
- Dla każdego zadania twórz elementy: checkbox, tekst zadania, przycisk usuwania
- Nasłuchuj zmiany checkboxa i aktualizuj stan
ukonczone w tablicy
- Przy usuwaniu użyj
filter() do usunięcia zadania z tablicy
- Dodaj licznik:
zadania.filter(z => !z.ukonczone).length
- Dodaj filtrowanie używając instrukcji
switch lub warunków
- Przetestuj czy dane przetrwają przeładowanie strony
Zadanie 4: Kalkulator BMI z wykresem
Cel:
Stwórz kalkulator BMI z interpretacją wyniku i prostym wizualnym wskaźnikiem.
Scenariusz:
Projektujesz moduł wellness na stronę fitness. Kalkulator przyjmuje wagę (kg) i wzrost (cm), oblicza BMI według wzoru: waga / (wzrost/100)^2. Następnie interpretuje wynik: niedowaga (<18.5), prawidłowa (18.5-24.9), nadwaga (25-29.9), otyłość (>=30). Wyświetl wynik z dokładnością do jednego miejsca po przecinku oraz kategorię z odpowiednim kolorem (zielony/niebieski/pomarańczowy/czerwony). Dodaj prosty wizualny wskaźnik (pasek postępu lub wskaźnik na skali). Uruchom kalkulator i przetestuj różne wartości.
Wskazówki do wykonania:
- Stwórz formularz z polami:
input type="number" id="waga" i input type="number" id="wzrost"
- Nasłuchuj zdarzenia
input lub change na polach formularza
- Pobierz wartości i przekonwertuj na liczby:
parseFloat()
- Oblicz BMI:
const bmi = waga / Math.pow(wzrost/100, 2)
- Użyj instrukcji
if/else if do określenia kategorii
- Zdefiniuj obiekt z kolorami i kategoriami:
const kategori = { niedowaga: '#3498db', prawidlowa: '#2ecc71', ... }
- Wyświetl wynik w elemencie
<span id="wynik">
- Zmień kolor wyniku używając
style.color
- Wizualny wskaźnik: pasek
<div> z tłem gradientowym i wskaźnikiem pozycji
- Oblicz pozycję wskaźnika:
(bmi - 15) * szerokosc / 30 (dla skali 15-45)
- Przetestuj z wartościami: 50kg/170cm (niedowaga), 70kg/175cm (prawidłowa), 90kg/180cm (nadwaga)
- Dodaj walidację: wymagana waga > 0 i wzrost > 0
Zadanie 5: Modal logowania z animacją
Cel:
Stwórz modal logowania z efektami animacji CSS i walidacją.
Scenariusz:
Implementujesz system logowania dla aplikacji webowej. Na stronie głównej znajduje się przycisk "Zaloguj", który otwiera modal z formularzem logowania. Modal zawiera pola: login lub email, hasło, oraz checkbox "Zapamiętaj mnie". Po kliknięciu "Zaloguj" walidujesz czy pola nie są puste, a następnie wyświetlasz symulowany komunikat "Logowanie..." przez 2 sekundy (używając setTimeout), po czym wyświetlasz sukces lub błąd. Modal ma płynną animację wejścia i wyjścia (fade + slide). Uruchom i przetestuj otwieranie, zamykanie (X, Escape, kliknięcie poza modalem) i walidację.
Wskazówki do wykonania:
- Przycisk otwiera modal używając
classList.add('active')
- Modal to element
<div id="modal" class="modal"> z zawartością
- Ukryj modal CSS:
.modal { opacity: 0; pointer-events: none; transition: ... }
- Pokaż modal:
.modal.active { opacity: 1; pointer-events: all }
- Nasłuchuj kliknięcia na przycisku otwierania modal
- Zamknij modal klikając w X lub w tło (sprawdź
e.target === modal)
- Nasłuchuj klawisza Escape:
document.addEventListener('keydown', e => { if(e.key === 'Escape') ... })
- Formularz z polami: login, hasło, checkbox "Zapamiętaj"
- Na submit użyj
e.preventDefault()
- Sprawdź czy pola nie są puste:
if (!login.value || !haslo.value)
- Symuluj logowanie:
setTimeout(() => { ... }, 2000)
- Wyświetl komunikat w elemencie
.komunikat z odpowiednim kolorem
- Dodaj CSS dla animacji wejścia/wyjścia (transform + opacity)
Zadanie 6: Tabela z sortowaniem i wyszukiwaniem
Cel:
Stwórz tabelę danych z funkcją sortowania kolumn i wyszukiwania tekstowego.
Scenariusz:
Budujesz panel administratora z tabelą użytkowników. Tabela zawiera dane: ID, Imię, Nazwisko, Email, Rola (Admin/Editor/Viewer), Status (Aktywny/Nieaktywny). Dane są w tablicy obiektów JavaScript. Nad tabelą jest pole wyszukiwania, które filtruje wiersze w czasie rzeczywistym. Nagłówki kolumn są klikalne i sortują tabelę rosnąco/malejąco (użyj icon rotate przy drugim kliknięciu). Dodaj wiersz z informacją o liczbie wyników. Uruchom i przetestuj wyszukiwanie i sortowanie.
Wskazówki do wykonania:
- Zdefiniuj tablicę obiektów:
const uzytkownicy = [{ id: 1, imie: 'Jan', ... }, ...]
- Generuj tabelę używając
map() i join() lub forEach()
- Nasłuchuj
input na polu wyszukiwania
- Filtrowanie:
uzytkownicy.filter(u => u.imie.includes(wyszukiwany) || ...)
- Dodaj atrybuty
data-sort="imie" do nagłówków
- Zmienna stanu:
let aktualnaKolumna = null; let kierunek = 'asc';
- Nasłuchuj kliknięcia na nagłówku i wywołaj
sortuj(kolumna)
- Funkcja sortująca:
tablica.sort((a,b) => a[kolumna] > b[kolumna] ? 1 : -1)
- Zmień kierunek przy drugim kliknięciu w tę samą kolumnę
- Zapisz kierunek w zmiennej i użyj w funkcji sortującej
- Po każdej operacji wywołaj render() tabeli
- Aktualizuj licznik wyników:
wyniki.length
- Dodaj CSS dla sortowanej kolumny i ikony kierunku
Zadanie 7: Zegar światowy ze strefami czasowymi
Cel:
Stwórz stronę wyświetlającą zegar dla wybranych stref czasowych.
Scenariusz:
Projektujesz stronę dla firmy działającej globalnie. Strona wyświetla zegar dla 4 stref czasowych: Warszawa (Europe/Warsaw), Nowy Jork (America/New_York), Tokio (Asia/Tokyo), Sydney (Australia/Sydney). Dla każdej strefy wyświetl: miasto, aktualną godzinę (HH:MM:SS), datę i dzień tygodnia. Godziny aktualizują się co sekundę (użyj setInterval). Dodaj funkcję aktualizacji czasu co minute (zmiana wyświetlania co 60 sekund, ale zegar nadal tyka). Użyj obiektu Intl.DateTimeFormat do formatowania. Uruchom i obserwuj aktualizację zegara.
Wskazówki do wykonania:
- Zdefiniuj tablicę stref:
const strefy = [{ miasto: 'Warszawa', timeZone: 'Europe/Warsaw' }, ...]
- Użyj
new Date() do pobrania aktualnego czasu
- Formatuj używając
Intl.DateTimeFormat('pl-PL', { timeZone: '...', hour: '2-digit', minute: '2-digit', second: '2-digit' })
- Dla daty: dodaj
weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'
- Generuj kartę dla każdej strefy używając szablonu literal:
`<div class="zegar">${miasto}...`
- Użyj
setInterval(aktualizujCzas, 1000) do aktualizacji co sekundę
- W funkcji aktualizuj() iteruj po kartach i aktualizuj ich treść
- Znajdź elementy po klasie lub
querySelectorAll('.zegar')
- Zapisz idx strefy w atrybucie
data-idx
- Stwórz funkcję do renderowania początkowego
- Dodaj CSS dla kart: flex, padding, tło, responsywność
- Przetestuj czy godziny są poprawne dla każdej strefy
Zadanie 8: Quiz interaktywny z punktacją
Cel:
Stwórz interaktywny quiz z pytaniami, odpowiedziami i systemem punktacji.
Scenariusz:
Tworzysz quiz wiedzy o HTML i JavaScript na stronę edukacyjną. Quiz zawiera 5 pytań z 4 odpowiedziami (tylko jedna poprawna). Po wyborze odpowiedzi podświetl ją na zielono (poprawna) lub czerwono (błędna) i wyświetl komunikat. Po 1 sekundzie przejdź do następnego pytania. Na końcu wyświetl podsumowanie: liczbę punktów (1 punkt za poprawną odpowiedź), procent poprawnych i komunikat (np. "Świetnie! 80%"). Dodaj przycisk "Zagraj ponownie". Pytania mają być w tablicy obiektów. Uruchom quiz i odpowiedz na wszystkie pytania.
Wskazówki do wykonania:
- Zdefiniuj tablicę pytań:
const pytania = [{ pytanie: '...', odpowiedzi: ['a','b','c','d'], poprawna: 1 }, ...]
- Zmienne stanu:
let aktualnePytanie = 0; let punkty = 0;
- Funkcja
wyswietlPytanie(idx) generuje treść pytania
- Twórz przyciski odpowiedzi z atrybutem
data-indeks
- Nasłuchuj
click na każdym przycisku odpowiedzi
- Sprawdź odpowiedź:
indeks === pytania[idx].poprawna
- Jeśli poprawna: dodaj klasę
.poprawna i punkty++
- Jeśli błędna: dodaj klasę
.bledna i podświetl poprawną
- Użyj
setTimeout(() => { aktualnePytanie++; wyswietlPytanie(aktualnePytanie) }, 1000)
- Po ostatnim pytaniu wyświetl podsumowanie
- Oblicz procent:
Math.round((punkty / 5) * 100)
- Przycisk "Zagraj ponownie" resetuje stan i wywołuje wyswietlPytanie(0)
- Dodaj CSS dla stanów poprawna/bledna (kolory tła)
Zadanie 9: Sklep - koszyk zakupowy
Cel:
Stwórz prosty koszyk zakupowy z dodawaniem, usuwaniem i podsumowaniem.
Scenariusz:
Budujesz prosty sklep internetowy. Strona wyświetla listę produktów z cenami (tablica obiektów: nazwa, cena). Każdy produkt ma przycisk "Dodaj do koszyka". Koszyk wyświetla dodane produkty z ilością (jeśli dodano kilka razy, zwiększ ilość), ceną i przyciskiem usuwania. Pod koszykiem: suma do zapłaty (cena * ilość dla każdego produktu). Dodaj funkcję "Wyczyść koszyk", która usuwa wszystko. Użyj localStorage do zapamiętania koszyka. Uruchom i przetestuj dodawanie, zwiększanie ilości, usuwanie produktów.
Wskazówki do wykonania:
- Zdefiniuj produkty:
const produkty = [{ id: 1, nazwa: 'Laptop', cena: 2999 }, ...]
- Początkowy koszyk: pobierz z localStorage lub pusta tablica
- Funkcja
dodajDoKoszyka(id): sprawdź czy produkt już w koszyku
- Jeśli jest:
ilocznosc++; jeśli nie: koszyk.push({ id, ilosc: 1 })
- Zapisz koszyk:
localStorage.setItem('koszyk', JSON.stringify(koszyk))
- Renderuj listę produktów używając
map()
- Renderuj koszyk: dla każdego produktu znajdź dane w tabeli produktów
- Oblicz sumę:
koszyk.reduce((sum, item) => sum + item.ilosc * produkt.cena, 0)
- Funkcja
usunZKoszyka(id): filter() lub zmniejsz ilość
- Funkcja
wyczyscKoszyk(): pusta tablica i zapisz
- Formatuj cenę:
toFixed(2) + ' zł'
- Nasłuchuj kliknięć na przyciskach "Dodaj" i "usuń"
- Po każdej operacji wywołaj render() koszyka i aktualizuj sumę
Zadanie 10: Notatnik z kolorowaniem składni
Cel:
Stwórz prosty edytor tekstowy z podświetlaniem składni JavaScript.
Scenariusz:
Tworzysz narzędzie do nauki JavaScript dla początkujących. Edytor to pole textarea, w którym użytkownik wpisuje kod JavaScript. Pod textarea jest przycisk "Uruchom", który wykonuje kod używając eval() i wyświetla wynik (lub błąd) w sekcji wyników. Dodaj podstawowe kolorowanie słów kluczowych: var/let/const (niebieski), function (różowy), string (zielony), komentarz // (szary), liczby (pomarańczowy). Kolorowanie ma działać po wpisaniu tekstu (nasłuch input). Uruchom edytor i przetestuj kolorowanie i wykonanie kodu.
Wskazówki do wykonania:
- Elementy:
<textarea id="kod"> i <pre id="wynik">
- Nasłuchuj
input na textarea
- Funkcja
koloruj(kod): używa wyrażeń regularnych do zamiany słów
- Zdefiniuj wzorce:
const slowaKluczowe = /\b(var|let|const|function|if|else|for|while|return)\b/g
- Użyj
kod.replace(wzorzec, '<span class="keyword">$1</span>')
- Dodaj wzorce dla stringów:
/(['"])(.*?)\1/g
- Dodaj wzorce dla komentarzy:
/\/\/.*$/gm
- Dodaj wzorce dla liczb:
\b\d+\b
- Użyj
innerHTML do wyświetlania pokolorowanego kodu
- Przycisk "Uruchom" wywołuje
eval(kod.value)
- Przechwyć błędy używając try/catch
- Wyświetl wynik w konsoli lub w elemencie wyników
- CSS:
.keyword { color: blue; }, .string { color: green; } itd.
- Dodaj bezpieczeństwo: ostrzeżenie przed użyciem eval w produkcji