Od podstaw JavaScript do 51 arkuszy egzaminacyjnych
Kurs ma dwie części. „Podstawy JS” to dziewiętnaście lekcji od zera. Jedenaście uczy samego języka: zmienne, funkcje (także strzałkowe), warunki, pętle, tablice, obiekty, teksty i szukanie błędów. Osiem kolejnych zbiera tematami to, czego wymagają arkusze: szukanie elementów, zdarzenia, formularze, style, tworzenie elementów, dane, pamięć, datę i losowanie oraz odczyt listy rozwijanej, pól opcji i pól wyboru. Jeśli dopiero zaczynasz, przerób je najpierw. Druga część to lekcje oparte na arkuszach. Obejmuje ona wszystkie 51 arkuszy praktycznych z JavaScript dostępnych w serwisie ezinf.it (INF.03 oraz starsze EE.09 i E.14). Dziewiętnaście arkuszy, które wnoszą coś nowego, ma własne lekcje. Dwadzieścia cztery pozostałe to dodatkowe próby bez lekcji, a osiem powtarza skrypt, który już jest w kursie. Poniżej widzisz działające wzory jedenastu arkuszy z 2026 roku; arkusze bez dopisku są z czerwca. W każdym część JavaScript jest oceniana osobno jako rezultat „skrypt”. Lekcje idą od najprostszych rzeczy do coraz trudniejszych i każda korzysta z poprzednich, więc najlepiej przerabiać je po kolei. Poniżej widzisz, co robi gotowy skrypt z każdego arkusza.
Arkusz 04: strona rezerwacji
Poniżej działa gotowa wersja. Kliknij przyciski i strzałki, żeby zobaczyć, co masz umieć napisać.
Zamiast zdjęć 1.jpg, 2.jpg, 3.jpg widzisz kolorowe karty z nazwą pliku. Plików z egzaminu tu nie ma, a skrypt i tak zmienia atrybut src tak samo.
Co dokładnie każe zrobić arkusz 04
| Funkcja | Kiedy | Co ma zrobić | Lekcja |
|---|---|---|---|
uczestnik() | klik „Uczestnik” | „Uczestnik” na DodgerBlue, „Rezerwacja” na SkyBlue. Kontrolki sekcji 1 aktywne, sekcji 2 nieaktywne. | 3, 4, 5 |
rezerwacja() | klik „Rezerwacja” | Kolory odwrotnie. Kontrolki sekcji 1 nieaktywne, sekcji 2 aktywne. | 3, 4, 5 |
nastepny() | klik „»” | Następne zdjęcie i miasto: Barcelona, Rzym, Londyn, po ostatnim znów pierwsze. | 6 |
poprzedni() | klik „«” | Poprzednie zdjęcie i miasto, z pierwszego przeskok na ostatnie. | 7 |
Arkusz 03: karta produktu
Kliknij miniaturę, żeby podmienić obraz główny. Kliknij obraz główny, żeby otworzyć okno, i znak ×, żeby je zamknąć.
| Funkcja | Kiedy | Co ma zrobić | Lekcja |
|---|---|---|---|
| podmieniająca obraz | klik miniatury | Obraz główny dostaje źródło klikniętej miniatury. | 8 |
| otwierająca okno | klik obrazu głównego | Blok okna dostaje display: block, a obraz w oknie źródło obrazu głównego. | 9, 10 |
| zamykająca okno | klik „×” | Blok okna dostaje display: none. | 9 |
Ten arkusz nie narzuca nazw funkcji ani id. Wymyślasz je samodzielnie, a nazwy klas (obraz, miniatury, okno, obrazOkno, zamknij) muszą zostać takie jak w treści zadania.
Arkusz 06: konto pacjenta
Tu nic nie klikasz. Skrypt uruchamia się przy wczytaniu strony i z danych pacjenta generuje bloki recept.
| Co generuje skrypt | Szczegóły z arkusza | Lekcja |
|---|---|---|
| blok dla każdej recepty | Tyle bloków, ile elementów tablicy recepty. Każdy ma klasę recepty. Tablica może urosnąć. | 11, 12, 13 |
| paragraf z datą | Treść „Data wystawienia: ” i wartość z tablicy. | 12 |
| lista numerowana leków | Pola lek1, lek2, lek3. Puste wpisy są pomijane. | 13 |
| nagłówek czwartego stopnia | Treść „Kod: ” i wartość kodu z tablicy. | 12 |
Arkusz 07: kółko i krzyżyk
Klikaj pola planszy. Znaki pojawiają się na zmianę, napis pokazuje, kto ma ruch, a zajęte pole nie reaguje. Lekcje 14 i 15.
Arkusz 08: licznik wejść
Funkcja uruchamiana przy załadowaniu strony zapisuje liczbę wejść w localStorage i wypisuje ją w stopce. Lekcja 16.
Arkusz 09: restauracja
Kliknięcie potrawy dopisuje ją do zamówienia. „Wyczyść” opróżnia listę, „Zatwierdź” pokazuje komunikat i też ją opróżnia. Lekcja 17.
Arkusz 11: atlas drzew
Kliknięcie obrazu zastępuje zawartość bloku głównego nazwą i opisem drzewa. Wyszukiwarka robi to samo dla wpisanej nazwy albo zgłasza, że drzewa nie ma. Lekcje 18 i 19.
Arkusz 12: salon rowerowy
Suwak przepisuje wzrost do pola liczbowego, przycisk oblicza rozmiar ramy dla wybranego typu roweru, a w tabeli pojawia się dzisiejsza data. Lekcje 20 i 21.
Styczeń 2026, arkusz 03: pola figur
Mały obraz wybiera figurę, a przycisk liczy pole trójkąta albo prostokąta, zależnie od tego, który duży obraz jest na stronie. Lekcja 22.
Styczeń 2026, arkusz 09: stylizacja paznokci
Najechanie kursorem na przycisk pokazuje jego sekcję i zmienia kolory przycisków. W trzeciej sekcji pętla generuje dziesięć obrazów. Lekcje 23 i 24.
Styczeń 2026, arkusz 12: studio tatuażu
Przycisk odczytuje nazwę wybranego pliku, kolor i cenę, pokazuje komunikat i dodaje nowy obraz do galerii. Lekcja 25.
a, f1, x2 kosztują punkt.Jak się tu uczyć
- Idź po kolei. Każda lekcja dokłada jeden element i kończy się ćwiczeniem.
- Kod wpisujesz w edytorze, a strona sama go uruchamia i sprawdza testami.
- Przycisk „Pokaż rozwiązanie” jest na wypadek zacięcia. Po podejrzeniu skasuj kod i napisz go z pamięci.
- Każdy arkusz kończy się próbą: pusty edytor i cały skrypt do napisania samodzielnie.
- Na koniec włącz „Tryb egzaminu”: losowy arkusz, stoper i wymagania widoczne dopiero po oddaniu pracy.
Pierwszy program i konsola
JavaScript to język, który przeglądarka wykonuje na stronie. Program to lista instrukcji wykonywanych po kolei, od góry do dołu. W tej części kursu uczysz się samego języka, bez strony z arkusza, a wyniki oglądasz w konsoli.
console.log
Instrukcja console.log(...) wypisuje w konsoli to, co podasz w nawiasach. W przeglądarce konsolę otwierasz klawiszem F12. W tym kursie jest pod podglądem.
console.log("Dzień dobry"); // tekst zawsze w cudzysłowie
console.log(2026); // liczba bez cudzysłowu
console.log(2 + 3); // najpierw obliczenie, potem wypisanie: 5
Trzy zasady zapisu
- Każdą instrukcję kończysz średnikiem.
- Wielkość liter ma znaczenie:
console.logdziała,Console.Lognie. - Wszystko po
//do końca linii to komentarz. Przeglądarka go pomija, a Tobie pomaga pamiętać, co robi kod.
Zmienne i typy danych
Zmienna to nazwane miejsce na wartość. Dzięki niej raz zapisaną wartość możesz wielokrotnie odczytywać i zmieniać.
let punkty = 60; // let: wartość można później zmienić
punkty = 75; // zmiana, już bez słowa let
const przedmiot = "INF.03"; // const: wartość stała, zmiana kończy się błędem
Znak = nie oznacza równości, tylko przypisanie: wartość z prawej strony trafia do zmiennej po lewej.
Trzy podstawowe typy
| Typ | Przykład | Do czego |
|---|---|---|
liczba (number) | 75, 3.5 | obliczenia; ułamki zapisujesz z kropką |
tekst (string) | "INF.03" | napisy, zawsze w cudzysłowie |
wartość logiczna (boolean) | true, false | odpowiedź tak lub nie |
Typ wartości sprawdzisz przez typeof: typeof 75 daje "number", a typeof "75" daje "string". Cudzysłów zmienia liczbę w tekst.
Nazwy zmiennych
Nazwa nie może mieć spacji ani zaczynać się od cyfry. Kilka słów łączysz wielką literą w środku: liczbaPunktow. Egzamin wymaga nazw znaczących, więc cenaBiletu jest dobra, a x nie.
let przy tej samej zmiennej („already been declared”), zmiana wartości const oraz użycie zmiennej, zanim została utworzona.Operatory, obliczenia i sklejanie tekstu
Działania na liczbach
7 + 2 // 9
7 - 2 // 5
7 * 2 // 14
7 / 2 // 3.5
7 % 2 // 1, reszta z dzielenia
Kolejność jest taka jak w matematyce: najpierw mnożenie i dzielenie, potem dodawanie. Nawiasy ją zmieniają.
Skróty
let licznik = 0;
licznik++; // zwiększ o 1
licznik += 5; // zwiększ o 5, to samo co: licznik = licznik + 5
Plus skleja teksty
Gdy po którejś stronie plusa stoi tekst, plus nie dodaje, tylko skleja.
"Do zapłaty: " + 120 + " zł" // "Do zapłaty: 120 zł"
"5" + "10" // "510", a nie 15
Tekst na liczbę
Wszystko, co użytkownik wpisze w formularzu, przychodzi jako tekst. Przed dodawaniem zamień to na liczbę.
Number("5") + Number("10") // 15
"5" * "10" daje 50. Tylko plus skleja. Dlatego błąd wychodzi dopiero przy dodawaniu.Funkcje: parametry i wynik
Funkcja to nazwany fragment kodu, który możesz uruchamiać wiele razy z różnymi danymi. Na egzaminie cały skrypt składa się z funkcji podpiętych pod przyciski.
function poleProstokata(a, b) { // a i b to parametry
return a * b; // return oddaje wynik
}
poleProstokata(3, 4); // wywołanie, wynik: 12
const pole = poleProstokata(5, 2); // wynik można zapisać w zmiennej
- Definicja (słowo
function) tylko opisuje, co funkcja robi. Kod w klamrach wykona się dopiero przy wywołaniu. - Parametry to zmienne, które dostają wartości podane w nawiasach przy wywołaniu, w tej samej kolejności.
- return kończy funkcję i oddaje wartość. Funkcja bez
returnoddajeundefined.
Wypisać a zwrócić
console.log pokazuje wartość w konsoli i nic więcej. return przekazuje ją dalej, do miejsca wywołania. Ćwiczenia w tej części sprawdzają to, co funkcja zwraca.
poleProstokata to sama funkcja, nie jej wynik), kod napisany po return (nigdy się nie wykona) oraz console.log zamiast return.Funkcje strzałkowe
Funkcję można zapisać krócej, ze strzałką =>. Taki zapis spotkasz w wielu rozwiązaniach arkuszy, zwłaszcza tam, gdzie funkcję przekazuje się dalej: do addEventListener, setTimeout albo metod tablic.
// zwykła funkcja
function poleProstokata(a, b) {
return a * b;
}
// ta sama funkcja jako strzałkowa
const poleProstokata = (a, b) => {
return a * b;
};
// skrót: jedno wyrażenie po strzałce jest od razu wynikiem
const poleProstokata = (a, b) => a * b;
Zasady zapisu
- Funkcję strzałkową zapisuje się w zmiennej, najczęściej
const. Nazwa zmiennej jest nazwą funkcji, a wywołanie wygląda tak samo:poleProstokata(3, 4). - Jeden parametr nie potrzebuje nawiasów:
const podwoj = x => x * 2; - Bez parametrów zostają puste nawiasy:
const losuj = () => Math.random(); - Bez klamr wynik wyrażenia jest zwracany sam, bez
return. Z klamrami trzeba napisaćreturn, tak jak w zwykłej funkcji. Klamry są potrzebne, gdy w funkcji jest kilka instrukcji.
const powitanie = imie => "Cześć, " + imie + "!";
const pokazWynik = (punkty) => {
const tekst = "Wynik: " + punkty;
document.getElementById("wynik").innerHTML = tekst;
};
Gdzie się przydaje
Najczęściej jako krótka funkcja wpisana od razu w miejscu, w którym jest potrzebna, bez wymyślania nazwy:
przycisk.addEventListener("click", () => {
licznik++;
});
setTimeout(() => alert("Minęły 3 sekundy"), 3000);
ceny.forEach(cena => console.log(cena + " zł"));
Czym się różni od zwykłej funkcji
- Kolejność w kodzie. Zwykłą funkcję (
function) można wywołać wyżej w skrypcie, niż jest zapisana. Funkcji strzałkowej wconstnie: trzeba ją najpierw zdefiniować. - Brak własnego
this. W funkcji strzałkowej podpiętej pod zdarzeniethisnie wskazuje klikniętego elementu. Gdy go potrzebujesz, użyj zwykłej funkcji albo parametru zdarzenia:(e) => e.target. - Atrybut
onclickdziała z obiema.<button onclick="pokazWynik(10)">wywoła też funkcję strzałkową zapisaną wconst.
oblicz”, to const oblicz = () => { … }; spełnia to wymaganie tak samo jak function oblicz() { … }. Wybierz zapis, w którym rzadziej się mylisz.Warunki: if, else i porównania
Instrukcja if wykonuje kod tylko wtedy, gdy warunek jest prawdziwy. else obsługuje przypadek przeciwny.
if (punkty >= 75) {
wynik = "zdane";
} else {
wynik = "niezdane";
}
Porównania
| Zapis | Znaczenie |
|---|---|
== | równe |
!= | różne |
<, > | mniejsze, większe |
<=, >= | mniejsze lub równe, większe lub równe |
Spotkasz też ===. Działa jak ==, ale dodatkowo wymaga tego samego typu: 5 == "5" jest prawdą, a 5 === "5" fałszem.
Więcej niż dwa przypadki
if (liczba > 0) {
opis = "dodatnia";
} else if (liczba < 0) {
opis = "ujemna";
} else {
opis = "zero";
}
Łączenie warunków
&& znaczy „i” (oba warunki muszą być prawdziwe), || znaczy „lub” (wystarczy jeden), ! znaczy „nie”.
if (wiek >= 18 && wiek < 26) { ... }
= w warunku. if (punkty = 75) niczego nie porównuje, tylko wpisuje 75 do zmiennej i warunek zawsze jest prawdziwy.Pętle: for i while
Pętla powtarza ten sam kod wiele razy. Używasz jej, gdy coś trzeba zrobić dla każdej liczby z zakresu albo dla każdego elementu listy.
for: znana liczba powtórzeń
for (let i = 1; i <= 5; i++) {
console.log(i); // wypisze 1, 2, 3, 4, 5
}
W nawiasie są trzy części rozdzielone średnikami: początek licznika, warunek dalszego działania i zmiana licznika po każdym obrocie.
Zbieranie wyniku
Typowy schemat: przed pętlą tworzysz zmienną na wynik, w pętli ją powiększasz, po pętli jej używasz.
let suma = 0;
for (let i = 1; i <= 5; i++) {
suma += i;
}
// suma == 15
Tak samo zbiera się tekst: zaczynasz od pustego "" i doklejasz kolejne kawałki.
while: do skutku
let liczba = 40;
while (liczba > 1) {
liczba = liczba / 2;
}
while działa, dopóki warunek jest prawdziwy. Pasuje wtedy, gdy nie wiesz z góry, ile będzie obrotów.
for pilnuj trzeciej części (i++), w while zmiany zmiennej z warunku.Tablice
Tablica przechowuje wiele wartości pod jedną nazwą, w ustalonej kolejności. Elementy mają numery (indeksy) liczone od zera.
const wyniki = [80, 45, 92];
wyniki[0] // 80, pierwszy element
wyniki[2] // 92, ostatni
wyniki.length // 3, liczba elementów
wyniki[1] = 50; // zmiana drugiego elementu
wyniki.push(77); // dopisanie na końcu
Przejście po wszystkich elementach
for (let i = 0; i < wyniki.length; i++) {
console.log(wyniki[i]);
}
Licznik zaczyna od 0, a warunek to i < length, bez znaku równości. Ostatni element ma indeks o jeden mniejszy od długości.
Szukanie największej wartości
let najwieksza = wyniki[0];
for (let i = 1; i < wyniki.length; i++) {
if (wyniki[i] > najwieksza) {
najwieksza = wyniki[i];
}
}
i <= wyniki.length (sięga o jeden element za daleko i dostajesz undefined), liczenie od 1 (pomija pierwszy element) oraz literówka lenght, która po cichu daje undefined.Obiekty
Obiekt łączy w jedną całość kilka nazwanych wartości opisujących tę samą rzecz. W tablicy do wartości sięgasz po numerze, w obiekcie po nazwie pola.
const uczen = {
imie: "Ola",
klasa: "4T",
oceny: [5, 4, 3]
};
uczen.imie // "Ola"
uczen.oceny[0] // 5, pole może być tablicą
uczen.klasa = "5T"; // zmiana pola
Tablica obiektów
Dane z plików JSON na egzaminie mają zwykle tę postać: lista rekordów, z których każdy jest obiektem.
const uczniowie = [
{ imie: "Ola", klasa: "4T" },
{ imie: "Jan", klasa: "4P" }
];
uczniowie[1].imie // "Jan"
uczniowie.length // 2
undefined. Jeśli na stronie pojawia się napis „undefined”, sprawdź literówkę w nazwie pola i wielkość liter.Ten sam zapis poznasz dokładniej w lekcji 11, na danych z arkusza „Strefa pacjenta”.
Teksty i ich metody
Tekst ma własne metody, czyli funkcje wywoływane po kropce. Większość z poniższych jest w tabeli dołączanej do arkusza.
const tekst = "Egzamin INF.03";
tekst.length // 14, liczba znaków
tekst[0] // "E", pierwszy znak
tekst.toUpperCase() // "EGZAMIN INF.03"
tekst.toLowerCase() // "egzamin inf.03"
tekst.indexOf("INF") // 8, pozycja fragmentu albo -1, gdy go nie ma
tekst.substring(0, 7) // "Egzamin", znaki od pozycji 0 do 7 (bez 7)
tekst.replace("INF", "EE") // "Egzamin EE.03"
Żadna z tych metod nie zmienia oryginału. Każda zwraca nowy tekst, który trzeba gdzieś zapisać albo od razu użyć.
Czy tekst coś zawiera
if (adres.indexOf("@") != -1) {
// w adresie jest małpa
}
tekst.length() z nawiasami (długość to pole, nie metoda), toUpperCase bez nawiasów (dostajesz funkcję zamiast tekstu) oraz oczekiwanie, że tekst.toUpperCase(); sam zmieni zmienną.Szukanie błędów
Na egzaminie nikt nie powie Ci, która linijka jest zła. Umiejętność znalezienia własnego błędu jest warta tyle samo co umiejętność pisania kodu. Są dwa rodzaje błędów i szuka się ich inaczej.
Błędy, które przeglądarka zgłasza
| Komunikat | Co zwykle znaczy |
|---|---|
SyntaxError: Unexpected token | brak nawiasu, klamry, cudzysłowu albo przecinka w pobliżu wskazanej linii |
ReferenceError: x is not defined | literówka w nazwie zmiennej lub funkcji albo brak jej deklaracji |
TypeError: Cannot read properties of null | getElementById nie znalazło elementu: zła nazwa id albo skrypt wykonał się przed wczytaniem strony |
TypeError: x is not a function | literówka w nazwie metody albo nawiasy przy czymś, co funkcją nie jest |
Błędy, których przeglądarka nie zgłasza
Kod działa, ale wynik jest zły. Wtedy wstaw console.log w kilku miejscach i porównaj wartości z tym, czego się spodziewasz.
console.log("suma przed pętlą:", suma);
console.log("element", i, "=", ceny[i]);
Słowa NaN i undefined w wyniku to wskazówki. undefined oznacza odczyt czegoś, co nie istnieje: element spoza tablicy, pole z literówką. NaN oznacza obliczenie na czymś, co nie jest liczbą, bardzo często właśnie na undefined.
= zamiast == w warunku, <= zamiast < w pętli po tablicy oraz literówka lenght. Żaden nie wyświetla komunikatu.Strona jako drzewo: szukanie i zmiana elementów
Przeglądarka zamienia kod HTML na drzewo obiektów, zwane DOM. Skrypt nie zmienia pliku HTML, tylko te obiekty, a przeglądarka od razu pokazuje efekt. Każda praca ze stroną zaczyna się od znalezienia elementu.
| Metoda | Zwraca | Kiedy |
|---|---|---|
document.getElementById("tytul") | jeden element | element ma id; podajesz je bez # |
document.querySelector(".opis") | pierwszy pasujący element | szukasz selektorem CSS: klasa, znacznik, zagnieżdżenie |
document.querySelectorAll("#ksiazki li") | listę wszystkich pasujących | chcesz zmienić albo policzyć wiele elementów |
Zmiana treści
document.getElementById("tytul").innerHTML = "Nowy tytuł";
Lista elementów
Wynik querySelectorAll zachowuje się jak tablica: ma length i indeksy od zera. Własności ustawiasz każdemu elementowi osobno, w pętli.
const pozycje = document.querySelectorAll("#ksiazki li");
pozycje.length // ile jest pozycji
pozycje[0] // pierwsza pozycja
for (let i = 0; i < pozycje.length; i++) {
pozycje[i].style.color = "navy";
}
Zdarzenia: co uruchamia funkcję
Zdarzenie to coś, co dzieje się na stronie: kliknięcie, najechanie kursorem, zmiana wartości pola. W atrybucie o nazwie zdarzenia wpisujesz wywołanie funkcji, a przeglądarka uruchomi je we właściwej chwili.
| Atrybut | Kiedy działa | Lekcje z arkuszy |
|---|---|---|
onclick | kliknięcie dowolnego elementu, nie tylko przycisku | 1, 8, 14 |
onmouseover, onmouseout | kursor wchodzi na element, kursor z niego schodzi | 24 |
onchange | zmieniła się wartość pola, listy albo suwaka | 20 |
onfocusout | użytkownik opuścił pole | 31 |
onload na body | strona skończyła się wczytywać | 16, 21 |
Przekazywanie danych do funkcji
<button onclick="zmien(1)">+</button> <!-- liczba -->
<button onclick="pokaz('2.jpg')">2</button> <!-- tekst w pojedynczych cudzysłowach -->
<li onclick="zaznacz(this)">Lalka</li> <!-- this: kliknięty element -->
Jedna funkcja z parametrem zastępuje kilka prawie identycznych. this przydaje się, gdy ten sam atrybut stoi na wielu elementach i funkcja ma działać na tym, który kliknięto.
Stan między zdarzeniami
Jeśli funkcja ma pamiętać coś od poprzedniego kliknięcia (licznik, numer zdjęcia, czyj ruch), zmienna musi stać poza funkcją.
let licznik = 0;
function zmien(krok) {
licznik += krok;
}
Formularze: odczyt, obliczenie, komunikat
Prawie co drugi arkusz ma formularz i przycisk, który coś oblicza. Schemat jest zawsze ten sam: odczytaj kontrolki, sprawdź dane, policz, wypisz wynik w ustalonym formacie.
| Kontrolka | Jak odczytać | Co dostajesz |
|---|---|---|
| pole tekstowe, liczbowe, suwak | pole.value | zawsze tekst |
lista rozwijana select | lista.value | tekst wybranej opcji albo jej atrybut value |
pole wyboru checkbox | pole.checked | true albo false |
pola opcji radio | pole.checked każdego z osobna | true tylko dla zaznaczonego |
Kolejność w funkcji
function oblicz() {
const imie = document.getElementById("imie").value;
const dni = Number(document.getElementById("dni").value);
const wynik = document.getElementById("wynik");
if (imie == "" || dni <= 0) { // 1. walidacja
wynik.innerHTML = "Uzupełnij dane";
return;
}
let stawka = 2; // 2. wartość domyślna
if (document.getElementById("film").checked) {
stawka = 5; // i jej zmiana
}
const koszt = dni * stawka; // 3. obliczenie
wynik.innerHTML = imie + " płaci " + koszt + " zł"; // 4. komunikat
}
Pola opcji nadpisują wartość (wybrana jest jedna). Pola wyboru ją modyfikują (każde niezależnie): dodają kwotę przez += albo naliczają zniżkę. Samym odczytem listy rozwijanej, pól opcji i pól wyboru zajmuje się lekcja P19.
Wygląd: style, widoczność i klasy
Skrypt zmienia wygląd na dwa sposoby: ustawia pojedynczą właściwość CSS albo podmienia klasę, do której w arkuszu stylów przypisano cały zestaw reguł.
Pojedyncza właściwość
element.style.backgroundColor = "Salmon"; // background-color
element.style.fontSize = 18 + "px"; // liczba zawsze z jednostką
element.style.display = "none"; // znika razem z miejscem
element.style.visibility = "hidden"; // znika, miejsce zostaje
Nazwa z myślnikiem zmienia się w zapis z wielką literą w środku. Wartość jest tekstem.
Przełącznik
Gdy jeden przycisk ma na zmianę pokazywać i ukrywać, potrzebna jest zmienna pamiętająca stan. Odczyt element.style.display nie wystarcza, bo nie widzi reguł z pliku CSS.
let widoczny = false;
function przelacz() {
widoczny = !widoczny; // wykrzyknik odwraca wartość
if (widoczny) {
panel.style.display = "block";
} else {
panel.style.display = "none";
}
}
Klasa zamiast wielu właściwości
element.className = "noc"; // nadaj klasę
element.className = ""; // zdejmij
display (9, 24), visibility (15), szerokość paska (31), filtry (32).Tworzenie i usuwanie elementów
Skrypt może dopisywać do strony nowe elementy i usuwać istniejące. Tak działają listy zadań, koszyki, galerie i okna czatu z arkuszy.
Dodanie elementu
const pozycja = document.createElement("li"); // 1. utwórz
pozycja.innerHTML = "Solaris"; // 2. wypełnij
document.getElementById("lista").appendChild(pozycja); // 3. wstaw na koniec rodzica
Dopóki nie wywołasz appendChild, element istnieje tylko w pamięci i nie widać go na stronie.
Element z przyciskiem
pozycja.innerHTML = tytul + ' <button onclick="usun(this)">Usuń</button>';
Usuwanie
function usun(przycisk) {
przycisk.parentElement.remove(); // usuwa pozycję listy, w której stoi przycisk
}
document.getElementById("lista").innerHTML = ""; // usuwa wszystko z wnętrza listy
Licznik po każdej zmianie
Liczbę elementów najlepiej policzyć od nowa po każdej zmianie, zamiast prowadzić osobną zmienną, która łatwo się rozjeżdża.
const ile = document.querySelectorAll("#lista li").length;
Od danych do strony
W kilku arkuszach dostajesz gotowe dane w tablicy i masz zbudować z nich fragment strony. Skrypt działa wtedy od razu po wczytaniu, bez kliknięcia, a dobrze napisany nie wymaga zmian, gdy danych przybędzie.
Jeden rekord, jeden blok
const katalog = document.getElementById("katalog");
for (let i = 0; i < ksiazki.length; i++) {
const ksiazka = ksiazki[i];
const blok = document.createElement("div");
blok.className = "ksiazka";
blok.innerHTML = "<h4>" + ksiazka.tytul + "</h4><p>" + ksiazka.autor + "</p>";
katalog.appendChild(blok);
}
Pętla idzie do length, nigdy do wpisanej liczby. Zmienna pomocnicza ksiazka skraca zapis i zmniejsza liczbę literówek.
Warunek wewnątrz pętli
if (ksiazka.dostepna == false) {
blok.className = "ksiazka brak"; // dwie klasy rozdzielone spacją
}
Szukanie rekordu
W tablicy obiektów indexOf nie znajdzie rekordu po jednym polu. Przechodzisz pętlą i porównujesz pole.
let znaleziona = null;
for (let i = 0; i < ksiazki.length; i++) {
if (ksiazki[i].tytul == szukanyTytul) {
znaleziona = ksiazki[i];
}
}
if (znaleziona == null) {
// nie ma takiej książki
}
Pamięć przeglądarki, data i liczby losowe
Trzy gotowe narzędzia przeglądarki, które w arkuszach pojawiają się rzadziej, ale zawsze w tej samej postaci.
localStorage: dane, które przetrwają odświeżenie
let wizyty = localStorage.getItem("wizyty"); // tekst albo null przy pierwszym razie
if (wizyty == null) {
wizyty = 0;
}
wizyty = Number(wizyty) + 1; // tekst na liczbę przed dodawaniem
localStorage.setItem("wizyty", wizyty);
Date: bieżąca data
const dzisiaj = new Date();
let dzien = dzisiaj.getDate();
let miesiac = dzisiaj.getMonth() + 1; // miesiące liczone od zera
const rok = dzisiaj.getFullYear();
if (dzien < 10) { dzien = "0" + dzien; } // zero z przodu
if (miesiac < 10) { miesiac = "0" + miesiac; }
Math: losowanie i zaokrąglanie
Math.random() // ułamek od 0 do prawie 1
Math.floor(Math.random() * 6) + 1 // liczba całkowita od 1 do 6
Math.round(2.5) // 3, do najbliższej
Math.floor(2.9) // 2, w dół
Math.ceil(2.1) // 3, w górę
Wzór na losową liczbę całkowitą od 1 do N: pomnóż przez N, zaokrąglij w dół, dodaj 1. Dla indeksu tablicy pomiń dodawanie jedynki.
Math.floor w algorytmie) oraz próby z Math.ceil i Math.round.Lista rozwijana, pola opcji i pola wyboru
Trzy kontrolki służą do wybierania gotowych odpowiedzi. Każdą odczytuje się inaczej, bo każda odpowiada na inne pytanie: lista i pola opcji na „który jeden?”, a pola wyboru na „które z nich?”.
Lista rozwijana: jedna wartość z całej listy
<select id="owoce">
<option value="gruszka">gruszka</option>
<option value="arbuz">arbuz</option>
<option value="banan">banan</option>
</select>
<input type="button" value="Wybierz owoc" onclick="wybierzOwoc()">
<div id="komunikat">Tu informacja o wyborze</div>
function wybierzOwoc() {
let owoce = document.getElementById("owoce").value;
document.getElementById("komunikat").innerHTML = "Kupiłeś " + owoce;
}
Pytasz samą listę, a nie jej opcje. lista.value zwraca atrybut value wybranej opcji. Gdy opcja nie ma tego atrybutu, dostajesz tekst spomiędzy znaczników. Wartość jest zawsze tekstem, więc cenę wpisaną w value zamień przez Number(...).
Pola opcji (radio): zaznaczone jest jedno
<input type="radio" name="owoce" id="jablko" checked> jabłko<br>
<input type="radio" name="owoce" id="gruszka"> gruszka<br>
<input type="radio" name="owoce" id="sliwka"> śliwka<br>
<input type="radio" name="owoce" id="brzoskwinia"> brzoskwinia<br>
Wspólny atrybut name łączy pola w grupę: zaznaczenie jednego odznacza pozostałe. Atrybut checked w HTML ustawia zaznaczenie początkowe. W skrypcie pytasz każde pole osobno o checked, a ponieważ prawdziwe jest tylko jedno, warunki łączysz przez else if:
function wyswietl() {
let jablko = document.getElementById("jablko").checked;
let gruszka = document.getElementById("gruszka").checked;
let sliwka = document.getElementById("sliwka").checked;
if (jablko) document.getElementById("kom").innerHTML = "Kupiłeś jabłko";
else if (gruszka) document.getElementById("kom").innerHTML = "Kupiłeś gruszkę";
else if (sliwka) document.getElementById("kom").innerHTML = "Kupiłeś śliwkę";
else document.getElementById("kom").innerHTML = "Kupiłeś brzoskwinię";
}
Ostatnie pole nie potrzebuje warunku. Skoro żadne z poprzednich nie jest zaznaczone, zostało tylko ono, więc wystarcza samo else.
Pola wyboru (checkbox): każde niezależnie
<input type="checkbox" id="jablko_ch" checked> jabłko<br>
<input type="checkbox" id="gruszka_ch"> gruszka<br>
<input type="checkbox" id="sliwka_ch"> śliwka<br>
Tu zaznaczonych może być kilka pól naraz albo żadne. Dlatego każde pole dostaje własne if, bez else, a odpowiedź zbierasz po kawałku w jednej zmiennej:
function wyswietl_ch() {
let jablko_ch = document.getElementById("jablko_ch").checked;
let gruszka_ch = document.getElementById("gruszka_ch").checked;
let sliwka_ch = document.getElementById("sliwka_ch").checked;
let sklejka = ""; // pusty tekst na początek
if (jablko_ch) sklejka += "jabłko "; // każde if dokleja swój kawałek
if (gruszka_ch) sklejka += "gruszkę ";
if (sliwka_ch) sklejka += "śliwkę ";
document.getElementById("komch").innerHTML = "Kupiłeś " + sklejka;
}
Zmienna sklejka musi zacząć od pustego tekstu "". Bez tego pierwsze += doklei kawałek do undefined. Spacja na końcu każdego kawałka oddziela nazwy od siebie. Gdy nic nie zaznaczono, sklejka zostaje pusta i można to sprawdzić warunkiem sklejka == "".
| Kontrolka | Ile odpowiedzi | Odczyt | Warunki |
|---|---|---|---|
| lista rozwijana | jedna | lista.value | niepotrzebne, wartość jest gotowa |
| pola opcji | jedna | pole.checked każdego pola | if … else if … else |
| pola wyboru | zero lub więcej | pole.checked każdego pola | osobne if i doklejanie przez += |
else if przy polach wyboru. Łańcuch zatrzymuje się na pierwszym zaznaczonym polu i kolejne zaznaczenia przepadają. Odwrotna pomyłka, czyli osobne if przy polach opcji, działa, ale sprawdza niepotrzebnie wszystkie pola.Funkcja i kliknięcie
Na egzaminie JavaScript prawie zawsze działa tak samo: użytkownik klika, przeglądarka wywołuje twoją funkcję, funkcja zmienia coś na stronie. Potrzebujesz do tego trzech rzeczy.
1. Miejsce na skrypt
Kod wpisujesz w znaczniku <script>. Wstaw go tuż przed </body>. Wtedy cała strona jest już wczytana, zanim skrypt ruszy, i każdy element da się znaleźć.
<body>
... cała strona ...
<script>
// tutaj twój kod
</script>
</body>
Możesz też użyć osobnego pliku: <script src="skrypt.js"></script>. Arkusz tego nie narzuca.
2. Funkcja
Funkcja to nazwany kawałek kodu. Sama definicja nic nie robi, kod w klamrach wykona się dopiero po wywołaniu.
function powitaj() {
// instrukcje, każda zakończona średnikiem
}
3. Podpięcie pod kliknięcie
Atrybut onclick w HTML zawiera kod do wykonania po kliknięciu. Wpisujesz tam wywołanie funkcji, czyli nazwę z nawiasami.
<button onclick="powitaj()">Kliknij</button>
onclick="powitaj" bez nawiasów. Strona się wczyta, błędu nie będzie, a kliknięcie nic nie zrobi.Tekst w elemencie zmieniasz przez innerHTML. Najpierw znajdujesz element po id, potem przypisujesz nową treść:
document.getElementById("wynik").innerHTML = "Nowy tekst";
Szukanie elementów na stronie
Zanim cokolwiek zmienisz, musisz wskazać, który element masz na myśli. Arkusz podaje w tabeli sześć metod. W praktyce wystarczą trzy.
| Metoda | Co podajesz | Co dostajesz |
|---|---|---|
document.getElementById("miejsce") | samo id, bez # | jeden element |
document.querySelector("#miejsce") | selektor CSS | pierwszy pasujący element |
document.querySelectorAll("section input") | selektor CSS | listę wszystkich pasujących |
Selektory są te same co w pliku styl.css: #id, .klasa, znacznik, rodzic potomek. To duże ułatwienie, bo nie uczysz się niczego nowego.
// po id
const naglowek = document.getElementById("miejsce");
// pierwszy akapit z klasą opis
const opis = document.querySelector(".opis");
// obraz wewnątrz elementu o id sekcjaRezerwacja
const obraz = document.querySelector("#sekcjaRezerwacja img");
Zmienne
Znaleziony element możesz zapisać w zmiennej. const oznacza wartość, której nie podmienisz na inną. let oznacza wartość, która będzie się zmieniać, na przykład numer zdjęcia.
null, a próba zmiany kończy się błędem „Cannot set properties of null”. Prawie zawsze to literówka w id albo # wpisany do getElementById. Na egzaminie otwórz konsolę klawiszem F12 i przeczytaj błąd.Zmiana treści, atrybutów i stylu
Na znalezionym elemencie możesz zmienić trzy rodzaje rzeczy. W tym arkuszu potrzebne są wszystkie trzy.
Treść
element.innerHTML = "Rzym";Atrybut HTML
obraz.src = "2.jpg";
pole.disabled = true;Styl CSS
przycisk.style.backgroundColor = "DodgerBlue";Atrybuty
Każdy atrybut HTML jest dostępny po kropce: src, alt, value, disabled, checked. Atrybut disabled jest logiczny. Wartość true wyłącza kontrolkę, false ją włącza.
document.getElementById("imie").disabled = true; // pole nieaktywne
document.getElementById("imie").disabled = false; // pole aktywne
Styl
Właściwości CSS z myślnikiem zapisujesz w JS bez myślnika, z wielką literą w środku: background-color to backgroundColor, font-size to fontSize. Wartość zawsze jest tekstem w cudzysłowie.
style.background-color (JS odczyta to jako odejmowanie), disabled = "false" w cudzysłowie (niepusty tekst znaczy „prawda”, więc pole zostanie wyłączone) oraz nazwa koloru bez cudzysłowu.Wiele elementów naraz
Sekcja „Dane rezerwacji” ma pięć kontrolek: pole liczbowe, listę rozwijaną i trzy pola opcji. Można każdej nadać id i napisać pięć linijek. Szybciej jest pobrać wszystkie jednym selektorem i przejść po nich pętlą.
const kontrolki = document.querySelectorAll("#sekcjaRezerwacja input, #sekcjaRezerwacja select");
for (let i = 0; i < kontrolki.length; i++) {
kontrolki[i].disabled = true;
}
Jak czytać pętlę for
let i = 0: licznik startuje od zera, bo elementy listy są numerowane od 0.i < kontrolki.length: pętla działa, dopóki licznik jest mniejszy od liczby elementów.i++: po każdym obrocie licznik rośnie o 1.kontrolki[i]: element o numerzei.
Przecinek w selektorze znaczy „lub”, tak jak w CSS. Dlatego sekcję trzeba wpisać po obu stronach przecinka. Selektor "#sekcjaRezerwacja input, select" złapałby listy rozwijane z całej strony.
document.querySelectorAll("input").disabled = true. Lista nie ma własności disabled, więc nic się nie stanie i nie zobaczysz nawet błędu. Wyłączać trzeba każdy element osobno, w pętli.Funkcje uczestnika i rezerwacji
Masz już wszystkie klocki. Każda z dwóch funkcji robi cztery rzeczy: ustawia dwa kolory i przełącza dwie grupy kontrolek. Obie są swoim lustrzanym odbiciem.
| uczestnik() | rezerwacja() | |
|---|---|---|
| Przycisk „Uczestnik” | DodgerBlue | SkyBlue |
| Przycisk „Rezerwacja” | SkyBlue | DodgerBlue |
| Kontrolki sekcji 1 | disabled = false | disabled = true |
| Kontrolki sekcji 2 | disabled = true | disabled = false |
Funkcja z parametrem oszczędza pisanie
Pętla wyłączająca i włączająca różni się tylko selektorem i wartością. Zamiast pisać ją cztery razy, napisz jedną funkcję pomocniczą z dwoma parametrami.
function ustawKontrolki(selektor, czyWylaczone) {
const kontrolki = document.querySelectorAll(selektor);
for (let i = 0; i < kontrolki.length; i++) {
kontrolki[i].disabled = czyWylaczone;
}
}
ustawKontrolki("#sekcjaKlient input", true); // wyłącza pola klienta
ustawKontrolki("#sekcjaKlient input", false); // włącza je z powrotem
Stan początkowy to HTML i CSS, nie skrypt
Arkusz wymaga, żeby po wczytaniu strony „Uczestnik” był DodgerBlue, a kontrolki sekcji 2 nieaktywne. Zrób to od razu w kodzie strony: atrybut disabled na kontrolkach i kolor tła przycisku w stylu.
<input type="number" id="osoby" min="1" max="4" value="2" disabled>
/* styl.css */
#btnUczestnik { background-color: DodgerBlue; }
Karuzela w przód
Strzałka „»” ma pokazać następne zdjęcie i następne miasto. Skrypt musi więc pamiętać, które zdjęcie jest teraz na ekranie. Do tego służą tablice i jedna zmienna z numerem.
Tablice
const obrazy = ["1.jpg", "2.jpg", "3.jpg"];
const miejsca = ["Barcelona", "Rzym", "Londyn"];
let numer = 0; // 0 to Barcelona, 1 to Rzym, 2 to Londyn
Obie tablice mają tę samą kolejność, więc obrazy[numer] i miejsca[numer] zawsze do siebie pasują. Te trzy linijki stoją poza funkcjami. Zmienna utworzona wewnątrz funkcji przy każdym kliknięciu startowałaby od zera.
Krok w przód z zawinięciem
function nastepny() {
numer++; // 0 → 1 → 2 → 3
if (numer > 2) { // 3 nie istnieje
numer = 0; // wracamy na początek
}
document.getElementById("obraz").src = obrazy[numer];
document.getElementById("miejsce").innerHTML = miejsca[numer];
}
To samo krócej zapisuje się resztą z dzielenia: numer = (numer + 1) % 3;. Dla 2 daje to 3 % 3, czyli 0. Wybierz zapis, który rozumiesz. Na egzaminie liczy się działanie.
Karuzela w tył
Strzałka „«” robi krok wstecz. Arkusz podaje kolejność: Barcelona, Londyn, Rzym, Barcelona. Z pierwszego zdjęcia trzeba więc przeskoczyć na ostatnie.
function poprzedni() {
numer--; // 0 → -1
if (numer < 0) { // -1 nie istnieje
numer = 2; // przeskok na ostatni
}
pokazWycieczke();
}
(numer - 1) % 3 dla zera daje w JavaScript -1, a nie 2. Poprawny zapis to (numer + 2) % 3. Jeśli nie masz pewności, użyj if.Wspólny kod do osobnej funkcji
Dwie ostatnie linijki obu funkcji są identyczne. Wydziel je i wywołuj z obu miejsc. Obie strzałki muszą też korzystać z tej samej zmiennej numer, inaczej przód i tył się rozjadą.
function pokazWycieczke() {
document.getElementById("obraz").src = obrazy[numer];
document.getElementById("miejsce").innerHTML = miejsca[numer];
}
Strzałki w HTML
Arkusz wymaga znacznika <span>, a znaki specjalne podaje w tabeli 2. onclick działa na każdym elemencie, nie tylko na przycisku.
<span onclick="poprzedni()">«</span>
<img id="obraz" src="1.jpg" alt="wycieczka">
<span onclick="nastepny()">»</span>
<h4 id="miejsce">Barcelona</h4>
Cały skrypt z arkusza, od zera
Edytor jest pusty. Napisz wszystkie cztery funkcje tak, jak na egzaminie. Dobry wynik to komplet testów w kwadrans bez podglądania rozwiązania. Kod strony znajdziesz w rozwijanym polu pod zadaniem.
Przed oddaniem pracy sprawdź
- Każdy
onclickma nazwę funkcji z nawiasami i ta sama nazwa jest w skrypcie. - Id w HTML i w skrypcie są identyczne, łącznie z wielkością liter.
- Po wczytaniu strony „Uczestnik” jest DodgerBlue, a kontrolki sekcji 2 są nieaktywne.
- Trzy kliknięcia „»” wracają do Barcelony. Jedno kliknięcie „«” na starcie pokazuje Londyn.
- Konsola przeglądarki (F12) nie pokazuje czerwonych błędów.
- Nazwy zmiennych i funkcji coś znaczą.
- Plik
przeglądarka.txtzawiera nazwę przeglądarki, w której testowałeś stronę.
Który element kliknięto: this
Karta produktu ma trzy miniatury. Kliknięcie każdej ma wstawić jej obraz w miejsce obrazu głównego. Trzy osobne funkcje byłyby stratą czasu. Wystarczy jedna, jeśli funkcja dowie się, którą miniaturę kliknięto.
this w atrybucie onclick
Wewnątrz atrybutu onclick słowo this oznacza element, na którym ten atrybut stoi, czyli właśnie kliknięty. Przekazujesz go do funkcji w nawiasach, a funkcja odbiera go jako parametr.
<img src="fotel1.png" alt="miniatura" class="miniatury" onclick="zmienObraz(this)">
<img src="fotel2.png" alt="miniatura" class="miniatury" onclick="zmienObraz(this)">
<img src="fotel3.png" alt="miniatura" class="miniatury" onclick="zmienObraz(this)">
function zmienObraz(miniatura) {
// miniatura to ten obrazek, który kliknięto
document.getElementById("glowny").src = miniatura.src;
}
Do tej pory atrybuty tylko ustawiałeś. Tutaj miniatura.src stoi po prawej stronie znaku równości, więc jest odczytywany. Jedna linijka czyta źródło z miniatury i wpisuje je do obrazu głównego.
Drugi sposób: nazwa pliku jako tekst
<img src="fotel2.png" class="miniatury" onclick="zmienObraz('fotel2.png')">
function zmienObraz(plik) {
document.getElementById("glowny").src = plik;
}
Też jest poprawny. Zwróć uwagę na cudzysłowy: atrybut jest w podwójnych, więc tekst w środku musi być w pojedynczych.
this w samej funkcji bez przekazania go w onclick. Przy onclick="zmienObraz()" słowo this wewnątrz funkcji nie wskazuje miniatury i this.src da undefined.Pokazywanie i ukrywanie: display
Okno z dużym obrazem jest na stronie przez cały czas, tylko ukryte. Arkusz pisze o klasie okno: „element jest usunięty”, a w tabeli 2 podaje, że tak działa display: none. Skrypt ma tę jedną właściwość przełączać.
Stan początkowy w styl.css
.okno {
background-color: rgba(0, 0, 0, 0.7);
width: 80%;
position: fixed;
left: 0;
top: 0;
z-index: 1;
display: none;
}Przełączanie w skrypcie
// pokaż
document.getElementById("okno").style.display = "block";
// ukryj
document.getElementById("okno").style.display = "none";Arkusz wymaga dokładnie tego: otwarcie przez „zmianę sposobu wyświetlania bloku okna na blokowy”, zamknięcie przez „zastosowanie odpowiedniej właściwości CSS”. Nie używaj więc visibility ani usuwania elementu z dokumentu.
Bez id też się da
Treść zadania narzuca klasy, a id dodajesz samodzielnie. Jeśli nie chcesz dopisywać id, sięgnij po element przez klasę:
document.querySelector(".okno").style.display = "block";
element.style widzi tylko style wpisane w atrybucie style albo ustawione wcześniej przez skrypt. Reguły z pliku styl.css tam nie ma. Zaraz po wczytaniu strony okno.style.display jest pustym tekstem, a nie "none". Warunek if (okno.style.display == "none") przy pierwszym kliknięciu nie zadziała. W tym arkuszu masz dwie osobne funkcje, więc żadnego warunku nie potrzebujesz.Okno z obrazem
Funkcja otwierająca okno robi dwie rzeczy, obie wypisane w arkuszu: zmienia sposób wyświetlania bloku okna na blokowy i przypisuje obrazowi w oknie źródło obrazu głównego.
Budowa okna w HTML
<img id="glowny" class="obraz" src="fotel1.png" alt="fotel" onclick="otworzOkno()">
<div class="okno" id="okno">
<span class="zamknij" onclick="zamknijOkno()">×</span>
<img class="obrazOkno" id="obrazOkno">
</div>
Obraz w oknie nie ma atrybutu src. Tak każe arkusz („obraz bez źródła”), bo źródło wpisuje dopiero skrypt.
Dlaczego kopiować źródło, a nie wpisać nazwę pliku
Obraz główny zmienia się po kliknięciu miniatury. Gdyby funkcja miała na stałe "fotel1.png", okno zawsze pokazywałoby pierwszy fotel. Dlatego czytasz źródło z obrazu głównego w chwili kliknięcia.
function otworzOkno() {
const obrazGlowny = document.getElementById("glowny");
document.getElementById("okno").style.display = "block";
document.getElementById("obrazOkno").src = obrazGlowny.src;
}
function zamknijOkno() {
document.getElementById("okno").style.display = "none";
}
obrazGlowny.src = obrazOkno.src czyści obraz główny), onclick na bloku okna zamiast na obrazie głównym oraz to samo id nadane dwóm elementom. Id musi być na stronie jedno, klasa może się powtarzać.Cały skrypt karty produktu, od zera
Edytor jest pusty. Napisz trzy funkcje: podmieniającą obraz główny, otwierającą okno i zamykającą okno. Kod strony z nazwami funkcji i id znajdziesz w rozwijanym polu pod zadaniem. Dobry wynik to komplet testów w pięć minut.
Przed oddaniem pracy sprawdź
- Każda z trzech miniatur podmienia obraz główny na swój.
- Po wczytaniu strony okno jest niewidoczne.
- Okno pokazuje ten fotel, który aktualnie jest obrazem głównym, także po zmianie miniaturą.
- Znak × zamyka okno, a kursor nad nim zmienia się na pointer.
- Nazwy klas są dokładnie takie jak w arkuszu:
obraz,miniatury,okno,obrazOkno,zamknij. - Konsola przeglądarki (F12) nie pokazuje czerwonych błędów.
Dane w obiekcie i tablicy
W arkuszu 06 budujesz konto pacjenta. Skrypt nie reaguje tu na kliknięcia. Uruchamia się raz, przy wczytaniu strony, i z gotowych danych generuje bloki recept. Dane dostajesz w pliku dane.json i kopiujesz je do skryptu.
dane.json. Nazwę zmiennej (pacjenci) nadajesz na egzaminie samodzielnie.const pacjenci = {
"id": "1",
"imie": "Agnieszka",
"nazwisko": "Nowak",
"wystawca": "lek. Marian Kowal",
"numer": "4387203",
"recepty": [
{ "id": "0", "data": "8.03.2025", "kod": "1220", "lek1": "Witamina C", "lek2": "Potas", "lek3": "Syrop prawoślazowy" },
{ "id": "1", "data": "23.04.2025", "kod": "4634", "lek1": "APAP", "lek2": "Witamina B", "lek3": "" },
{ "id": "2", "data": "13.05.2025", "kod": "2913", "lek1": "Melatonina", "lek2": "", "lek3": "" },
{ "id": "3", "data": "30.10.2025", "kod": "1105", "lek1": "Witamina C", "lek2": "Calcium", "lek3": "Sinupret" }
]
};
Jak to czytać
- Klamry
{ }to obiekt, czyli zestaw nazwanych pól. Do pola sięgasz po kropce:pacjenci.imie. - Nawiasy kwadratowe
[ ]to tablica. Elementy mają numery od zera:pacjenci.recepty[0]to pierwsza recepta. - Każdy element tablicy
receptyjest obiektem, więc kropki i nawiasy łączysz w łańcuch.
pacjenci.recepty.length // 4, liczba recept
pacjenci.recepty[0].data // "8.03.2025"
pacjenci.recepty[1].lek2 // "Witamina B"
pacjenci.recepty[2].lek2 // "" czyli pusty tekst, leku nie ma
JSON a JavaScript
Plik JSON wygląda prawie jak kod JS. Różnica: w JSON nazwy pól są w cudzysłowach ("data": "8.03.2025"). Taki zapis jest w JavaScript poprawny, więc treść pliku wklejasz po znaku równości bez zmian. Do pól i tak sięgasz po kropce, bez cudzysłowów.
Tworzenie elementów w skrypcie
Sekcja prawa2 jest w HTML pusta. Bloki recept mają powstać w skrypcie. Tabela w arkuszu podaje do tego dwie metody: createElement i appendChild.
Trzy kroki na każdy element
// 1. utwórz element (na razie istnieje tylko w pamięci)
const blok = document.createElement("div");
// 2. ustaw mu klasę i treść
blok.className = "recepty";
// 3. wstaw go do strony, na koniec wybranego rodzica
document.getElementById("prawa2").appendChild(blok);
Elementy zagnieżdżasz tak samo. Akapit i nagłówek wstawiasz do bloku, a blok do sekcji.
const akapit = document.createElement("p");
akapit.innerHTML = "Data wystawienia: " + recepta.data;
blok.appendChild(akapit);
Znak + skleja teksty. Pamiętaj o spacji po dwukropku wewnątrz cudzysłowu, bo arkusz podaje treść „Data wystawienia: ” ze spacją.
appendChild (element powstaje, ale nie widać go na stronie), blok.class = "recepty" zamiast className oraz document.appendChild(blok) przepisane z tabeli arkusza. Wstawiać trzeba do konkretnego rodzica, nie do document.Drugi sposób: sklejanie HTML
Ten sam wynik da zbudowanie tekstu ze znacznikami i wpisanie go przez innerHTML. Jest krócej, ale łatwiej zgubić cudzysłów albo znacznik zamykający. Oba sposoby są na egzaminie poprawne.
document.getElementById("prawa2").innerHTML +=
'<div class="recepty"><p>Data wystawienia: ' + recepta.data + '</p></div>';
Pętla po receptach i pomijanie pustych leków
Arkusz zastrzega, że do tablicy recepty mogą zostać dopisane nowe elementy i skrypt ma to uwzględnić. Nie wolno więc wpisać liczby 4. Pętla ma iść do recepty.length.
for (let i = 0; i < pacjenci.recepty.length; i++) {
const recepta = pacjenci.recepty[i];
// tutaj budujesz jeden blok dla tej recepty
}
Lista leków z warunkiem
Recepta ma najwyżej trzy leki w polach lek1, lek2, lek3. Pusty wpis nie może trafić na listę. Najprościej zebrać trzy pola w małą tablicę i przejść po niej drugą pętlą.
const lista = document.createElement("ol");
const leki = [recepta.lek1, recepta.lek2, recepta.lek3];
for (let j = 0; j < leki.length; j++) {
if (leki[j] != "") {
const pozycja = document.createElement("li");
pozycja.innerHTML = leki[j];
lista.appendChild(pozycja);
}
}
blok.appendChild(lista);
Lista numerowana to <ol>, nie <ul>. Wewnętrzna pętla ma własny licznik j, żeby nie zepsuć licznika i pętli zewnętrznej.
<li> zawsze, także dla pustych leków. Na stronie widać wtedy numer bez nazwy i punkt za skrypt przepada. Bez tablicy też się da: trzy osobne warunki if (recepta.lek2 != "").Kolejność w bloku
Arkusz wymaga w każdym bloku trzech rzeczy w tej kolejności: paragraf „Data wystawienia: …”, lista numerowana leków, nagłówek czwartego stopnia „Kod: …”. Kolejność wywołań appendChild decyduje o kolejności na stronie.
Cały skrypt konta pacjenta
W edytorze są tylko dane, tak jak po skopiowaniu ich z pliku dane.json. Dopisz skrypt, który w sekcji prawa2 wygeneruje blok dla każdej recepty. Dobry wynik to komplet testów w dziesięć minut.
Przed oddaniem pracy sprawdź
- Bloków jest tyle, ile elementów tablicy
recepty, a pętla kończy się nalength. - Każdy blok ma klasę
recepty. - W bloku są kolejno: paragraf z datą, lista
<ol>, nagłówek<h4>z kodem. - Listy mają tyle pozycji, ile recepta ma niepustych leków.
- Skrypt stoi na końcu
<body>, bo działa od razu po wczytaniu i potrzebuje gotowej sekcjiprawa2. - Nazwy zmiennych coś znaczą, a konsola (F12) nie pokazuje błędów.
Stan gry w zmiennej i warunek if
Arkusz 07 to plansza do gry w kółko i krzyżyk. Każde kliknięcie obrazu wywołuje tę samą funkcję, a funkcja musi wiedzieć, czyj jest ruch. Tę wiedzę trzyma jedna zmienna zadeklarowana poza funkcją. Arkusz nazywa to „aktualnym graczem”.
let aktualnyGracz = "kolko"; // stan początkowy: zaczyna kółko
if i else
Funkcja sprawdza zmienną i wykonuje jedną z dwóch gałęzi. Na końcu każdej gałęzi zmienia gracza na przeciwnego.
function ruch(pole) {
if (aktualnyGracz == "kolko") {
pole.src = "o.png";
aktualnyGracz = "krzyzyk";
} else {
pole.src = "x.png";
aktualnyGracz = "kolko";
}
}
Kliknięty obraz trafia do funkcji przez this, tak jak miniatury w lekcji 8: <img src="nic.png" onclick="ruch(this)">.
==). Jeden znak (=) to przypisanie. Zapis if (aktualnyGracz = "kolko") nie zgłosi błędu, tylko za każdym razem ustawi kółko i warunek zawsze będzie prawdziwy.Zamiast tekstu możesz użyć wartości logicznej, na przykład let ruchKolka = true; i zmiany przez ruchKolka = !ruchKolka;. Oba sposoby są poprawne, byle nazwa mówiła, co zmienna przechowuje.
Zajęte pola i właściwość visibility
Brak akcji na zajętym polu
Arkusz wymaga, żeby kliknięcie w pole z kółkiem lub krzyżykiem nic nie robiło. Funkcja musi więc najpierw sprawdzić, jaki obraz jest w klikniętym polu.
function ruch(pole) {
if (pole.getAttribute("src") != "nic.png") {
return; // pole zajęte: kończymy funkcję od razu
}
// dalej zwykły ruch
}
Słowo return przerywa funkcję. Cała reszta kodu wykona się tylko dla pustego pola, a gracz się nie zmieni.
pole.src zwraca pełny adres, na przykład file:///C:/.../nic.png. Porównanie pole.src == "nic.png" jest wtedy zawsze fałszywe. Użyj pole.getAttribute("src"), które zwraca dokładnie to, co wpisano w HTML, albo pole.src.endsWith("nic.png").Ukryty, ale zajmuje miejsce
Arkusz pisze o sekcji prawej: „blok jest niewidoczny (ukryty)”. To właściwość visibility. Element z visibility: hidden znika, ale jego miejsce zostaje puste i układ strony się nie przesuwa. display: none z lekcji 9 usuwa element razem z miejscem, więc plansza skakałaby na boki.
document.getElementById("lewa").style.visibility = "hidden"; // ukryj
document.getElementById("prawa").style.visibility = "visible"; // pokaż
Stan początkowy ustawiasz w styl.css: sekcja prawa ma visibility: hidden. Sekcje w arkuszu nie mają narzuconych id, nadajesz je samodzielnie.
Cała plansza do gry, od zera
Edytor jest pusty. Napisz zmienną z aktualnym graczem i funkcję ruch(pole). Rozstrzygania wygranej arkusz nie wymaga.
Przed oddaniem pracy sprawdź
- Każdy z dziewięciu obrazów ma
onclickz tą samą funkcją ithis. - Zaczyna kółko, a po wczytaniu strony widać tylko „Gra kółko”.
- Znaki pojawiają się na zmianę, a napis po bokach zawsze wskazuje gracza, który ma teraz ruch.
- Klik w zajęte pole nie zmienia obrazu, napisu ani kolejki.
Licznik wejść: localStorage i onload
W arkuszu 08 skrypt to jedna funkcja licznik w osobnym pliku skrypty.js. Ma liczyć wyświetlenia strony. Zwykła zmienna znika przy każdym odświeżeniu, więc liczbę trzeba zapisać w pamięci przeglądarki.
localStorage
localStorage.setItem("liczbaWejsc", 5); // zapis pod wybraną nazwą
let liczba = localStorage.getItem("liczbaWejsc"); // odczyt: "5" (tekst!)
let brak = localStorage.getItem("cosInnego"); // null, bo nic takiego nie zapisano
Dwie rzeczy decydują o tym, czy licznik działa:
- Pierwsze wejście. Nic jeszcze nie zapisano, więc
getItemzwracanull. Trzeba to zamienić na zero. - Tekst zamiast liczby. localStorage przechowuje wyłącznie tekst.
"1" + 1daje"11", a nie 2. Przed dodawaniem zamień tekst na liczbę przezNumber(...)alboparseInt(...).
function licznik() {
let liczbaWejsc = localStorage.getItem("liczbaWejsc");
if (liczbaWejsc == null) {
liczbaWejsc = 0;
}
liczbaWejsc = Number(liczbaWejsc) + 1;
localStorage.setItem("liczbaWejsc", liczbaWejsc);
// na koniec wypisz liczbę w paragrafie stopki
}
Wywołanie przy załadowaniu strony
Arkusz wymaga, żeby funkcja ruszała „w momencie załadowania się” obu stron. Służy do tego zdarzenie onload na znaczniku body. Plik skryptu podłączasz w obu plikach HTML.
<head>
<script src="skrypty.js"></script>
</head>
<body onload="licznik()">
licznik() wprost w pliku podłączonym w head (paragraf jeszcze nie istnieje) oraz plik skryptu podłączony tylko na jednej z dwóch stron.Lista zamówień: dodawanie, czyszczenie, alert
Arkusz 09 to strona restauracji z trzema skryptami. Kliknięcie bloku z potrawą dopisuje jej nazwę do listy, „Wyczyść” opróżnia listę, a „Zatwierdź” pokazuje komunikat i też opróżnia listę.
Skrypt 1: nazwa z klikniętego bloku
Blok potrawy zawiera obraz i paragraf z nazwą. Blok przekazujesz przez this, a paragrafu szukasz już tylko wewnątrz niego. querySelector działa na dowolnym elemencie, nie tylko na document.
<div class="potrawa" onclick="dodaj(this)">
<img src="nalesniki.webp" alt="Naleśniki">
<p>Naleśniki</p>
</div>
function dodaj(blok) {
const nazwa = blok.querySelector("p").innerHTML; // paragraf w TYM bloku
const pozycja = document.createElement("li");
pozycja.innerHTML = nazwa;
document.getElementById("lista").appendChild(pozycja);
}
document.querySelector("p") zwróciłby pierwszy paragraf na całej stronie, czyli zawsze tę samą potrawę. Dlatego szukasz od blok.
Skrypt 2: czyszczenie listy
document.getElementById("lista").innerHTML = "";
Pusty tekst w innerHTML usuwa wszystkie elementy z wnętrza listy. Sama lista <ul> zostaje na stronie.
Skrypt 3: alert i czyszczenie
function zatwierdz() {
alert("Zamówienie zostało przekazane do realizacji");
wyczysc(); // funkcję ze skryptu 2 można wywołać w innej funkcji
}
Trzy skrypty restauracji, od zera
Edytor jest pusty. Napisz funkcje dla bloków potraw i dla obu przycisków. Nazwy funkcji znajdziesz w kodzie strony pod zadaniem.
Przed oddaniem pracy sprawdź
- Każdy z sześciu bloków ma
onclicki dopisuje własną nazwę, nie cudzą. - Lista w HTML jest pusta: sam znacznik
<ul>bez elementów. - „Wyczyść” nie pokazuje alertu, „Zatwierdź” pokazuje go z treścią z arkusza.
- Po zatwierdzeniu lista jest pusta.
Podmiana zawartości bloku danymi z tablic
Arkusz 11 to atlas drzew. W pliku do_strony.txt dostajesz dwie tablice: nazwy drzew i ich opisy. Nazwa i opis tego samego drzewa stoją pod tym samym indeksem. Kliknięcie obrazu ma wyczyścić blok główny i wstawić do niego nagłówek z nazwą oraz paragraf z opisem.
const nazwyDrzew = ["buk", "lipa", "wierzba", "brzoza", "dąb", "kasztanowiec", "jarzębina", "klon", "magnolia"];
const opisyDrzew = ["Buk ma gładką...", "Lipa kwitnie...", "Wierzba rośnie...", /* i tak dalej, dziewięć opisów */];
nazwyDrzew[0] // "buk"
opisyDrzew[0] // opis buka
Skąd funkcja wie, które drzewo kliknięto
Najprościej przekazać numer w onclick. Pierwszy obraz dostaje 0, drugi 1 i tak dalej, w tej samej kolejności co tablice.
<img src="buk.jpg" alt="buk" onclick="pokazDrzewo(0)">
<img src="lipa.jpg" alt="lipa" onclick="pokazDrzewo(1)">
Trzy kroki funkcji
function pokazDrzewo(numer) {
const blokGlowny = document.getElementById("glowny");
blokGlowny.innerHTML = ""; // 1. usuń starą zawartość
const naglowek = document.createElement("h2"); // 2. nagłówek z nazwą
naglowek.innerHTML = nazwyDrzew[numer];
blokGlowny.appendChild(naglowek);
// 3. tak samo paragraf z opisem i klasą opis
}
Arkusz mówi wprost o „elementach DOM”, więc użyj createElement i appendChild z lekcji 12. Klasę nadajesz przez className.
innerHTML = "" każde kliknięcie dopisuje kolejne drzewo pod poprzednim.Wartość z pola tekstowego i szukanie w tablicy
Co wpisał użytkownik
Treść pola formularza siedzi we właściwości value, nie w innerHTML.
const wpisanaNazwa = document.getElementById("szukane").value;
Czy taka nazwa jest w tablicy
Metoda indexOf zwraca numer, pod którym wartość stoi w tablicy. Gdy jej nie znajdzie, zwraca -1.
nazwyDrzew.indexOf("lipa") // 1
nazwyDrzew.indexOf("akacja") // -1, nie ma
Znaleziony numer to dokładnie ten, którego potrzebuje funkcja z poprzedniej lekcji. Arkusz sam podpowiada, że można ją tu wykorzystać.
function szukajDrzewa() {
const wpisanaNazwa = document.getElementById("szukane").value;
const numer = nazwyDrzew.indexOf(wpisanaNazwa);
if (numer != -1) {
pokazDrzewo(numer);
} else {
// wpisz do bloku głównego komunikat z arkusza
}
}
if (numer) uzna zero za fałsz i buka nigdy nie znajdzie. Porównuj z -1.Bez indexOf też się da: pętla po tablicy z warunkiem if (nazwyDrzew[i] == wpisanaNazwa). Komunikat o braku drzewa przepisz z arkusza dokładnie, z kropką na końcu.
Suwak, pola opcji i obliczenia
Arkusz 12 to salon rowerowy z trzema skryptami. Dwa pierwsze pracują na formularzu: suwak przepisuje wartość do pola liczbowego, a przycisk oblicza rozmiar ramy.
Skrypt 1: suwak zmienia pole
Suwak to <input type="range">. Zdarzenie onchange uruchamia się po puszczeniu suwaka, a oninput już w trakcie przesuwania. Arkusz wymaga wywołania „po zmianie wartości”, więc oba spełniają warunek.
<input type="range" id="suwak" min="100" max="220" value="150" onchange="przepiszWzrost()">
function przepiszWzrost() {
document.getElementById("wzrost").value = document.getElementById("suwak").value;
}
Skrypt 2: które pole opcji jest zaznaczone
Pole opcji ma właściwość checked, która jest true albo false. Ustawiasz współczynnik domyślny i zmieniasz go, gdy zaznaczone jest inne pole.
let wspolczynnik = 0.26; // górski
if (document.getElementById("szosa").checked) {
wspolczynnik = 0.3;
}
if (document.getElementById("trekking").checked) {
wspolczynnik = 0.28;
}
Liczby
- W kodzie ułamki pisze się z kropką. Arkusz podaje „0,26” i „2,54”, w skrypcie to
0.26i2.54. valuezawsze jest tekstem. Zamień je na liczbę:Number(pole.value).Math.round(liczba)zaokrągla do najbliższej liczby całkowitej.
const wzrost = Number(document.getElementById("wzrost").value);
const rozmiar = Math.round(wzrost * wspolczynnik / 2.54);
0,26 to dla JS dwie osobne wartości), sprawdzanie value pola opcji zamiast checked oraz tekst wyniku inny niż w arkuszu. Wymagany format to „Zalecany rozmiar ramy to: 15 cali”.Dzisiejsza data w formacie DD.MM.RRRR
Trzeci skrypt arkusza 12 działa po załadowaniu strony i wpisuje do komórki tabeli aktualną datę.
const dzisiaj = new Date(); // obiekt z bieżącą datą i godziną
dzisiaj.getDate() // dzień miesiąca: 1 do 31
dzisiaj.getMonth() // miesiąc liczony od zera: 0 to styczeń, 11 to grudzień
dzisiaj.getFullYear() // rok, cztery cyfry
getMonth() trzeba powiększyć o 1, inaczej październik wyjdzie jako 9. Dzień miesiąca daje getDate(), bo getDay() zwraca dzień tygodnia.Zero z przodu
Format DD.MM wymaga dwóch cyfr, czyli 08.03, a nie 8.3. Dla liczb mniejszych od 10 doklejasz zero.
let dzien = dzisiaj.getDate();
if (dzien < 10) {
dzien = "0" + dzien;
}
To samo robisz z miesiącem, a potem sklejasz całość kropkami: dzien + "." + miesiac + "." + rok. Funkcję wywołujesz przez <body onload="...">, tak jak licznik w lekcji 16.
Trzy skrypty salonu rowerowego, od zera
Edytor jest pusty. Napisz funkcję suwaka, funkcję liczącą rozmiar ramy i funkcję wypisującą datę.
Przed oddaniem pracy sprawdź
- Pola opcji mają ten sam atrybut
name, więc zaznaczyć da się tylko jedno. - Suwak ma wartości 100, 150, 220 i przepisuje wartość do pola liczbowego.
- Wynik ma dokładnie format z arkusza i jest liczbą całkowitą.
- Data ma zera wiodące i poprawny miesiąc.
Wybór figury i obliczenie pola
Arkusz „Pola figur płaskich” ma dwa skrypty. Pierwszy podmienia duży obraz po kliknięciu małego. Drugi liczy pole, a o tym, którą figurę liczyć, decyduje obraz widoczny w tej chwili na stronie.
Skrypt 1: mały obraz ustawia duży
Mały obraz 1m.bmp ma ustawić duży na 1d.bmp, a 2m.bmp na 2d.bmp. Najprościej przekazać docelową nazwę pliku w onclick, tak jak w lekcji 8.
<img class="figura" src="1m.bmp" alt="Wybierz trójkąt" onclick="ustawFigure('1d.bmp')">
<img class="figura" src="2m.bmp" alt="Wybierz prostokąt" onclick="ustawFigure('2d.bmp')">
function ustawFigure(plik) {
document.getElementById("duzy").src = plik;
}
Skrypt 2: stan strony zamiast zmiennej
W kółku i krzyżyku stan gry trzymała zmienna. Tutaj stan jest już zapisany na stronie: wystarczy sprawdzić, jaki plik ma duży obraz. Arkusz wymaga też, żeby obliczenia działały przed pierwszym kliknięciem. Wtedy na stronie jest 1d.bmp, czyli trójkąt, więc jedno sprawdzenie załatwia oba przypadki.
const bokA = Number(document.getElementById("bokA").value);
const bokB = Number(document.getElementById("bokB").value);
let pole = bokA * bokB / 2; // trójkąt
if (document.getElementById("duzy").getAttribute("src") == "2d.bmp") {
pole = bokA * bokB; // prostokąt
}
obraz.src zwraca pełny adres, więc porównuj przez getAttribute("src") albo sprawdzaj końcówkę: obraz.src.endsWith("2d.bmp").Arkusz nie narzuca formatu wyniku, wystarczy liczba w paragrafie pod przyciskiem. Wartości z pól zamień na liczby przez Number(...). Mnożenie zadziała i bez tego, ale przy dodawaniu teksty by się skleiły.
Dziesięć obrazów z jednej pętli
W arkuszu „Stylizacja paznokci” skrypt 1 ma wyświetlić za pomocą pętli obrazy od 1.jpg do 10.jpg. Każdy ma klasę wzory i dymek z numerem. Dziesięć znaczników wpisanych ręcznie w HTML nie spełnia wymagania, bo oceniana jest pętla.
Licznik pętli jako część nazwy
Tym razem pętla zaczyna od 1 i kończy na 10 włącznie, bo takie są numery plików. Liczba sklejona z tekstem daje tekst: 3 + ".jpg" to "3.jpg".
const blokWzorow = document.getElementById("obrazyWzorow");
for (let i = 1; i <= 10; i++) {
const obraz = document.createElement("img");
obraz.src = i + ".jpg";
obraz.className = "wzory";
obraz.title = i; // dymek po najechaniu kursorem
blokWzorow.appendChild(obraz);
}
Dymek to atrybut title. Przeglądarka sama pokazuje jego treść, gdy kursor zatrzyma się na elemencie.
Wersja z document.write
Tabela w arkuszu podaje też document.write. Skrypt wstawiony w HTML dokładnie tam, gdzie mają być obrazy, wypisuje znaczniki w tym miejscu. Ten sposób działa tylko w trakcie wczytywania strony.
<script>
for (let i = 1; i <= 10; i++) {
document.write('<img src="' + i + '.jpg" class="wzory" title="' + i + '">');
}
</script>
0.jpg, którego nie ma), warunek i < 10 (brakuje dziesiątego obrazu) oraz pomylone cudzysłowy przy sklejaniu znacznika w document.write.Zakładki przełączane najechaniem kursora
Skrypt 2 tego arkusza działa po najechaniu kursorem na przycisk, a nie po kliknięciu. Zdarzenie nazywa się onmouseover i podpina się je tak samo jak onclick.
<button id="przycisk1" onmouseover="pokazSekcje(1)">Kolor</button>
<button id="przycisk2" onmouseover="pokazSekcje(2)">Kształt</button>
<button id="przycisk3" onmouseover="pokazSekcje(3)">Wzór</button>
Wyłącz wszystko, włącz jedno
Arkusz opisuje trzy przypadki i w każdym sześć zmian. Wypisane wprost dają osiemnaście linijek. Krócej jest najpierw ustawić wszystkie sekcje i przyciski w stan „nieaktywny”, a potem włączyć tylko tę jedną parę, o którą chodzi.
function pokazSekcje(numer) {
for (let i = 1; i <= 3; i++) {
document.getElementById("sekcja" + i).style.display = "none";
document.getElementById("przycisk" + i).style.backgroundColor = "Crimson";
}
document.getElementById("sekcja" + numer).style.display = "block";
document.getElementById("przycisk" + numer).style.backgroundColor = "Salmon";
}
Id sklejasz z tekstu i numeru: "sekcja" + 2 daje "sekcja2". Dlatego warto nadać elementom id różniące się tylko cyfrą. Wersja z trzema blokami if też jest poprawna, tylko dłuższa.
styl.css: sekcja 1 ma display: block, sekcje 2 i 3 display: none, pierwszy przycisk tło Salmon, pozostałe Crimson. Skrypt ma ten stan odtworzyć po najechaniu na „Kolor”.Dwa skrypty stylizacji paznokci, od zera
Edytor jest pusty. Napisz pętlę generującą obrazy oraz funkcję przełączającą zakładki.
Przed oddaniem pracy sprawdź
- Obrazów jest dokładnie dziesięć, od
1.jpgdo10.jpg, i powstają w pętli. - Każdy obraz ma klasę
wzoryi dymek z numerem. - W każdej chwili widać tylko jedną sekcję i tylko jeden przycisk jest Salmon.
- Przyciski reagują na najechanie kursorem, bez klikania.
Nazwa pliku, komunikat i nowy obraz
W arkuszu „Studio tatuażu” jeden skrypt robi trzy rzeczy po kliknięciu przycisku: ustala nazwę wybranego pliku, pokazuje komunikat z danymi z formularza i dodaje do galerii nowy obraz.
Ścieżka z pola wyboru pliku
Pole <input type="file"> nie zdradza prawdziwej lokalizacji pliku. Arkusz sam podaje, co zwraca jego value: C:\fakepath\fileName.png. Potrzebna jest sama nazwa, czyli część po ostatnim ukośniku wstecznym.
const sciezka = document.getElementById("plik").value; // C:\fakepath\smok.png
const nazwaPliku = sciezka.split("\\").pop(); // smok.png
split("\\")dzieli tekst na kawałki w miejscach ukośnika wstecznego i zwraca tablicę:["C:", "fakepath", "smok.png"].pop()zwraca ostatni element tej tablicy.- Ukośnik wsteczny w kodzie JS trzeba napisać podwójnie, bo pojedynczy rozpoczyna znak specjalny, na przykład
\n.
To samo da się zrobić metodami z tabeli arkusza: sciezka.substr(sciezka.lastIndexOf("\\") + 1).
Komunikat sklejony z trzech wartości
Wybraną opcję listy rozwijanej daje value znacznika select. Format komunikatu arkusz podaje co do znaku.
const kolor = document.getElementById("kolor").value;
const cena = document.getElementById("cena").value;
alert("Wzór: " + nazwaPliku + ", kolor " + kolor + " w cenie " + cena + " zł");
Nowy obraz w galerii
Obraz tworzysz jak w lekcji 12. Źródłem i tekstem alternatywnym ma być nazwa pliku, a klasą miniatury.
const obraz = document.createElement("img");
obraz.src = nazwaPliku;
obraz.alt = nazwaPliku;
obraz.className = "miniatury";
document.getElementById("galeria").appendChild(obraz);
split("\") (błąd składni, bo ukośnik „zjada” cudzysłów), zwykły ukośnik / zamiast wstecznego oraz komunikat ze ścieżką zamiast samej nazwy. Jeśli pliki graficzne leżą w podfolderze, dopisz go tylko do src.Rodzic elementu i przycisk w tworzonym elemencie
Arkusz „Planer zadań” to lista z przyciskiem „Wykonane” przy każdej pozycji. Przycisk ma przekreślić treść swojego elementu listy, a „Dodaj” ma dopisać nową pozycję razem z działającym przyciskiem.
Od przycisku do elementu listy
Funkcja dostaje kliknięty przycisk przez this. Przekreślić trzeba jednak nie przycisk, tylko element li, w którym on stoi. Do elementu nadrzędnego prowadzi właściwość parentElement.
<li>Gimnastyka <button onclick="wykonane(this)">Wykonane</button></li>
function wykonane(przycisk) {
przycisk.parentElement.style.textDecoration = "line-through";
}
Przekreślenie to właściwość CSS text-decoration: line-through, w JS zapisana jako textDecoration.
Nowy element razem z przyciskiem
Nowa pozycja ma zawierać tekst z pola i przycisk, który wywołuje tę samą funkcję. Najprościej wpisać gotowy znacznik przycisku do innerHTML tworzonego elementu.
function dodajZadanie() {
const tresc = document.getElementById("noweZadanie").value;
const element = document.createElement("li");
element.innerHTML = tresc + ' <button onclick="wykonane(this)">Wykonane</button>';
document.getElementById("lista").appendChild(element);
}
this w onclick nowy przycisk nie będzie wiedział, który element przekreślić.Pola wyboru i sumowanie
Pola opcji (radio) pozwalają wybrać jedną rzecz. Pola wyboru (checkbox) można zaznaczyć wszystkie naraz, więc ceny trzeba dodawać. W arkuszu „Kursy komputerowe” każdy zaznaczony kurs powiększa koszt całkowity.
let koszt = 0;
if (document.getElementById("javascript").checked) {
koszt += 3000; // to samo co: koszt = koszt + 3000
}
if (document.getElementById("react").checked) {
koszt += 5000;
}
Warunki są osobne, bez else. Przy polach opcji z lekcji 20 każdy warunek nadpisywał wartość, tutaj każdy ją powiększa.
Rata i długi komunikat
Ratę arkusz każe policzyć najprościej: koszt podzielony przez liczbę rat. Miasto bierzesz z value listy rozwijanej.
const liczbaRat = Number(document.getElementById("raty").value);
const rata = koszt / liczbaRat;
const miasto = document.getElementById("miasto").value;
wynik.innerHTML = "Kurs odbędzie się w " + miasto + ". Koszt całkowity: " + koszt +
" zł. Płacisz " + liczbaRat + " rat po " + rata + " zł";
< > wstawić " + zmienna + ".Walidacja formularza
Walidacja to sprawdzenie danych przed ich użyciem. W arkuszu „Montaż paneli podłogowych” skrypt liczy koszt tylko wtedy, gdy oba pola są wypełnione. W przeciwnym razie wypisuje komunikat.
Czy pole jest puste
Puste pole ma value równe pustemu tekstowi. Dwa warunki łączysz operatorem || („lub”): wystarczy jedno puste pole, żeby dane były złe.
const szerokosc = document.getElementById("szerokosc").value;
const dlugosc = document.getElementById("dlugosc").value;
if (szerokosc == "" || dlugosc == "") {
wynik.innerHTML = "Wprowadź poprawne dane.";
} else {
const pole = szerokosc * dlugosc;
// tutaj koszt według wybranego panelu
}
Sprawdzaj tekst z pola, zanim zamienisz go na liczbę. Number("") daje 0, więc po zamianie nie odróżnisz pustego pola od wpisanego zera.
Inne walidacje z arkuszy
- Dwa identyczne hasła:
if (haslo1 != haslo2) { alert("Podane hasła różnią się"); } - Wymagana zgoda:
if (!document.getElementById("regulamin").checked) { … }. Wykrzyknik odwraca wartość, czyli warunek znaczy „nie zaznaczono”. - Wielkość liter:
tekst.toUpperCase()itekst.toLowerCase()z tabeli arkusza zwracają tekst wielkimi albo małymi literami.
|| to „lub”, && to „i”, ! to „nie”. Pomylenie || z && w tym zadaniu sprawi, że komunikat pojawi się dopiero przy obu pustych polach.Algorytm: liczba dziesiętna na binarną
Arkusz „Pozycyjne systemy liczbowe” podaje algorytm w krokach i każe go zapisać w JavaScript. Dzielisz liczbę przez 2, zapisujesz resztę, powtarzasz aż do zera. Reszty czytane od końca dają zapis dwójkowy.
Pętla while, reszta i dzielenie całkowite
while (warunek) { … }powtarza kod, dopóki warunek jest prawdziwy. Pasuje tu lepiej niżfor, bo nie wiesz z góry, ile będzie obrotów.liczba % 2to reszta z dzielenia przez 2, czyli 0 albo 1.Math.floor(liczba / 2)to wynik dzielenia zaokrąglony w dół.
let liczba = 13;
let binarna = "";
while (liczba > 0) {
binarna = (liczba % 2) + binarna; // nową cyfrę doklejamy Z PRZODU
liczba = Math.floor(liczba / 2);
}
// binarna == "1101"
Algorytm z arkusza każe na końcu odwrócić napis. Doklejanie cyfry z przodu robi to od razu: ostatnia reszta ląduje na początku.
Spacja co cztery cyfry od prawej
Wynik ma być pogrupowany jak 10 0001 1001. Przechodzisz po cyfrach i przed cyfrą wstawiasz spację, gdy do końca zostało ich 4, 8, 12 i tak dalej.
let zeSpacjami = "";
for (let i = 0; i < binarna.length; i++) {
if (i > 0 && (binarna.length - i) % 4 == 0) {
zeSpacjami += " ";
}
zeSpacjami += binarna[i];
}
wynik.innerHTML = zeSpacjami + "<sub>(2)</sub>";
Math.floor (liczba nigdy nie dojdzie do zera i pętla się nie skończy), doklejanie cyfr z tyłu (wynik wychodzi odwrócony) oraz grupowanie od lewej zamiast od prawej.Losowanie z tablicy i okno czatu
W arkuszu „Chat” jeden przycisk dodaje do okna czatu wpisaną wiadomość, a drugi losową odpowiedź z tablicy dziewięciu tekstów.
Losowy indeks
Math.random() zwraca ułamek od 0 do prawie 1. Pomnożony przez liczbę elementów i zaokrąglony w dół daje całkowity indeks od 0 do 8.
const numer = Math.floor(Math.random() * odpowiedzi.length); // 0, 1, … 8
const tekst = odpowiedzi[numer];
Math.round mogłoby dać 9, a takiego indeksu w tablicy nie ma. Wtedy w czacie pojawia się napis undefined.Blok wypowiedzi
Wypowiedź to blok z obrazem i paragrafem. Tworzysz div, nadajesz mu klasę i wpisujesz zawartość przez innerHTML.
const wypowiedz = document.createElement("div");
wypowiedz.className = "jolanta";
wypowiedz.innerHTML = '<img src="Jolka.jpg" alt="Jolanta"><p>' + tekst + '</p>';
document.getElementById("chat").appendChild(wypowiedz);
wypowiedz.scrollIntoView(); // przewiń czat do nowej wypowiedzi
Arkusz wymaga przewinięcia do nowej wypowiedzi, gdy blok czatu jest pełny. Robi to scrollIntoView(). Po wysłaniu warto też wyczyścić pole: pole.value = "";.
Utrata focusa, pasek postępu i konsola
Arkusz „Zarejestruj się w sklepie” ma trzy funkcje. Zakładki znasz z lekcji 24. Nowe są dwie rzeczy: zdarzenie utraty focusa i wypisywanie do konsoli.
Zdarzenie po opuszczeniu pola
Pole „ma focus”, gdy użytkownik w nim pisze. Traci go po kliknięciu gdzie indziej albo po naciśnięciu Tab. Tabela w arkuszu podaje do tego zdarzenie onfocusout (działa też onblur).
<input type="text" id="imie" onfocusout="zwiekszPasek()">
Pasek postępu
Pasek to pusty blok wewnątrz bloku tła. Skrypt zmienia tylko jego szerokość. Aktualną wartość pamięta zmienna poza funkcją, a warunek pilnuje, żeby nie przekroczyć 100.
let szerokoscPaska = 4;
function zwiekszPasek() {
szerokoscPaska += 12;
if (szerokoscPaska > 100) {
szerokoscPaska = 100;
}
document.getElementById("pasek").style.width = szerokoscPaska + "%";
}
Szerokość w CSS wymaga jednostki, dlatego do liczby doklejasz "%". Sama liczba zostałaby zignorowana.
Wypisywanie do konsoli
console.log(imie + ", " + nazwisko + ", " + zgoda);
Wynik console.log widać w narzędziach przeglądarki (F12, karta Konsola). Na egzaminie zrób zrzut z otwartą konsolą, jeśli arkusz tego wymaga. W tym kursie tekst pojawia się w polu „Konsola” pod podglądem.
Filtry CSS ustawiane skryptem
W arkuszu „Efekty na obrazach” skrypt nakłada na obrazy filtry CSS. Wszystkie siedzą w jednej właściwości filter, a jej wartość wygląda jak wywołanie funkcji. Arkusz podaje nazwy filtrów w tabeli.
obraz.style.filter = "blur(5px)"; // rozmycie
obraz.style.filter = "sepia(100%)"; // stara fotografia
obraz.style.filter = "invert(100%)"; // negatyw
obraz.style.filter = "grayscale(100%)"; // odcienie szarości
obraz.style.filter = "none"; // zdjęcie filtra
Wartość z suwaka w środku tekstu
Przezroczystość i jasność mają pochodzić z suwaka. Wartość filtra sklejasz z trzech kawałków: nazwy z nawiasem, liczby i jednostki z nawiasem zamykającym.
const wartosc = document.getElementById("przezroczystosc").value;
obraz.style.filter = "opacity(" + wartosc + "%)"; // np. "opacity(40%)"
Trzy pola opcji, jeden obraz
if (document.getElementById("sepia").checked) {
obraz.style.filter = "sepia(100%)";
}
opacity ustawione jako osobna właściwość zamiast jako filtr oraz filter = "" pomylone z "none" tam, gdzie filtr był nadany w pliku CSS.Okno prompt, przedziały wartości i licznik
Ten arkusz pochodzi ze starszej kwalifikacji EE.09, ale jego skrypt używa rzeczy, które mogą pojawić się w INF.03: okna do wpisania wartości, kolorowania według przedziałów i licznika.
prompt: pytanie do użytkownika
const nowaIlosc = prompt("Podaj nową ilość:"); // zwraca wpisany tekst
document.getElementById("p1").innerHTML = nowaIlosc;
alert tylko wyświetla komunikat. prompt dodatkowo zwraca to, co wpisał użytkownik, zawsze jako tekst.
Trzy przedziały: if, else if, else
Tło komórki zależy od liczby: 0 to kolor czerwony, od 1 do 5 żółty, reszta Honeydew. Łańcuch else if sprawdza warunki po kolei i zatrzymuje się na pierwszym prawdziwym.
const komorka = document.getElementById("p1");
const ilosc = Number(komorka.innerHTML); // treść komórki to tekst
if (ilosc == 0) {
komorka.style.backgroundColor = "red";
} else if (ilosc <= 5) {
komorka.style.backgroundColor = "yellow";
} else {
komorka.style.backgroundColor = "Honeydew";
}
Trzy komórki to trzy takie sprawdzenia. Wpisz ich id do tablicy i przejdź po niej pętlą, tak jak po receptach w lekcji 13.
Licznik zamówień
Numer zamówienia rośnie przy każdym kliknięciu, więc zmienna stoi poza funkcją. Arkusz każe najpierw zwiększyć id, a potem je pokazać.
let idZamowienia = 0;
function zamow(nazwaProduktu) {
idZamowienia++;
alert("Zamówienie nr: " + idZamowienia + " Produkt: " + nazwaProduktu);
}
zaznaczBraki();.Skrypty z pozostałych arkuszy, bez nowych lekcji
Te arkusze nie wymagają niczego, czego nie było w lekcjach. Każda próba to pusty edytor, strona z arkusza i testy. Obok nazwy jest numer lekcji, która przydaje się najbardziej.
| Arkusz | Co robi skrypt | Lekcje | Stan |
|---|
Arkusze z tym samym skryptem
Osiem starszych arkuszy powtarza skrypt, który już jest w kursie, czasem z innymi cenami lub tekstami. Nie mają osobnych prób.
- EE.09-05-20.06 „Salon fryzjerski”: to samo co INF.03-08-24.01, inne ceny.
- EE.09-04-20.06 „Salon kosmetyczny”: to samo co INF.03-05-24.01, inne ceny.
- EE.09-02-19.06 „Stacja paliw”: to samo co INF.03-02-22.06.
- E.14-01-20.06 „Malarz”: to samo co INF.03-01-23.01.
- E.14-05-19.06 „Usługi informatyczne”: to samo co INF.03-01-24.01.
- E.14-06-19.06 „Pogotowie komputerowe”: to samo co INF.03-02-24.01.
- E.14-12-19.01 „Fotografie zwierząt”: to samo co E.14-11-19.01.
- E.14-02-20.01 „Fabryka żelków”: to samo co E.14-03-20.01, inne nazwy kształtów.
Losowy arkusz na czas, bez podpowiedzi
Strona losuje jeden arkusz i włącza stoper. Dostajesz treść zadania, gotową stronę i edytor. Podgląd możesz uruchamiać dowolnie często, tak jak przeglądarkę na egzaminie. Listy wymagań i rozwiązania nie widać, dopóki nie oddasz pracy. Liczy się pierwsze oddanie.
HTML tej strony
Ostatnie podejścia
Nie masz jeszcze żadnego oddanego arkusza.
| Arkusz | Wynik | Czas | Data |
|---|
Quiz o typowych pułapkach
Każde pytanie dotyczy błędu, który na egzaminie zabiera punkty za skrypt. Po kliknięciu odpowiedzi zobaczysz wyjaśnienie.
Tabela z arkusza i składnia w pigułce
Tabelę 1 dostajesz na egzaminie do ręki. Nie musisz znać jej na pamięć. Musisz wiedzieć, który wiersz do czego służy.
| Zapis z arkusza | Do czego | Przykład z tego zadania |
|---|---|---|
document.getElementById(id) | jeden element po id | document.getElementById("obraz") |
document.querySelector(sel) | pierwszy element pasujący do selektora CSS | document.querySelector("h4") |
document.querySelectorAll(sel) | lista wszystkich pasujących, do pętli | document.querySelectorAll("#sekcjaKlient input") |
getElementsByTagName, getElementsByClassName, getElementsByName | też zwracają listę, starszy sposób | document.getElementsByName("wyzywienie") |
element.innerHTML = "wartość" | zmiana treści elementu | naglowek.innerHTML = "Rzym" |
element.attribute_name = "wartość" | zmiana atrybutu HTML | obraz.src = "2.jpg", pole.disabled = true |
element.setAttribute(atrybut, wartosc) | to samo innym zapisem | obraz.setAttribute("src", "2.jpg") |
element.style.property_name = "wartość" | zmiana stylu CSS | przycisk.style.backgroundColor = "SkyBlue" |
onclick | zdarzenie kliknięcia | <span onclick="nastepny()"> |
this w onclick | kliknięty element przekazany do funkcji | <img onclick="zmienObraz(this)"> |
element.style.display | pokazanie i ukrycie elementu (tabela 2 arkusza 03) | okno.style.display = "block", "none" |
| odczyt atrybutu | skopiowanie wartości z jednego elementu do drugiego | obrazOkno.src = obrazGlowny.src |
obiekt.pole, tablica[i] | odczyt danych z obiektu i tablicy (arkusz 06) | pacjenci.recepty[1].kod, pacjenci.recepty.length |
document.createElement(element) | utworzenie nowego elementu w pamięci | const blok = document.createElement("div") |
element.className | nadanie klasy utworzonemu elementowi | blok.className = "recepty" |
appendChild(element) | wstawienie elementu na koniec rodzica; wywołuj na rodzicu, nie na document | sekcja.appendChild(blok) |
element.innerHTML = "" | usunięcie całej zawartości elementu (arkusze 09 i 11) | lista.innerHTML = "" |
element.getAttribute(atrybut) | odczyt atrybutu dokładnie tak, jak wpisano go w HTML | pole.getAttribute("src") == "nic.png" |
element.style.visibility | ukrycie elementu z zachowaniem jego miejsca (arkusz 07) | prawa.style.visibility = "hidden", "visible" |
onload | wywołanie funkcji po załadowaniu strony | <body onload="licznik()"> |
localStorage.getItem, setItem | odczyt i zapis w pamięci przeglądarki; odczyt daje tekst albo null | localStorage.setItem("liczbaWejsc", 3) |
Number(tekst) | zamiana tekstu na liczbę przed obliczeniami | Number(pole.value) |
alert(tekst) | okno z komunikatem | alert("Zamówienie zostało przekazane do realizacji") |
lista.value | wybrana opcja listy rozwijanej select: jej atrybut value albo tekst | document.getElementById("owoce").value |
if … else if / osobne if | pola opcji: jedno zaznaczone, więc łańcuch else if; pola wyboru: każde osobnym if i += | if (jablko_ch.checked) sklejka += "jabłko "; |
pole.value, pole.checked | treść pola formularza; zaznaczenie pola opcji | suwak.value, szosa.checked |
tablica.indexOf(wartość) | numer elementu w tablicy albo -1, gdy go nie ma | nazwyDrzew.indexOf("lipa") |
Math.round(liczba) | zaokrąglenie do liczby całkowitej | Math.round(wzrost * 0.26 / 2.54) |
new Date() | bieżąca data: getDate(), getMonth() + 1, getFullYear() | dzisiaj.getMonth() + 1 |
onmouseover | wywołanie funkcji po najechaniu kursorem na element | <button onmouseover="pokazSekcje(2)"> |
element.title | dymek pokazywany po zatrzymaniu kursora na elemencie | obraz.title = i |
"tekst" + liczba | sklejanie nazwy pliku albo id z licznikiem pętli | i + ".jpg", "sekcja" + numer |
tekst.split(znak).pop() | ostatni kawałek tekstu po podziale, np. nazwa pliku ze ścieżki | sciezka.split("\\").pop() |
lista.value | opcja wybrana w liście rozwijanej select | document.getElementById("kolor").value |
element.parentElement | element nadrzędny, np. pozycja listy, w której stoi kliknięty przycisk | przycisk.parentElement.style.textDecoration = "line-through" |
+= | powiększenie zmiennej, np. suma cen zaznaczonych pól wyboru | koszt += 3000 |
||, &&, ! | lub, i, nie w warunkach; walidacja pustych pól | if (szerokosc == "" || dlugosc == "") |
toUpperCase(), toLowerCase() | tekst wielkimi albo małymi literami | email.toLowerCase() |
while (warunek), %, Math.floor | pętla do skutku, reszta z dzielenia, zaokrąglenie w dół | liczba = Math.floor(liczba / 2) |
Math.ceil(liczba) | zaokrąglenie w górę | Math.ceil(powierzchnia / 4) |
Math.random() | losowy ułamek od 0 do 1; z Math.floor daje losowy indeks tablicy | Math.floor(Math.random() * odpowiedzi.length) |
onfocusout | wywołanie funkcji, gdy pole traci focus | <input onfocusout="zwiekszPasek()"> |
onmouseout | wywołanie funkcji, gdy kursor zjeżdża z elementu | <img onmouseout="podmien('pies1', 'pies1-szary.jpg')"> |
console.log(tekst) | wypisanie w konsoli przeglądarki (F12) | console.log("Witaj " + imie) |
element.style.filter | filtr CSS: blur, sepia, invert, grayscale, opacity, brightness | obraz.style.filter = "opacity(" + wartosc + "%)" |
prompt(tekst) | okno z polem; zwraca wpisany tekst | prompt("Podaj nową ilość:") |
if … else if … else | kilka przedziałów wartości, pierwszy pasujący wygrywa | else if (ilosc <= 5) |
Length. W JavaScript wielkość liter ma znaczenie i poprawnie pisze się length, na przykład kontrolki.length.Składnia w pigułce
// zmienne
const miejsca = ["Barcelona", "Rzym", "Londyn"]; // tablica, numeracja od 0
let numer = 0; // wartość, która się zmienia
// funkcja
function nastepny() {
numer++;
}
// ta sama funkcja jako strzałkowa
const nastepnyNumer = () => numer++;
const podwoj = x => x * 2; // jedno wyrażenie: wynik bez return
// warunek
if (numer > 2) {
numer = 0;
} else {
// w przeciwnym razie
}
// pętla po liście elementów
for (let i = 0; i < kontrolki.length; i++) {
kontrolki[i].disabled = true;
}
// porównania: == != < > <= >= logika: && (i) || (lub) ! (nie)