JS cz.5
JSON – Java Script Object Notation, wywodzi się z JS , ale stał się niezależnym typem; każdy język programowania ma obsługę JSONa
JSON (JavaScript Object Notation) to format danych, czyli sposób zapisywania informacji w czytelny sposób, tak aby programy mogły je odczytać i przetwarzać.
- To nie jest język programowania, tylko standard do przedstawiania danych.
- Dane zapisuje się w postaci klucz → wartość, podobnie jak obiekty w JavaScripcie
---
Serializacja to proces zamiany obiektu w języku programowania na format, który można zapisać lub przesłać, np. na JSON, XML czy plik binarny.
- Cel: przechowywanie lub przesyłanie danych między systemami.
- W JavaScripcie to najczęściej zamiana obiektu JS na JSON.
const json = JSON.stringify(osoba/nazwa obiektu) = wynik to sting z elementami obiektu
Deserializacja
Deserializacja to proces odwrotny: zamiana danych zapisanych w formacie wymiany (np. JSON) na obiekt w języku programowania.
- Cel: odczytanie danych i praca z nimi w programie.
const osoba = JSON.parse()
Nieserializują się:
-date (zamienią się na ciąg stringów w formacie ISO)
-referencje cykliczne
-metody obiektu
-funkcje
-symbole
-wartości undefined w obiektach lub tablicach
Co się serializuje poprawnie:
- Liczby, teksty, wartości logiczne (true/false)
- Tablice
- Obiekty (bez cykli)
- Null
JSON plaseholder – miejsce do testowania JSONów
Funkcje pomocne przy konwersji:
Function sourceReplacer() – podczas serializacji (JSON.stringify)
- Służy do kontrolowania, co i jak zostanie zamienione na JSON.
- Można nim:
- Filtrować pola – wybrać tylko te, które mają być zapisane.
- Modyfikować wartości – np. zmienić format daty albo tekst.
Function smartReviver() – podczas deserializacji (JSON.parse)
- Służy do kontrolowania, jak dane JSON są zamieniane na obiekty JS.
- Można nim np.:
- Zamienić daty w formie tekstu na obiekty Date.
- Przekształcić wartości w inne typy.
Bibioteka circural JSON pomagają usuwac cykliczne referencje (miejsca gdzie obiekt odnosi siee sam do siebie)
Co to jest JSON Schema?
JSON Schema to specyfikacja służąca do opisywania struktury danych w formacie JSON.
- Pozwala określić, jakie pola powinny występować w obiekcie, jakie mają typy, które są wymagane itp.
- Dzięki temu można sprawdzać poprawność danych JSON (walidacja).
- Można używać w programach, które odbierają JSON z serwera, aby upewnić się, że dane są zgodne ze standardem.
API (ang. Application Programming Interface) to interfejs programistyczny, czyli zbiór reguł i narzędzi, dzięki którym różne programy mogą się ze sobą komunikować.
- API pozwala wywoływać funkcje lub pobierać dane z innego programu, bez potrzeby wiedzy, jak ten program działa wewnętrznie.
- Można je porównać do menu w restauracji: zamawiasz danie, nie zaglądając do kuchni, jak jest przygotowywane.
Można pobierać API z internetu taki jak np. serwisy pogodowe, publiczne api z danymi finansowymi, rozkładem jazdy – trzeba te dane walidować (sprawdzać typy (czy coś jest stringiem, liczbą, obiektem), struktury, formaty (js.10)). Nie można ufać JSONowi z zewnątrz, źródła mogą być niepewne
Jest różnica między walidacją tych danych a sanityzacją tych danych - Sanityzacja w programowaniu oznacza oczyszczanie danych wejściowych w taki sposób, żeby były bezpieczne i poprawne przed użyciem w programie lub zapisaniem w bazie danych.
Jak pracować z zagnieżdżonymi strukturami?
Najczęściej API zwracają bardzo zagnieżdżone dane, wymagają optional chaining, używa się nullish coalescing
Te struktury można spłaszczyć, robić destructuring, stosować metody tablicowe, filtrowanie – tego się tu używa
- DOM (Document Object Model) to struktura dokumentu HTML jako obiektów w JS.
- Pozwala dostęp i modyfikację elementów strony za pomocą JavaScript.
- Każdy element HTML staje się obiektem w drzewie DOM.
DOM przypomina drzewo, gdzie każdy węzeł to node.
- Document – główny obiekt dokumentu (
document) - Element nodes – każdy tag HTML (
<div>,<p>,<button>) - Text nodes – zawartość tekstowa elementu
- Attribute nodes – atrybuty elementu (
id,class,src,href) - Comment nodes – komentarze w HTML (
<!-- komentarz -->)
Dlaczego DOM jest ważny?
- Pozwala JS czytać, zmieniać i usuwać elementy HTML
- Możesz dynamicznie:
- dodawać nowe elementy (
createElement) - usuwać elementy (
removeChild) - zmieniać style (
style) - reagować na zdarzenia (
addEventListener)
- dodawać nowe elementy (
POSOBY NA POBIERANIE ELEMENTÓW I PODSTAWOWE OBERACJE NA ELEMENTACH
| Typ odwołania | Metoda / Właściwość | Co zwraca / opis | Przykład |
|---|---|---|---|
| Po ID | document.getElementById("id") |
pojedynczy element | const el = document.getElementById("title"); |
| Po klasie | document.getElementsByClassName("klasa") |
HTMLCollection (wszystkie pasujące elementy) | const items = document.getElementsByClassName("item"); |
| Po nazwie tagu | document.getElementsByTagName("tag") |
HTMLCollection wszystkich elementów | const divs = document.getElementsByTagName("div"); |
| Selektor CSS (pierwszy) | document.querySelector("selector") |
pierwszy pasujący element | const el = document.querySelector(".item"); |
| Selektor CSS (wszystkie) | document.querySelectorAll("selector") |
NodeList wszystkich pasujących elementów | const els = document.querySelectorAll(".item"); |
| Węzły potomne | element.children |
HTMLCollection elementów potomnych | parent.children[0]; |
element.childNodes |
wszystkie węzły potomne (tekst, komentarze, elementy) | parent.childNodes; |
|
| Rodzic | element.parentNode |
rodzic elementu | child.parentNode; |
| Sąsiednie elementy | element.nextElementSibling |
następny element na tym samym poziomie | el.nextElementSibling; |
element.previousElementSibling |
poprzedni element na tym samym poziomie | el.previousElementSibling; |
|
| Atrybuty | document.querySelectorAll("[atrybut='wartosc']") |
elementy z konkretnym atrybutem | document.querySelectorAll("[data-id='123']"); |
TWORZENIE I WSTAWIANIE NOWYCH ELEMENTÓW
createElement – nie daje treści w środku, ta metoda tworzy tylko element HTML
createTextNode– pozwala wypełnić tekstem ten sam element, tworzy jego zawartość, tworzy węzeł tekstowy, czyli zawartość elementu HTML, Używa się razem z appendChild(), żeby wstawić tekst do elementu.
Metod które dodają elementy do HTMLA jest kilka:
1. AppendChild() dodaje element jako ostatnie dziecko do wskazanego rodzica
2. InsertBefore() - służy do wstawiania nowego elementu DOM przed innym elementem w tym samym rodzicu.
parentNode.insertBefore(newNode, referenceNode);
parentNode – element, w którym wstawiamy nowy węzeł
newNode – element, który chcemy wstawić
oldNode – element, zostanie usunięty i zastopiony (w metodzie replace)
referenceNode – istniejący element, przed którym zostanie wstawiony nowy węzeł
- Jeśli referenceNode jest null, nowy węzeł zostanie dodany na końcu rodzica (tak jak appendChild())
3. replaceChild (wskazujemy nowy element i element odniesienia) – zmienia istniejący na nowy; jeśli nie ma punktu odniesienia to domyślnie zadziała jak AppendChild
parentNode.replaceChild(newNode, oldNode);
4. removeChild() – usuwa wybrany element rodzica, przydatne do dynamicznego usuwania elementów na stronie (np. przy kliknięciu przycisku „usuń”), remove nie zwraca nic
PODSUMOWANIE:
| Metoda / Właściwość | Co robi | Przykład |
|---|---|---|
document.createElement(tag) |
Tworzy nowy element HTML (pusty) | const div = document.createElement("div"); |
element.textContent |
Ustawia lub pobiera tekst w elemencie | div.textContent = "Hello!"; |
element.innerHTML |
Ustawia lub pobiera HTML w elemencie | div.innerHTML = "<strong>Hi</strong>"; |
parent.appendChild(child) |
Dodaje element jako ostatnie dziecko | document.body.appendChild(div); |
parent.insertBefore(newNode, referenceNode) |
Wstawia element przed wskazanym dzieckiem | parent.insertBefore(div, parent.firstChild); |
parent.replaceChild(newNode, oldNode) |
Zastępuje istniejące dziecko nowym | parent.replaceChild(div, oldDiv); |
element.remove() |
Usuwa element z DOM | div.remove(); |
document.getElementById(id) |
Pobiera element po id | const title = document.getElementById("title"); |
document.getElementsByClassName(className) |
Pobiera wszystkie elementy o danej klasie | const items = document.getElementsByClassName("item"); |
document.getElementsByTagName(tag) |
Pobiera wszystkie elementy danego typu | const divs = document.getElementsByTagName("div"); |
document.querySelector(selector) |
Pobiera pierwszy element pasujący do selektora CSS | const first = document.querySelector(".item"); |
document.querySelectorAll(selector) |
Pobiera wszystkie elementy pasujące do selektora CSS | const all = document.querySelectorAll(".item"); |
element.setAttribute(attr, value) |
Ustawia atrybut elementu | div.setAttribute("id","myDiv"); |
element.getAttribute(attr) |
Pobiera wartość atrybutu | div.getAttribute("id"); // "myDiv" |
W JavaScript możesz zmieniać wygląd elementów NA DWA SPOSOBY:
- element.style
element.style, np.:
element.style.color = "red";
To właściwość każdego elementu DOM, która reprezentuje inline style (czyli styl wpisany bezpośrednio w elemencie).
- classList to obiekt w JavaScript, który daje Ci narzędzia (metody) do manipulowania klasami CSS elementu. MA SWOJE METODY:
1.classList.add to metoda w JavaScript, która dodaje klasę CSS do elementu.
Używa się jej, żeby zmienić wygląd elementu (bo CSS działa na klasy).
2. classList.remove("klasa") – usuwa klasę
3.classList.toggle("klasa")
Przełącza klasę:
• jeśli jest → usuwa
• jeśli nie ma → dodaje
4.classList.toggle("klasa")
Przełącza klasę:
• jeśli jest → usuwa
• jeśli nie ma → dodaje
• element.classList.toggle("active");
• Jeśli element ma klasę active → zostanie usunięta.
• Jeśli nie ma → zostanie dodana.
• toggle – zwraca boolean („Toggle” oznacza przełączanie czegoś między dwoma stanami.
Czyli: jeśli coś jest włączone → wyłącz, a jeśli wyłączone → włącz.)
5. classList.replace("stara", "nowa")
Kiedy używać którego?
• element.style → gdy chcesz zmienić pojedynczą wartość dynamicznie.
Np. zmiana koloru podczas animacji lub reakcji na kliknięcie.
• classList → gdy chcesz zarządzać zestawem stylów, np. włącz/wyłącz tryb ciemny, podświetlenie, ukrywanie/pokazywanie elementów.
W praktyce często łączysz oba:
• classList do struktury i dużych zmian stylu
• style do drobnych dynamicznych efektów.
• element.style → zmienia pojedyncze właściwości CSS inline.
• classList → zmienia klasy CSS, co może wpływać na wiele właściwości naraz.
• classList jest bardziej skalowalne, style jest bardziej bezpośrednie i szybkie.
Ważne:
- Odwołania nie są w HTML ani w DOM „dodawane automatycznie”.
- Każdy element ma swój obiekt w DOM od początku.
- Tworzysz zmienne w JS (
const title = ...) tylko dla tych elementów, którymi chcesz manipulować lub odczytać dane.
Czyli: DOM zawiera wszystkie elementy, ale nie każdy element musi mieć zmienną w JS — tylko te, które chcesz użyć.
DocumentFragment to specjalny, „lekki” mini-dokument, którego używa się do tworzenia elementów poza głównym DOM – dzięki temu dodawanie wielu elementów na raz jest duuużo szybsze i nie powoduje migania, przeładowania i niepotrzebnych renderów.
To bardzo przydatny obiekt w programowaniu front-endowym.
Co to jest DocumentFragment?
To tymczasowy kontener na elementy DOM.
Nie jest częścią dokumentu (document), dopóki go nie wstawisz.
- nie ma rodzica (parentNode = null)
- działa jak niewidzialny pojemnik
- możesz dodać do niego dowolne elementy
- po dodaniu do DOM jego zawartość jest przenoszona, a sam fragment znika
const fragment = document.createDocumentFragment();
DOM jest ciężki — każde dodanie elementu:
- powoduje przeliczenia layoutu
- repaint
- reflow
- aktualizację struktury drzewa
A DocumentFragment tego nie robi, dopóki nie dodasz go do dokumentu.
Najważniejsze właściwości DocumentFragment
✔ działa jak element DOM, ale nie jest w DOM
✔ po wstawieniu do DOM kopiuje tylko dzieci, a sam znika
✔ idealny do:
- list
- rendering w pętli
- dynamicznych tabel
- frameworków (React robi to wewnętrznie)
deep clone
„Deep clone” (głęboka kopia) oznacza skopiowanie obiektu lub tablicy razem z całą jego/zawartością, tak aby nowa kopia była całkowicie niezależna od oryginału.
To bardzo ważny temat w JavaScript, bo wiele osób myśli, że robi kopię — a tak naprawdę tworzy tylko referencję.
Shallow copy vs Deep copy – podstawowa różnica
🔸 Shallow copy (płytka kopia)
Kopiujesz tylko obiekt zewnętrzny, ale jego wnętrze (obiekty w środku) nadal są połączone.
Deep copy (głęboka kopia)
Tworzysz kopię obiektu + wszystkich obiektów w nim zawartych.
Nowy obiekt ma własne, niezależne wnętrze.
structuredClone() — nowoczesny i najlepszy sposób
Działa od razu, szybko, bez hacków.
Przydatne w:
· React (uniknięcie bezpośredniego mutowania state)
· Redux
· praca z formularzami
· praca z dużymi obiektami konfiguracyjnymi
· testowanie
EVENTY/ZDARZENIA
onclick to atrybut lub właściwość w JavaScript, który służy do reagowania na zdarzenie kliknięcia użytkownika na danym elemencie.
Czyli: kiedy użytkownik kliknie np. przycisk, możemy wykonać jakąś funkcję.
Kliknij mnie
Kiedy użytkownik kliknie przycisk → wywoła się funkcja alert().
onclick tutaj jest atrybutem HTML, który bezpośrednio wskazuje, co zrobić po kliknięciu.
Można w nim dodać tylko jedną funkcję ?
addEventListener – nowocześniejsza metoda
Zamiast nadpisywać onclick, lepiej używać:
btn.addEventListener("click", function() {
alert("Kliknięto z addEventListener!");
});
Dlaczego?
- Możesz dodać wiele funkcji do tego samego zdarzenia.
- Nie nadpisujesz istniejącego onclick
- Listner może mieć dodakową zmienną (event) lub (e)
W JavaScript, kiedy używasz addEventListener, do funkcji obsługującej zdarzenie możesz podać specjalny parametr, zwykle nazywany event (czasem e). js.7
To obiekt reprezentujący zdarzenie, który zawiera wszystkie informacje o tym, co się wydarzyło.
Dlaczego używa się event zamiast zwykłej funkcji?
Dzięki event:
- Masz dostęp do elementu, który wywołał zdarzenie (event.target)
- Możesz anulować domyślne zachowanie (formularze, linki)
- Możesz kontrolować propagację zdarzenia w hierarchii DOM
- Możesz reagować dynamicznie na różne rodzaje zdarzeń
Event.target - event.target to właściwość obiektu zdarzenia, który mówi Ci dokładnie, który element został kliknięty lub w ogóle wywołał zdarzenie.
To bardzo przydatne, bo dzięki temu możesz używać jednego listenera dla wielu elementów i wiedzieć, który element wywołał akcję.
Jednym eventListenerem w DIV można uruchamiać wiele przycisków, które są w jego wnętrzu i uruchamiać je (?)
Opcje ważne dla formularzy:
submit
- submit to zdarzenie wywoływane, gdy użytkownik wysyła formularz.
- Formularz wysyłany może być na serwer (action) albo przeładować stronę, jeśli action nie jest podany.
event.preventDefault()
- preventDefault() blokuje domyślne zachowanie przeglądarki przy danym zdarzeniu.
- W przypadku submit oznacza to: formularz nie zostanie wysłany, strona się nie przeładuje.
- Pozwala na kontrolowanie wysyłki formularza przez JS.
Dlaczego warto używać preventDefault przy formularzach
- Dodajesz dynamiczne elementy na stronie (np. lista ToDo) bez przeładowania.
- Walidacja: możesz sprawdzić dane przed wysłaniem na serwer.
- Lepsza kontrola UX: nie tracisz danych ani scrolla na stronie.
Eventy
|
Zdarzenie
(event) |
Co oznacza
/ kiedy się wywołuje |
|
mousedown |
przycisk
myszy został wciśnięty nad elementem kursjs.pl+1 |
|
mouseup |
przycisk
myszy został puszczony nad elementem developerupdates.com (do obsługi złap i przesuń) |
|
click |
kliknięcie
— naciśnięcie + puszczenie przycisku myszy javascripttutorial.net+1 |
|
dblclick |
podwójne
kliknięcie myszy javascripttutorial.net |
|
mousemove |
kursor
myszy porusza się nad elementem javascripttutorial.net |
|
mouseover |
kursor
myszki wjechał na element lub jego pod-elementy javascripttutorial.net+1 |
|
mouseout |
kursor
opuścił element lub jego pod-elementy kursjs.pl+1 |
|
mouseenter |
kursor
wszedł na element (nie zlicza pod-elementów) javascripttutorial.net |
|
mouseleave |
kursor
opuścił element (nie zlicza pod-elementów) developerupdates.com |
|
contextmenu |
kliknięcie
prawym przyciskiem myszy (otwarcie menu kontekstowego) javascripthive.info |
|
wheel |
obrót
kółkiem myszy / scroll myszy javascripttutorial.net |
|
Zdarzenie
(event) |
Co robi /
kiedy się wywołuje |
|
focus |
Pole
formularza zyskuje fokus (użytkownik kliknął w pole lub użył tabulatora). |
|
blur |
Pole
formularza traci fokus (użytkownik opuścił pole). |
|
input |
Wartość
pola zmienia się na bieżąco podczas pisania (dla <input> i
<textarea>). |
|
change |
Wartość
pola uległa zmianie i pole straciło fokus (dla <input>, <select>,
<textarea>). |
|
submit |
Formularz
został wysłany (np. kliknięto przycisk submit). |
|
reset |
Formularz
został zresetowany do wartości domyślnych. |
|
invalid |
Pole
formularza nie spełnia wymagań walidacji HTML5. |
|
select |
Fragment
tekstu w polu formularza został zaznaczony przez użytkownika. |
|
keydown |
Naciśnięto
klawisz na polu formularza. |
|
keyup |
Zwolniono
klawisz na polu formularza. |
|
keypress |
Naciśnięto
klawisz, który generuje znak (stare, rzadko używane, lepiej keydown). |
|
focusin |
Podobne do
focus, ale zdarzenie bąbelkuje (można je łapać na rodzicu). |
|
focusout |
Podobne do
blur, ale zdarzenie bąbelkuje (można je łapać na rodzicu). |
Eventy dotykowe:
|
Zdarzenie |
Co oznacza
/ kiedy się wywołuje |
|
touchstart |
Wywoływane,
gdy użytkownik przyłoży palec do ekranu (rozpoczęcie dotyku). |
|
touchmove |
Wywoływane,
gdy palec porusza się po ekranie. Można użyć do przeciągania elementów lub
gestów. |
|
touchend |
Wywoływane,
gdy użytkownik podnosi palec z ekranu (koniec dotyku). |
|
touchcancel |
Wywoływane,
gdy dotyk został przerwany (np. przychodzący telefon, system przejmuje
kontrolę). |
⌨️ Zdarzenia klawiatury
⬇️ keydown
Klawisz naciśnięty (najczęściej używane).
⬆️ keyup
Klawisz puszczony.
(stare) keypress
Tylko klawisze generujące znaki. Obecnie rzadko stosowane.
Jak działają
- Każdy z eventów otrzymuje obiekt zdarzenia (event), który zawiera właściwości związane z dotykiem:
- touches – lista wszystkich palców dotykających ekran w danym momencie.
- targetTouches – lista palców dotykających konkretny element.
- changedTouches – lista palców, które zmieniły swój stan w tym evencie (np. zostały podniesione lub rozpoczęły dotyk).
- Można odczytać współrzędne dotyku:
- touch.pageX, touch.pageY – pozycja względem całej strony.
- touch.clientX, touch.clientY – pozycja względem widocznej części okna.
- Eventy dotykowe nie bąbelkują w ten sam sposób jak klasyczne zdarzenia myszy, dlatego czasami warto używać preventDefault(), żeby np. zapobiec scrollowaniu strony podczas przeciągania elementu.
W przeglądarkach takich jak Chrome lub Edge możesz w konsoli i narzędziach deweloperskich symulować urządzenie dotykowe, żeby testować eventy dotykowe (touchstart, touchmove, touchend).
Jak działa multitouch w JS
Eventy dotykowe (touchstart, touchmove, touchend) obsługują wielopunktowy dotyk za pomocą właściwości obiektu event:
Właściwość Opis
event.touches Lista wszystkich palców aktualnie dotykających ekran.
event.targetTouches Lista palców dotykających konkretny element, który nas interesuje.
event.changedTouches Lista palców, które zmieniły swój stan w tym evencie (np. rozpoczęły lub zakończyły dotyk).
Js. 16
👉 Które zdarzenia NIE bąbelkują?
❌ mouseenter
❌ mouseleave
❌ focus
❌ blur
Podsumowanie — dlaczego usuwać event listenery?
|
Powód |
Co daje? |
|
unikanie wycieków pamięci |
strona nie spowalnia po dłuższym czasie |
|
brak duplikacji |
funkcje nie wywołują się wielokrotnie |
|
mniejsze zużycie procesora |
animacje i eventy są lżejsze |
|
poprawna logika |
mniej błędów przy wielokrotnym otwieraniu elementów |
|
kontrola aplikacji SPA |
zapobiega chaosowi w systemie zdarzeń |
A kiedy TRZEBA usuwać event listenery?
Tylko w sytuacji, gdy listener:
1️⃣ Jest tymczasowy
np. przewijanie, przeciąganie, trzymanie klawisza, animacje.
Przykład: użytkownik przeciąga element i podczas przeciągania aktywny jest listener mousemove.
Ale kiedy skończy przeciągać → listener trzeba usunąć.
2️⃣ Element zostaje usunięty z DOM
Jeśli element znika (np. usuwa się kartę, modal, wiadomość), a listener zostaje → pamięć przecieka.
Przykład:
Masz listę zadań, usuwasz jedno zadanie z HTML, ale listener zostaje “pod spodem”.
3️⃣ Możesz przypadkowo dodać ten sam listener kilka razy
Kiedy NIE trzeba usuwać? (normalne sytuacje)
✔ zwykłe kliknięcia przycisków
✔ toggle menu
✔ obsługa formularzy
✔ akordeony
✔ rozwijane listy
✔ zwykłe hover → click → zmiana koloru
✔ statyczne elementy strony
Do 80% prac nie trzeba w ogóle myśleć o removeEventListener.
capture (czasem „capturing phase”) to jeden z dwóch kierunków propagacji zdarzeń w JavaScript, czyli sposób, w jaki zdarzenie “przepływa” przez elementy HTML.
🔥 Jak działa propagacja zdarzeń (bardzo ważne!)
Każde zdarzenie w JS — klik, focus, input, mouseover — przebiega w 3 fazach:
1️⃣ CAPTURING – faza przechwytywania (z góry w dół)
Zdarzenie „schodzi” od dokumentu do elementu, który został kliknięty.
document → body → div → button
2️⃣ TARGET – faza celu
Zdarzenie osiąga faktyczny element kliknięty.
3️⃣ BUBBLING – faza bąbelkowania (z dołu w górę)
Zdarzenie „idzie w górę" od elementu klikniętego do góry dokumentu.
button → div → body → document
DOM domyślnie używa bubbling (bąbelkowanie).
🟣 Gdzie w tym jest capture?
Kiedy dodajesz event listener:
element.addEventListener("click", handler);
domyślnie działa on w fazie bubbling.
Jeżeli chcesz, żeby handler wykonał się w fazie capturing, musisz ustawić:
element.addEventListener("click", handler, { capture: true });
Albo krócej (starsza składnia):
element.addEventListener("click", handler, true);
🟦 Po co używać capture?
✔ 1. Gdy chcesz przechwycić zdarzenie WCZEŚNIEJ niż dzieci
Np. globalny handler, który zatrzymuje niektóre kliki, zanim dojdą gdzie indziej.
✔ 2. Gdy wolisz odwrócić kolejność wywołań
Czasem potrzebne przy animacjach lub specjalnych komponentach.
✔ 3. Do debugowania
Capture pozwala zobaczyć, jak zdarzenia przechodzą przez DOM.
🟥 Kiedy NIE używać capture?
W 95% projektów nie trzeba!
Bubbling jest wystarczający i prostszy.
🟩 Prosta metafora, żeby zapamiętać
Wyobraź sobie, że klik to paczka:
- capturing = listonosz idzie od drzwi głównych budynku do Twojego mieszkania
- bubbling = wraca od Twojego mieszkania do drzwi wyjściowych
Normalnie odbierasz paczkę dopiero w swoim mieszkaniu.
Ale jeśli ustawisz capture: true, możesz „przechwycić" ją już w drzwiach wejściowych budynku.
Event propagation
➡️ opisuje JAK zdarzenia przemieszczają się przez DOM (capturing → target → bubbling).
Event delegation
➡️ to technika, która WYKORZYSTUJE propagację, żeby obsługiwać wiele elementów jednym listenerem.
🧠 Dlaczego event delegation jest super?
✔ działa nawet dla elementów dynamicznie dodanych do strony
✔ masz jeden event listener zamiast setek
✔ szybsze działanie aplikacji
✔ łatwiejsze zarządzanie kodem
✔ mniejsze zużycie pamięci
|
Event |
Kiedy się uruchamia |
Użycie |
|
load |
pełne
wczytanie strony |
gdy
potrzebujesz obrazków itp. |
|
DOMContentLoaded |
tylko HTML |
setup JS |
|
error |
ładowanie
zasobu lub błąd JS |
obsługa
błędów |
|
beforeunload |
użytkownik
opuszcza stronę |
ostrzeżenia |
|
unload |
strona
zamykana |
czyszczenie |
|
resize |
zmiana
rozmiaru okna |
layout |
|
scroll |
scrollowanie |
sticky menu,
animacje |
|
visibilitychange |
karta
została ukryta |
pauza |
|
online/offline |
zmiana stanu
internetu |
powiadomienia |
|
storage |
inna karta
zmienia localStorage |
synchronizacja |
---
ASYNCHRONICZNOŚĆ
Asynchroniczność
-wykonuj kod dalej mimo danego zadania
-kod synchroniczny wykona się linia po linii – początek, działanie, rezultaty
-kod asynchroniczny – to wykonaj natychmiast, to wykonaj za sekundę (funkcja timeout)
(to tylko symulacja ansychroniczności) – nie chcemy czekać aż wszystkie operacje się wykonają, część może wykonywać się w tle
Pierwsze narzędzie asynchroniczne to funkcja: setTimeout (argumenty to funkcja i czas wykonania)
setIntrwal – ta funkcja wykonuje się cyklicznie, za każdym razem jak minie zdefiniowane okno
timerów możemy ustawić więcej niż jeden, każdy możemy zatrzymać (clearInterwal )
call back hell – zagnieżdżone funkcje callback
Co to jest Promise?
- Promise to obiekt reprezentujący wynik operacji asynchronicznej, która może zakończyć się:
- sukcesem → resolved
- błędem → rejected
Inaczej mówiąc, promise mówi:
„Nie mam jeszcze wyniku, ale kiedy skończę, dam Ci wynik albo błąd”.
const myPromise = new Promise((resolve, reject) => {
// operacja asynchroniczna
const success = true;
promise – może mieć 3 stany: oczekujące, z sukcesem lu odrzocone
- resolve(value) → operacja się udała, value to wynik.
- reject(error) → operacja się nie udała, error to powód błędu.
CZYLI
· Promise = obietnica wyniku w przyszłości
· Stany: pending → fulfilled → rejected (oczekujący, realizowany, odrzucony)
· Obsługuje asynchroniczność w czytelny sposób (then, catch)
· Możesz łączyć kilka promiseów (Promise.all, Promise.race)
Promise może tylko raz zmienić swój stan
Słowo kluczowe .then() w kontekście Promise służy do obsługi wyniku, gdy obietnica zakończy się sukcesem (czyli gdy Promise jest w stanie fulfilled).
Jak działa .then():
- Przyjmuje funkcję callback, która otrzyma wynik Promise’a przekazany przez resolve().
- Ta funkcja wykona się tylko wtedy, gdy Promise zostanie zrealizowany (fulfilled).
- Możesz też łańcuchować kilka .then(), żeby przetwarzać wynik krok po kroku.
Jeśli obietnica jest spełniona, mówimy wykonaj coś a następie wykonaj coś innego…
(coś może zaczekać, żeby potem sięgnąć po wartość 20:20 – w synchronicznym kodzie mielibyśmy undefined)
Ale może się zdarzyć, że będziemy mieli reject – wtedy używamy catch – obsługujemy błąd
Niezależnie od wyniku możemy na końcu użyć metody finally, która posprząta zasoby, może ukryć loader (symbol ładowania),
- nie zawsze musimy używać konceptu then/catch/finally bo możemy mieć promise, który na pewno zakończy się sukcesem, tylko trwa
- then może przyjąć dodatkowe argumenty, jako hamdler błędu (ale to mniej czytelne niż użycie catch
-czytelny łacuch wywołań – promise chaing – łączenie wielu operacji asynchronicznych – każde then zwraca kolejne promise CZYLI:
startPromise
.then(value) => {…….}
.then(value) => {…….}
.then(value) => {…….}
-każde then to kolejne promise, które wykona się tylko jeśli wykona się poprzednie then; then obsługuje sukces
Error propagation – to błąd obsługiwany przez jedno catch – w łańcuchu zdarzeń, na końcu catch będzie obsługiwać błędy wcześniejszych promisów
TAKI KOD NIE BLOKUJE
setTimout a Promise chaing = w drugiej opcji łatwiej prześledzić co kiedy się wydarzy i jak zostanie obsłużony błąd (js12)
UWAGA – może być tak: promise – ok, promise -błąd = brak wykonania, catch – łapie błąd, ale po błędzie kolejne then/promise wykona się
METODY do obsługiwania zbiorów promisów:
Promise all – przyjmuje tablice promisów – zwraca jeden promise, który się rozwiązuje jako sukces, jeżeli wszystkie promisy w tablicy zakończą się sukcesem
4. Metody statyczne Promise
- Promise.all([promises]) – czeka aż wszystkie Promises się spełnią, jeśli którykolwiek się nie powiedzie, zwraca błąd. (nie będzie czekać na wszystkie promisy, wystarczy wykrycie jednego błędu), zwraca tablice?
- Promise.race([promises]) – zwraca wynik pierwszego Promise, który się spełni lub odrzuci.
- Promise.allSettled([promises]) – zwraca wynik wszystkich Promises, niezależnie od tego, czy się spełniły czy nie- czeka na zweryfikowanie wszytkich promisów/ równoległe wykonywanie wielu operacji asynchronicznych
- Promise.any([promises]) – zwraca wynik pierwszego spełnionego Promise, ignorując odrzucenia.
- Promise.resolve(value) – tworzy Promise spełniony od razu z podaną wartością.
- Promise.reject(reason) – tworzy Promise odrzucony od razu z podanym powodem.
Tam gdzie dane z różnych źródeł, gdzie kalkulacje odbywają się równolegle – warto tego typu operacje stosować
Jak tworzyć własne asynchroniczne funkcje?
1. async
- Służy do oznaczenia funkcji asynchronicznej.
- Funkcja async zawsze zwraca Promise, nawet jeśli w kodzie zwracasz zwykłą wartość.
- Pozwala w środku używać await.
2. await
- Służy tylko w funkcji async.
- Pauzuje wykonanie funkcji aż Promise się spełni (fulfilled) i zwraca jego wartość.
- Dzięki temu można pisać kod asynchroniczny w sposób synchronizowany, czyli łatwiejszy do czytania.
Funkcji async używa się zawsze wtedy, gdy w środku funkcji musisz obsłużyć operacje asynchroniczne (czyli takie, które nie wykonują się od razu i zwracają Promise).
AJAX – powstawał kiedy nie było JSONa
AJAX (ang. Asynchronous JavaScript and XML) to technika w JavaScript, która pozwala asynchronicznie komunikować się z serwerem bez przeładowywania całej strony.
Czyli możesz pobierać lub wysyłać dane w tle, a użytkownik nadal widzi stronę i może z niej korzystać.
Kluczowe cechy AJAX
- Asynchroniczność
- Strona nie odświeża się podczas pobierania danych.
- JavaScript
- Wykorzystuje JS do wysyłania żądań i obsługi odpowiedzi.
- Dane z serwera
- Najczęściej w formacie JSON, dawniej często XML.
- Interaktywność
- Umożliwia dynamiczne aktualizowanie zawartości strony (np. komentarze, lajki, wyszukiwanie).
|
Cecha |
XHR (XMLHttpRequest) |
Fetch API |
|
Typ interfejsu |
Klasyczny obiekt |
Nowoczesny interfejs Promise-based |
|
Obsługa asynchroniczna |
Tak, ale trzeba ustawiać true w open() |
Domyślnie asynchroniczny |
|
Obsługa JSON |
Trzeba ręcznie użyć JSON.parse(xhr.responseText) |
Wbudowana metoda response.json() |
|
Obsługa błędów |
Trudniejsza, trzeba sprawdzać status i readyState |
Prosta, obsługa przez .catch() lub try/catch w async/await |
|
Kod |
Bardziej rozbudowany (więcej boilerplate) |
Krótszy i bardziej czytelny |
|
Obsługa Promise |
❌ brak |
✔ obsługuje Promise, łatwe
async/await |
|
Wywołania |
xhr.open(), xhr.send() |
fetch(url, options) |
|
Wsparcie dla starszych przeglądarek |
✔ działa wszędzie |
✔ nowoczesne przeglądarki,
starsze wymagają polyfill |
|
Czytelność kodu |
Niska (callbacki, zdarzenia) |
Wysoka (Promise / async-await) |
|
Streaming odpowiedzi |
Możliwe, ale trudne |
Lepsze wsparcie dla strumieni (ReadableStream) |
REST API – co to znaczy
- REST = Representational State Transfer
- To styl architektury, czyli zasady projektowania API, a nie konkretna technologia.
- API = Application Programming Interface
- Mówiąc prosto: interfejs umożliwiający programom wymianę danych.
REST API = API, które działa według zasad REST, czyli pozwala klientowi komunikować się z serwerem w prosty i przewidywalny sposób.
Cechy REST API
- Zasoby (resources)
- Wszystko to, co chcemy udostępnić, traktujemy jako „zasób”: użytkownicy, posty, komentarze.
- Każdy zasób ma swój unikalny URL, np.:
- /users → lista użytkowników
- /users/1 → użytkownik o id=1
JAK ŁADOWAĆ PLIKI LOKALNIE
CRUD
Dlaczego CRUD jest ważny
- To podstawowy zestaw operacji w każdej aplikacji z danymi
- Kiedy tworzysz API, zwykle implementujesz CRUD dla każdej „tabeli” (np. użytkownicy, posty, komentarze)
- Pomaga w planowaniu i organizacji kodu
|
Metoda |
Jak działa |
Wymaga serwera? |
Uwagi |
|
Inline |
Dane wpisane
bezpośrednio w HTML/JS |
❌ |
Dobre dla
małych danych |
|
Struktura
danych w kodzie |
Plik JS z
danymi, importowane |
❌ |
Lepsza
organizacja niż Inline |
|
Fetch z
lokalnego pliku |
Pobranie
JSON lub innych danych przez fetch |
✅ |
SOP wymaga
lokalnego serwera |
|
FileReader |
Użytkownik
wybiera plik do odczytu |
❌ |
Bezpieczne,
wymaga interakcji użytkownika |
|
Metoda |
CRUD |
Co robi |
Przykład użycia |
|
GET |
Read |
Czyta i pobiera
dane z serwera, nie zmienia ich |
GET /users → pobierz wszystkich użytkowników |
|
POST |
Create |
Tworzy nowy
zasób na serwerze |
POST /users z JSON {name:
"Ala"} → dodaje nowego użytkownika |
|
PUT |
Update |
Aktualizuje
cały zasób – nadpisuje wszystko |
PUT /users/1 z JSON {name:
"Nowe Imię", email: "nowy@email"} → nadpisuje
użytkownika o id=1 |
|
PATCH |
Update |
Aktualizuje
tylko wybrane pola zasobu |
PATCH /users/1 z JSON {email:
"nowy@email"} → zmienia tylko email użytkownika |
|
DELETE |
Delete |
Usuwa zasób
z serwera |
DELETE /users/1 → usuwa użytkownika o id=1 |
|
Operacja |
Metoda HTTP |
Przykład URL |
|
Create |
POST |
/users (dodaj nowego użytkownika) |
|
Read |
GET |
/users (pobierz wszystkich użytkowników) |
|
Update |
PUT/PATCH |
/users/1 (edytuj użytkownika o id=1) |
|
Delete |
DELETE |
/users/1 (usuń użytkownika o id=1) |
Dlaczego potrzebujemy metod HTTP?
- Rozróżnienie operacji
- Serwer musi wiedzieć, czy klient chce tylko pobrać dane, czy np. utworzyć nowego użytkownika, albo usunąć coś.
- Dzięki metodom HTTP mamy jasny sygnał: GET = odczyt, POST = tworzenie, DELETE = usuwanie itd.
- Bezpieczeństwo i logika serwera
- GET zwykle nie zmienia danych, więc można ją buforować i traktować bezpiecznie.
- POST, PUT, PATCH, DELETE mogą zmieniać dane – serwer może zastosować odpowiednie zabezpieczenia (np. autoryzację).
- REST API i standardy
- Metody te pozwalają projektować czytelne, przewidywalne API.
- Kiedy ktoś patrzy na URL i metodę, od razu wie, co się wydarzy:
- GET /users → pobierz użytkowników
- DELETE /users/1 → usuń użytkownika o id=1
Bezpieczeństwo, autoryzacja zapisu
Klucze (API Keys)
· API Key = specjalny unikalny identyfikator przypisany do użytkownika lub aplikacji, który umożliwia dostęp do API.
· Służy do kontrolowania dostępu i limitowania użycia API.
🔹 Jak działa w praktyce:
- Rejestrujesz aplikację u dostawcy API → otrzymujesz unikalny klucz.
- Każde żądanie do API zawiera ten klucz w nagłówku lub parametrze URL:
🟩 Dlaczego klucze są ważne
- Zapobiegają nieautoryzowanemu użyciu API
- Mogą pozwalać na śledzenie, kto korzysta z API
- Mogą ograniczać np. liczbę żądań na dzień (rate limiting)
💡 Podsumowanie w prostych słowach:
- Bezpieczeństwo API → kontrola dostępu do danych i operacji
- Autoryzacja zapisu → nie każdy może tworzyć/edytować/usunąć dane
- Klucze (API Keys) → identyfikator aplikacji lub użytkownika, który mówi serwerowi: „To jest uprawniony klient”
--- NIE POWINNO SIĘ podawać klucza w adresie URL – będzie widoczny
--LEPIEJ UŻYWAĆ HEADERA (chociaż dalej będzie przesyłany jako zwykły tekst – dlatego potrzebne połączenie https zaszyfrowane)
--NAJLEPSZA METODA do przesyłania kluczy – zdefiniowany HEADERS Authorization z kluczem, tu konkretny sposób przsyłu typ (basic, bearer – token JWT (JSON Web Token/czasowe hasło), apkikey,digest)+ uwierzytelnienie
CANVAS
CANVAS operuje na bitmapie – rysuje pixele (to nie obiekty DOM to obrazek) – czyli modyfikacja = usunięcie i zrobienie od nowa
Element JS dostępny w HTML 5, Samo <canvas> nic NIE wyświetli, dopóki JS nie narysuje czegoś.
Możemy wchodzić w interakcję z canvas – to pozwala tworzyć gry
Podstawowy canvas definiujemy w HTML w <body>
<canvas id=myCanvas” width=’800’ height=”600”> </canvas>
W <script> tworzymy uchwyt:
Const canvas = document.getElementById(‘myCanvas’);
Const ctx = canvas.getContext(‘2d’); --tu odwołanie do współrzędnych, które czyta się w canvas nieintuicyjnie
ctx.fillStyle = "red"; // kolor
ctx.fillRect(10, 10, 100, 60); // x, y, szerokość, wysokość
okręgi rysuje się odrębną funkcją w radianach; obrys prostokąta:
ctx.strokeStyle = "blue";
ctx.strokeRect(10, 90, 100, 60);
rysowanie ścieżki, linii:
ctx.beginPath();
ctx.moveTo(10, 10); // punkt startowy
ctx.lineTo(150, 80); // punkt końcowy
ctx.stroke(); // narysuj linię
rysowanie koła:
ctx.beginPath();
ctx.arc(150, 75, 50, 0, Math.PI * 2);
ctx.fillStyle = "green";
ctx.fill();
PARAMETRY: ctx.arc(x, y, radius, startAngle, endAngle, counterclockwise);
Co oznaczają parametry?
Parametr Znaczenie
x pozycja środka okręgu na osi X
y pozycja środka okręgu na osi Y
radius promień (jak duży jest okrąg)
startAngle początek rysowania (w radianach)
endAngle koniec rysowania (też w radianach)
counterclockwise (opcjonalne) kierunek rysowania — domyślnie zgodnie z ruchem wskazówek zegara
kolejność rysowania ma znaczenie,
ctx.fillStyle= wypełnienie
ctx.strokeStyle =obramowanie
-można pracować na załadowanych obrazkach – warunek – musi być onload – załadowany przez przeglądarkę, trzeba mu te właściwości w html dać
-canvas nie dziedziczy stylów z css
ctx.font = "20px Arial";
ctx.fillStyle = "black";
ctx.fillText("Hello Canvas!", 50, 50);
dla tekstu zawsze najpierw wypełnienie potem obrys
można nakładać na siebie obiekty
obrazki image są promise
Metody modyfikacji obiektów w canvas:
|
Metoda |
Co robi? |
|
translate(x,y) |
Przesuwa
układ współrzędnych |
|
rotate(angle) |
Obraca układ |
|
scale(x,y) |
Skaluje w
osi X i Y |
|
save() |
Zapamiętuje
aktualny stan |
|
restore() |
Przywraca
ostatni zapisany stan |
|
transform() |
Ustawia
macierz transformacji (zaawansowane) |
|
setTransform() |
Resetuje i
ustawia transformację od zera |
Transformacje działają kumulacyjnie – przesunięcie 2 razy przesunie obiekt z pkt a do b
Save zapisuje też styl elementu, restore pozwala wrócić do wcześniejszego stanu
Metoda na tworzenie animacji w canvas:
W JavaScript animacje na <canvas> robi się zawsze według jednej, głównej metody, czyli pętli animacji opartej na requestAnimationFrame().
To jest oficjalny, nowoczesny i najwydajniejszy sposób tworzenia animacji.
1. Zasada działania animacji w canvas
Każda animacja na canvas składa się z 3 kroków:
- Wyczyszczenie sceny (clearRect)
- Aktualizacja położenia/wyglądu obiektów
- Narysowanie elementów na nowo
I to wszystko uruchamia się w pętli, około 60 razy na sekundę.
1. Główna metoda: requestAnimationFrame()
requestAnimationFrame() to mechanizm, który:
- uruchamia funkcję w idealnym momencie, zsynchronizowany z odświeżaniem ekranu,
- działa płynniej niż setInterval,
- nie marnuje energii (przestaje działać, kiedy zakładka jest niewidoczna),
- jest standardem w każdej animacji HTML5.
Możemy animować kilka obiektów, mieszać rodzaju ruchu
Można zaprogramować kolizję elementów
Elementy najlepiej tworzyć obie jako obiekty
/
Kolizje w canvas polegają na sprawdzaniu, czy dwa obiekty zachodzą na siebie.
W animacjach robi się to w pętli requestAnimationFrame(), czyli przy każdej klatce.
Prosta funkcja wykrywania kolizji:
function isColliding(a, b) {
return (
a.x < b.x + b.width &&
a.x + a.width > b.x &&
a.y < b.y + b.height &&
a.y + a.height > b.y
);
}
Funkcja porównuje współrzędne dwóch obiektów – sprawdza relacje obiektów; brany jest również rozmiar elementu