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:
    1. Filtrować pola – wybrać tylko te, które mają być zapisane.
    2. 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.:
    1. Zamienić daty w formie tekstu na obiekty Date.
    2. 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.

  1. Document – główny obiekt dokumentu (document)
  2. Element nodes – każdy tag HTML (<div>, <p>, <button>)
  3. Text nodes – zawartość tekstowa elementu
  4. Attribute nodes – atrybuty elementu (id, class, src, href)
  5. 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)

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:

  1. 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).

  1. 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:

  1. Masz dostęp do elementu, który wywołał zdarzenie (event.target)
  2. Możesz anulować domyślne zachowanie (formularze, linki)
  3. Możesz kontrolować propagację zdarzenia w hierarchii DOM
  4. 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

  1. Dodajesz dynamiczne elementy na stronie (np. lista ToDo) bez przeładowania.
  2. Walidacja: możesz sprawdzić dane przed wysłaniem na serwer.
  3. 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: pendingfulfilledrejected (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():

  1. Przyjmuje funkcję callback, która otrzyma wynik Promise’a przekazany przez resolve().
  2. Ta funkcja wykona się tylko wtedy, gdy Promise zostanie zrealizowany (fulfilled).
  3. 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

  1. Asynchroniczność
    • Strona nie odświeża się podczas pobierania danych.
  2. JavaScript
    • Wykorzystuje JS do wysyłania żądań i obsługi odpowiedzi.
  3. Dane z serwera
    • Najczęściej w formacie JSON, dawniej często XML.
  4. 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

  1. 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?

  1. 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.
  2. 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ę).
  3. 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:

  1. Rejestrujesz aplikację u dostawcy API → otrzymujesz unikalny klucz.
  2. 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:

  1. Wyczyszczenie sceny (clearRect)
  2. Aktualizacja położenia/wyglądu obiektów
  3. 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