Learning Log #7: JavaScript – manipulacja DOM, zdarzenia i pierwsza prawdziwa interaktywność
Poniedziałek, 2 września, 21:40. Szkoła wróciła do normalnego rytmu dziś rano. Dom w końcu cichy. A ja siedzę i patrzę na przycisk na ekranie, który właśnie zmienił kolor po kliknięciu.
Brzmi banalnie, prawda? Przycisk zmienia kolor. Wielka rzecz.
Ale to JA to zrobiłam. Napisałam kod, który sprawił, że strona internetowa reaguje na to, co robi użytkownik. Nie odświeżam strony. Nie klikam linku. Element na ekranie po prostu… reaguje. Na żywo.
Po dwóch miesiącach mikroedukacji w wakacje (o czym pisałam w poprzednim wpisie) i powrocie do pełnego tempa we wrześniu, wreszcie dotarłam do tematu, na który czekałam najbardziej: manipulacja DOM i zdarzenia w JavaScript. To jest moment, w którym JavaScript przestaje być „kolejnym językiem do nauki” i staje się narzędziem, które tchnie życie w strony internetowe.
Dziś w Learning Log #7 pokażę Wam czym jest DOM, jak JavaScript nim manipuluje, czym są nasłuchiwacze zdarzeń, i opiszę te momenty „wow”, kiedy pierwszy raz zobaczyłam własny kod reagujący na kliknięcie myszką.
Czym jest DOM – wyjaśnienie które w końcu do mnie dotarło
Problem: rozumiałam składnię, ale nie rozumiałam koncepcji
Przez pierwsze tygodnie nauki JavaScript umiałam pisać pętle, funkcje, warunki – ale nie rozumiałam, jak to wszystko łączy się ze stroną internetową, którą widzę w przeglądarce.
To była luka, która blokowała mnie od tworzenia czegokolwiek realnego.
Wyjaśnienie które zadziałało – analogia z domem
DOM (Document Object Model, po polsku: obiektowy model dokumentu) to sposób, w jaki przeglądarka „widzi” stronę internetową – nie jako tekst HTML, ale jako strukturę drzewa obiektów, którymi można manipulować.
Analogia która mi pomogła:
Wyobraź sobie dom (budynek, nie stronę). HTML to plan architektoniczny domu – papierowy dokument opisujący, gdzie są ściany, drzwi, okna.
DOM to sam dom, zbudowany na podstawie tego planu – fizyczna struktura, którą można otworzyć, zamknąć, przemalować, przestawić meble.
HTML (plan):
html
<div id="salon">
<button id="przycisk">Kliknij mnie</button>
<p id="tekst">Witaj!</p>
</div>
DOM (dom zbudowany z planu): Przeglądarka tworzy strukturę drzewa:
document
└── div#salon
├── button#przycisk
└── p#tekst
JavaScript może wejść do tego „domu” i:
- Otworzyć drzwi (znaleźć element)
- Przemalować ścianę (zmienić styl)
- Przestawić meble (zmienić strukturę)
- Zainstalować dzwonek reagujący na naciśnięcie (dodać nasłuchiwacz zdarzenia)
Pierwsza manipulacja DOM – znajdowanie elementów
Podstawowe metody wyszukiwania elementów:
javascript
// Po ID (najczęściej używane)
const przycisk = document.getElementById('przycisk');
// Po klasie (może zwrócić wiele elementów)
const wszystkieKarty = document.getElementsByClassName('karta');
// Po selektorze CSS (najbardziej elastyczne)
const pierwszyPrzycisk = document.querySelector('.przycisk');
const wszystkiePrzyciski = document.querySelectorAll('.przycisk');
WTF moment #1: „Czekaj, mogę wyszukiwać elementy DOKŁADNIE tak samo jak w CSS?!”
To była pierwsza rzecz, która sprawiła, że JavaScript nagle „kliknął” (nie mylić z tym przyciskiem, o którym za chwilę). Znałam już selektory CSS z pracy z WordPressem. Nagle mogłam użyć tej samej wiedzy do wyszukiwania elementów w JavaScript.
Manipulacja DOM – zmienianie tego, co widać na ekranie
Zmiana tekstu
javascript
const naglowek = document.getElementById('naglowek');
naglowek.textContent = 'Nowy tekst!';
Pierwsza rzecz, którą zrobiłam: Zmiana powitania na stronie w zależności od pory dnia.
javascript
const godzina = new Date().getHours();
const powitanie = document.getElementById('powitanie');
if (godzina < 12) {
powitanie.textContent = 'Dzień dobry!';
} else if (godzina < 18) {
powitanie.textContent = 'Dzień dobry (popołudniu)!';
} else {
powitanie.textContent = 'Dobry wieczór!';
}
Efekt na ekranie: Odświeżam stronę – tekst się zmienia w zależności od tego, o której godzinie to robię. Proste, ale to był mój pierwszy prawdziwy moment „wow”.
Zmiana stylu (CSS przez JavaScript)
javascript
const przycisk = document.getElementById('przycisk');
przycisk.style.backgroundColor = 'niebieski';
przycisk.style.color = 'biały';
przycisk.style.padding = '10px 20px';
Zmiana klasy (lepsza praktyka niż zmiana pojedynczych stylów):
javascript
const karta = document.querySelector('.karta');
karta.classList.add('podswietlona');
karta.classList.remove('nieaktywna');
karta.classList.toggle('rozwiniety'); // dodaje jeśli nie ma, usuwa jeśli jest
Dlaczego classList jest lepsze niż bezpośrednie zmienianie style:
Bezpośrednia zmiana stylu (element.style.color = 'red') miesza logikę JavaScript ze stylowaniem CSS. Lepsza praktyka to przygotowanie klas CSS wcześniej (np. .aktywny { color: red; }) i dodawanie/usuwanie tych klas przez JavaScript.
Tworzenie nowych elementów dynamicznie
To była kolejna rzecz, która mnie zachwyciła – możliwość tworzenia całkowicie nowych elementów HTML za pomocą kodu, bez wcześniejszego pisania ich w pliku HTML.
javascript
function dodajZadanie(tresc) {
// Tworzę nowy element
const nowyElement = document.createElement('li');
nowyElement.textContent = tresc;
nowyElement.classList.add('zadanie');
// Dodaję go do listy na stronie
const lista = document.getElementById('listaZadan');
lista.appendChild(nowyElement);
}
dodajZadanie('Nauczyć się manipulacji DOM');
dodajZadanie('Zbudować listę zadań');
WTF moment #2: „Mogę tworzyć elementy które nigdy nie istniały w oryginalnym HTML?!”
To otworzyło mi drzwi do zrozumienia, jak działają aplikacje typu lista zadań, komentarze dodawane na żywo, czy dynamiczne galerie zdjęć.
Zdarzenia (events) – jak strona reaguje na użytkownika
Czym są zdarzenia
Zdarzenie to sygnał, że coś się wydarzyło na stronie – kliknięcie, najechanie myszką, wpisanie tekstu, przewinięcie strony, załadowanie się dokumentu.
Nasłuchiwacz zdarzenia (event listener) to fragment kodu, który „czeka” na konkretne zdarzenie i uruchamia się, kiedy ono nastąpi.
Pierwszy nasłuchiwacz zdarzenia – moment przełomowy
javascript
const przycisk = document.getElementById('przycisk');
przycisk.addEventListener('click', function() {
console.log('Kliknięto przycisk!');
});
To był moment, o którym pisałam na początku posta. Kliknęłam przycisk w przeglądarce, i w konsoli pojawił się mój tekst. Coś, co napisałam, zareagowało na moje działanie w czasie rzeczywistym.
Rozwinięcie do praktycznego przykładu – zmiana koloru po kliknięciu:
javascript
const przycisk = document.getElementById('przycisk');
let jestAktywny = false;
przycisk.addEventListener('click', function() {
jestAktywny = !jestAktywny; // odwrócenie wartości logicznej
if (jestAktywny) {
przycisk.style.backgroundColor = 'zielony';
przycisk.textContent = 'Aktywne!';
} else {
przycisk.style.backgroundColor = 'szary';
przycisk.textContent = 'Kliknij mnie';
}
});
Rodzaje zdarzeń które poznałam
Zdarzenia myszy:
javascript
element.addEventListener('click', funkcja); // kliknięcie
element.addEventListener('mouseover', funkcja); // najechanie myszką
element.addEventListener('mouseout', funkcja); // zjechanie myszką
element.addEventListener('dblclick', funkcja); // podwójne kliknięcie
Zdarzenia klawiatury:
javascript
element.addEventListener('keydown', funkcja); // naciśnięcie klawisza
element.addEventListener('keyup', funkcja); // puszczenie klawisza
Zdarzenia formularzy:
javascript
formularz.addEventListener('submit', funkcja); // wysłanie formularza
input.addEventListener('input', funkcja); // zmiana wartości podczas pisania
input.addEventListener('change', funkcja); // zmiana wartości (po opuszczeniu pola)
Zdarzenia strony:
javascript
window.addEventListener('load', funkcja); // strona się załadowała
window.addEventListener('scroll', funkcja); // przewinięcie strony
window.addEventListener('resize', funkcja); // zmiana rozmiaru okna
Obiekt zdarzenia – dodatkowe informacje o tym, co się stało
Kiedy funkcja obsługująca zdarzenie się uruchamia, automatycznie dostaje dostęp do obiektu zdarzenia – zawierającego szczegółowe informacje o tym, co dokładnie się wydarzyło.
javascript
przycisk.addEventListener('click', function(zdarzenie) {
console.log(zdarzenie.target); // który element został kliknięty
console.log(zdarzenie.clientX); // pozycja X kursora
console.log(zdarzenie.clientY); // pozycja Y kursora
});
Praktyczne zastosowanie – walidacja formularza podczas pisania:
javascript
const inputEmail = document.getElementById('email');
const komunikat = document.getElementById('komunikatEmail');
inputEmail.addEventListener('input', function(zdarzenie) {
const wartosc = zdarzenie.target.value;
if (wartosc.includes('@')) {
komunikat.textContent = 'Wygląda dobrze!';
komunikat.style.color = 'zielony';
} else {
komunikat.textContent = 'Brakuje znaku @';
komunikat.style.color = 'czerwony';
}
});
WTF moment #3: „Mogę sprawdzać co użytkownik pisze W CZASIE RZECZYWISTYM, bez klikania jakiegokolwiek przycisku 'sprawdź’?!”
To był moment, który uświadomił mi, dlaczego nowoczesne formularze internetowe pokazują błędy na bieżąco, zamiast dopiero po wysłaniu.
Mój pierwszy prawdziwy projekt interaktywny – lista zadań
Po dwóch tygodniach nauki manipulacji DOM i zdarzeń, zbudowałam mój pierwszy w pełni interaktywny projekt – prostą listę zadań (to-do list).
HTML:
html
<div class="kontener">
<h1>Moja Lista Zadań</h1>
<div class="formularz">
<input type="text" id="noweZadanie" placeholder="Wpisz zadanie...">
<button id="dodajPrzycisk">Dodaj</button>
</div>
<ul id="listaZadan"></ul>
</div>
JavaScript:
javascript
const input = document.getElementById('noweZadanie');
const przyciskDodaj = document.getElementById('dodajPrzycisk');
const lista = document.getElementById('listaZadan');
function dodajZadanie() {
const tresc = input.value.trim();
// Walidacja - nie dodawaj pustych zadań
if (tresc === '') {
alert('Wpisz treść zadania!');
return;
}
// Tworzenie nowego elementu listy
const nowyElement = document.createElement('li');
nowyElement.classList.add('zadanie');
// Tekst zadania
const tekstZadania = document.createElement('span');
tekstZadania.textContent = tresc;
// Przycisk oznaczenia jako wykonane
const przyciskWykonaj = document.createElement('button');
przyciskWykonaj.textContent = '✓';
przyciskWykonaj.classList.add('przycisk-wykonaj');
przyciskWykonaj.addEventListener('click', function() {
tekstZadania.classList.toggle('wykonane');
});
// Przycisk usunięcia
const przyciskUsun = document.createElement('button');
przyciskUsun.textContent = '✗';
przyciskUsun.classList.add('przycisk-usun');
przyciskUsun.addEventListener('click', function() {
nowyElement.remove();
});
// Składanie wszystkiego razem
nowyElement.appendChild(tekstZadania);
nowyElement.appendChild(przyciskWykonaj);
nowyElement.appendChild(przyciskUsun);
lista.appendChild(nowyElement);
// Czyszczenie inputu po dodaniu
input.value = '';
input.focus();
}
// Dodawanie przez kliknięcie przycisku
przyciskDodaj.addEventListener('click', dodajZadanie);
// Dodawanie przez naciśnięcie Enter
input.addEventListener('keydown', function(zdarzenie) {
if (zdarzenie.key === 'Enter') {
dodajZadanie();
}
});
Co się nauczyłam budując ten projekt:
- ✅ Łączenie manipulacji DOM z obsługą zdarzeń – to nie są osobne tematy, tylko dwa elementy tej samej całości
- ✅ Tworzenie zagnieżdżonych elementów dynamicznie (element wewnątrz elementu wewnątrz elementu)
- ✅ Wielokrotne nasłuchiwacze zdarzeń na różnych elementach jednocześnie
- ✅
trim()– usuwanie białych znaków z początku/końca tekstu (zapobiega dodawaniu „pustych” zadań ze spacjami) - ✅
zdarzenie.key– sprawdzanie, który konkretnie klawisz został naciśnięty
Czas realizacji: 3 godziny (rozłożone na trzy dni po godzinie)
Porównanie: Pierwszy mini-projekt w lipcu (kalkulator) zajął mi 2 godziny, ale był statyczny w tym sensie, że nie tworzył nowych elementów. Lista zadań to pierwszy raz, kiedy strona rozrasta się i zmienia strukturę w odpowiedzi na to, co robi użytkownik.
Wyzwania techniczne – co sprawiało najwięcej trudności
1. Zrozumienie this wewnątrz nasłuchiwaczy zdarzeń
Problem:
javascript
przycisk.addEventListener('click', function() {
console.log(this); // co to jest "this"?
});
W kontekście nasłuchiwacza zdarzenia, this odnosi się do elementu, na którym zdarzenie zostało zarejestrowane (czyli do samego przycisku).
Ale przy funkcji strzałkowej (arrow function) this zachowuje się inaczej:
javascript
przycisk.addEventListener('click', () => {
console.log(this); // to NIE jest przycisk, tylko kontekst zewnętrzny
});
Lekcja: Przy pracy z DOM i zdarzeniami, zwykłe funkcje (function() {}) i funkcje strzałkowe (() => {}) zachowują się różnie względem this. To był mylący temat przez dobry tydzień.
2. Event bubbling – „wypływanie” zdarzeń
Problem: Kliknięcie na przycisk wewnątrz elementu <li> uruchamiało nasłuchiwacz zarejestrowany na samym <li>, mimo że kliknęłam tylko przycisk.
Wyjaśnienie: Zdarzenia w DOM „wypływają” od elementu, na którym się wydarzyły, w górę przez wszystkich rodziców w strukturze drzewa.
javascript
lista.addEventListener('click', function(zdarzenie) {
console.log(zdarzenie.target); // dokładny element, który został kliknięty
console.log(zdarzenie.currentTarget); // element, na którym zarejestrowano nasłuchiwacz
});
Praktyczne zastosowanie – delegacja zdarzeń (event delegation):
Zamiast dodawać osobny nasłuchiwacz do każdego elementu listy (co jest nieefektywne przy dynamicznie dodawanych elementach), dodaje się JEDEN nasłuchiwacz do rodzica i sprawdza, co dokładnie zostało kliknięte:
javascript
lista.addEventListener('click', function(zdarzenie) {
if (zdarzenie.target.classList.contains('przycisk-usun')) {
zdarzenie.target.closest('.zadanie').remove();
}
});
WTF moment #4, ale w dobrym sensie: Ta technika rozwiązała problem, z którym walczyłam tydzień wcześniej, próbując dodawać nasłuchiwacze do elementów tworzonych dynamicznie.
3. Zapobieganie domyślnemu zachowaniu przeglądarki
Problem: Formularz po wysłaniu odświeżał całą stronę, co usuwało wszystkie wprowadzone dane.
Rozwiązanie:
javascript
formularz.addEventListener('submit', function(zdarzenie) {
zdarzenie.preventDefault(); // blokuje domyślne odświeżenie strony
// reszta logiki obsługi formularza
});
Lekcja: Wiele elementów HTML ma wbudowane „domyślne zachowanie” (formularz wysyła i odświeża stronę, link przenosi na inną stronę). preventDefault() pozwala przejąć kontrolę i zdecydować, co ma się stać zamiast tego.
Momenty „wow” – lista moich ulubionych
Podsumowując te dwa tygodnie nauki, oto konkretne momenty, które sprawiły, że poczułam prawdziwą radość z programowania:
1. Pierwszy klik konsoli – kiedy console.log('Kliknięto!') faktycznie się pojawił po kliknięciu przycisku
2. Zmiana koloru w czasie rzeczywistym – przycisk zmieniający kolor tła po kliknięciu, bez odświeżania strony
3. Tworzenie elementów, których nigdy nie było w HTML – dodanie nowego zadania do listy, które fizycznie nie istniało w pliku HTML
4. Walidacja na żywo – komunikat błędu pojawiający się i znikający, kiedy piszę w polu formularza, bez klikania czegokolwiek
5. Delegacja zdarzeń działająca poprawnie – moment, kiedy zrozumiałam, dlaczego mój kod przestał działać po dodaniu nowych elementów, i jak to naprawić jednym uniwersalnym nasłuchiwaczem
6. Ukończona lista zadań – moment, kiedy mogłam dodać zadanie, oznaczyć je jako wykonane, i usunąć – wszystko bez odświeżania strony ani jednej linijki PHP
Zasoby, które pomogły mi zrozumieć DOM i zdarzenia
1. JavaScript.info – rozdział „Document” (★★★★★)
Najbardziej szczegółowe i zrozumiałe wyjaśnienie manipulacji DOM, jakie znalazłam. Wracałam do niego wielokrotnie.
2. MDN Web Docs – dokumentacja Event (★★★★★)
Kiedy potrzebowałam sprawdzić, jakie właściwości ma dany typ zdarzenia (np. co dokładnie zawiera obiekt zdarzenia przy keydown), dokumentacja MDN była niezastąpiona.
3. Traversy Media – „JavaScript DOM Crash Course” (★★★★★)
Godzinny film, który pokazuje budowanie kilku małych projektów interaktywnych na żywo. Zobaczenie procesu myślowego kogoś doświadczonego bardzo pomogło mi zrozumieć, jak łączyć poszczególne koncepty.
4. FreeCodeCamp – sekcja „DOM Manipulation” (★★★★☆)
Ćwiczenia praktyczne z natychmiastową weryfikacją. Trochę oderwane od kontekstu (pojedyncze zadania, nie cały projekt), ale świetne do utrwalenia składni.
Plany na wrzesień-październik – co dalej
Tydzień 1-2 września:
- Dokończenie tematu zdarzeń (event delegation, custom events)
- Rozbudowa listy zadań o zapisywanie w localStorage
Tydzień 3-4 września:
- Fetch API – pobieranie danych z zewnętrznych źródeł
- Praca z JSON w JavaScript
Październik:
- Pierwsze starcie z asynchronicznością (promises, async/await)
- Może pierwszy kontakt z React, jeśli poczuję się gotowa
Cel realistyczny: Do końca września chcę umieć budować w pełni funkcjonalne, interaktywne komponenty dla stron klientów – formularze z walidacją, proste kalkulatory, dynamiczne galerie.
FAQ – manipulacja DOM i zdarzenia w JavaScript
Czy manipulacja DOM to to samo co React/Vue?
Nie, ale jest fundamentem, na którym te frameworki się opierają. React i Vue „pod maską” też manipulują DOM, tylko robią to bardziej efektywnie i za pomocą swojej własnej, uproszczonej składni. Zrozumienie czystego (vanilla) DOM znacznie ułatwia późniejszą naukę frameworków.
Czy potrzebuję znać jQuery, żeby manipulować DOM?
Nie. jQuery było popularne, kiedy natywne API JavaScript do manipulacji DOM było bardziej niewygodne. Dzisiaj nowoczesny JavaScript (metody jak querySelector, classList, addEventListener) jest wystarczająco przyjazny, że jQuery stało się w dużej mierze zbędne dla nowych projektów.
Ile czasu zajęła Ci nauka tego tematu?
Około dwóch tygodni intensywniejszej nauki (po powrocie do pełnego tempa po wakacjach) – łącznie może 12-15 godzin, plus dodatkowy czas na budowę projektu listy zadań.
Co było najtrudniejsze w tym temacie?
Zdecydowanie zrozumienie event bubbling i delegacji zdarzeń. To jest koncept, który na papierze brzmi prosto, ale dopóki nie napotkałam realnego problemu (nasłuchiwacz nie działający na dynamicznie dodanych elementach), nie rozumiałam, po co to jest potrzebne.
Czy manipulacja DOM jest przydatna, jeśli pracuję głównie z WordPressem?
Zdecydowanie tak. Nawet przy pracy z gotowym CMS-em, umiejętność dodania własnego, lekkiego JavaScript do konkretnych interakcji (zamiast instalowania kolejnej wtyczki) to ogromna przewaga – i pod względem wydajności strony, i pod względem tego, co możesz zaoferować klientom.
Podsumowanie – Learning Log #7
Manipulacja DOM i zdarzenia w JavaScript to temat, który zmienił moje rozumienie tego, czym w ogóle jest programowanie frontendowe. Wcześniej JavaScript był dla mnie „kolejnym językiem ze składnią podobną do Javy”. Teraz jest narzędziem, które sprawia, że strony internetowe żyją.
Co osiągnęłam:
- ✅ Rozumiem czym jest DOM i jak przeglądarka go tworzy
- ✅ Potrafię wyszukiwać, tworzyć i modyfikować elementy dynamicznie
- ✅ Rozumiem nasłuchiwacze zdarzeń i obiekt zdarzenia
- ✅ Znam delegację zdarzeń i wiem, kiedy jej używać
- ✅ Zbudowałam pierwszy w pełni interaktywny projekt (lista zadań)
- ✅ Widzę bezpośrednie zastosowanie w pracy freelance
Najważniejsza lekcja tego etapu:
Programowanie frontendowe to nie pisanie kodu, który „coś robi”. To pisanie kodu, który reaguje.
Ten przycisk, który zmienia kolor po kliknięciu – to nie jest wielka rzecz techniczna. Ale to jest moment, w którym zrozumiałam, dlaczego ludzie kochają programowanie frontendu: piszesz coś, i to coś odpowiada Ci na żywo.
Po wakacyjnej przerwie i strategii mikroedukacji, wrzesień przywrócił mi pełne tempo – i przyniósł jeden z najbardziej satysfakcjonujących etapów nauki do tej pory.
PS: Pamiętasz swój pierwszy moment „wow” w programowaniu? Co to było? A jeśli dopiero zaczynasz naukę DOM i zdarzeń – z czym masz największe trudności? Zostaw komentarz, chętnie pomogę albo po prostu poczuję się mniej samotna w tym zachwycie nad zmieniającym kolor przyciskiem!
