Temat 15 · 2 × 45 minINF.03
Zmiana stylów, klas i atrybutów
Druga wielka grupa zadań egzaminacyjnych nie liczy nic – zmienia wygląd strony: ukrywa i pokazuje bloki, podmienia obrazek, koloruje aktywny przycisk, nakłada filtr na zdjęcie. W próbie 26 analizowanych zadań z JavaScriptem prawie co drugie wymagało zmiany element.style, a co piąte – pokazania i ukrycia sekcji (te ostatnie wyłącznie w latach 2024–2026). W tej lekcji poznasz trzy narzędzia: właściwość style (pojedyncza cecha), classList (gotowy zestaw cech z CSS) i atrybuty (src, alt, title, setAttribute). Znajdowanie elementów znasz z lekcji 11, zdarzenia z lekcji 12.
element.style – jedna właściwość naraz
Każdy element ma obiekt style, którego pola odpowiadają właściwościom CSS. Przypisanie element.style.color = 'red' działa tak, jakbyś dopisał do znacznika atrybut style="color: red" – czyli styl inline, który wygrywa z arkuszem CSS. Wartości podajesz jako napisy, dokładnie tak, jak pisałbyś je w CSS, razem z jednostką: '16px', '100%', '2px solid black'.
Nazwy z myślnikiem zamieniasz na camelCase: myślnik znika, a następna litera jest wielka.
| CSS | JavaScript | Przykład |
|---|---|---|
color | style.color | p.style.color = 'Navy'; |
background-color | style.backgroundColor | div.style.backgroundColor = '#FFAEA5'; |
font-size | style.fontSize | p.style.fontSize = '20px'; |
font-weight | style.fontWeight | p.style.fontWeight = 'bold'; |
text-decoration | style.textDecoration | li.style.textDecoration = 'line-through'; |
display | style.display | sekcja.style.display = 'none'; |
width | style.width | pasek.style.width = '40%'; |
border | style.border | img.style.border = '3px solid red'; |
filter | style.filter | img.style.filter = 'sepia(100%)'; |
list-style-type | style.listStyleType | ul.style.listStyleType = 'square'; |
Co się stanie po załadowaniu strony z tym skryptem?
var p = document.getElementById('info');
p.style.background-color = 'yellow';<p id="tekst">Ten akapit zmienia wygląd.</p>
<label>Rozmiar [%]: <input type="number" id="rozmiar" value="100" min="50" max="300"></label>
<select id="krój">
<option value="normal">prosty</option>
<option value="italic">kursywa</option>
</select>
<button type="button" onclick="formatuj('red')">czerwony</button>
<button type="button" onclick="formatuj('green')">zielony</button>
<button type="button" onclick="formatuj('blue')">niebieski</button>// jedna funkcja z parametrem zamiast trzech kopii – jak w arkuszu E.14 ze stycznia 2019
function formatuj(kolor) {
const akapit = document.getElementById('tekst');
const rozmiar = document.getElementById('rozmiar').value; // napis, np. "150"
akapit.style.fontSize = rozmiar + '%'; // jednostka doklejona do napisu
akapit.style.fontStyle = document.getElementById('krój').value; // "normal" / "italic"
akapit.style.color = kolor;
}Zwróć uwagę na rozmiar + '%' – bez jednostki (style.fontSize = 150) przeglądarka zignoruje przypisanie (wyjątek: 0 i właściwości bez jednostek jak opacity czy zIndex). Jeśli wolisz zapis z myślnikiem, działa też akapit.style['background-color'] = 'yellow' oraz akapit.style.setProperty('background-color', 'yellow') – ale camelCase jest najkrótszy i tak piszą arkusze.
Pokaż / ukryj – display
Najczęstszy mechanizm w arkuszach 2024–2026: kliknięcie chowa jeden blok i pokazuje drugi. Służy do tego właściwość display: 'none' ukrywa element całkowicie (nie zajmuje miejsca), 'block' pokazuje go jako blok. Dla elementów liniowych (span, img) wracasz do 'inline' lub 'inline-block'; można też przypisać pusty napis '', co usuwa styl inline i przywraca wartość z CSS.
Akapit #p1 ma w CSS kolor niebieski. Co będzie po DRUGIM kliknięciu przycisku?
<button onclick="document.getElementById('p1').style.color = 'red'">Zmień</button>Rotacja cytatów z arkusza INF.03-10-24.06 (kliknięcie cytatu 1 ukrywa go i pokazuje cytat 2, potem 2→3 i 3→1; arkusz dopuszczał jedną funkcję parametrową lub trzy osobne) w jednej funkcji:
<blockquote id="cytat1" onclick="pokazNastepny(1)">1. Kliknij, aby zobaczyć następny cytat.</blockquote>
<blockquote id="cytat2" onclick="pokazNastepny(2)">2. Programowanie to sztuka mówienia komputerowi, czego chcesz.</blockquote>
<blockquote id="cytat3" onclick="pokazNastepny(3)">3. Najpierw spraw, by działało. Potem – by działało dobrze.</blockquote>blockquote { background: #fff8d6; padding: 12px; border-left: 4px solid #15171c; cursor: pointer; }
#cytat2, #cytat3 { display: none; } /* wstępnie ukryte w CSS */function pokazNastepny(numer) {
const nastepny = numer === 3 ? 1 : numer + 1; // zawijanie 3 → 1
document.getElementById('cytat' + numer).style.display = 'none';
document.getElementById('cytat' + nastepny).style.display = 'block';
}Zauważ dwa chwyty: 'cytat' + numer buduje id z liczby (dlatego warto nazywać elementy cytat1, cytat2…), a ukrycie startowe jest w CSS, więc skrypt nadpisuje je stylem inline. To działa, bo styl inline ma pierwszeństwo przed arkuszem.
Alternatywa dla prostego ukrywania: atrybut HTML hidden – element.hidden = true chowa, false pokazuje. Działa jak display: none, ale krócej. Na egzaminie style.display jest bezpieczniejsze, bo bywa, że arkusz wymaga tego wprost („przez zmianę wartości odpowiedniej właściwości CSS”).
Jedna funkcja dla wielu przycisków – zakładki
Klasyk z czerwca 2024 (INF.03-08-24.06) i stycznia 2026 (INF.03-09-26.01): trzy przyciski, trzy sekcje. Kliknięcie (albo najechanie – onmouseover) ukrywa wszystkie sekcje, pokazuje wybraną i koloruje aktywny przycisk. Zamiast trzech funkcji pisz jedną z parametrem – arkusze (np. INF.03-10-24.06, INF.03-08-25.06) wprost dopuszczają jedną funkcję parametrową lub trzy osobne, a jedna to mniej literówek.
Kluczowa sztuczka: najpierw wyłącz wszystko (pętlą lub trzema liniami), potem włącz jedno. Dzięki temu nie musisz pamiętać, co było aktywne wcześniej.
<nav>
<button type="button" id="btn-kolor" onclick="pokazSekcje('kolor')">Kolor</button>
<button type="button" id="btn-ksztalt" onclick="pokazSekcje('ksztalt')">Kształt</button>
<button type="button" id="btn-wzor" onclick="pokazSekcje('wzor')">Wzór</button>
</nav>
<section id="kolor" class="zakladka">Sekcja KOLOR – wybierz lakier.</section>
<section id="ksztalt" class="zakladka">Sekcja KSZTAŁT – migdał, kwadrat, owal.</section>
<section id="wzor" class="zakladka">Sekcja WZÓR – french, ombre, brokat.</section>nav button { background: Crimson; color: white; border: 0; padding: 8px 16px; cursor: pointer; }
.zakladka { display: none; padding: 16px; border: 1px solid #ccc; margin-top: 8px; }
#kolor { display: block; } /* start: pierwsza sekcja widoczna */function pokazSekcje(nazwa) {
// 1. ukryj wszystkie sekcje i „zgaś” wszystkie przyciski
const sekcje = document.querySelectorAll('.zakladka');
for (const sekcja of sekcje) {
sekcja.style.display = 'none';
}
const przyciski = document.querySelectorAll('nav button');
for (const przycisk of przyciski) {
przycisk.style.backgroundColor = 'Crimson';
}
// 2. pokaż wybraną sekcję i podświetl jej przycisk
document.getElementById(nazwa).style.display = 'block';
document.getElementById('btn-' + nazwa).style.backgroundColor = 'Salmon';
}
pokazSekcje('kolor'); // stan początkowy: także przycisk ma właściwy kolorJeśli arkusz żąda reakcji na najechanie, zamieniasz tylko onclick na onmouseover (lub 'click' na 'mouseover' w addEventListener). Gdy nie chcesz nadawać przyciskom id, przekaż do funkcji sam przycisk: onclick="pokazSekcje('kolor', this)" – this w atrybucie to kliknięty element, więc przycisk.style.backgroundColor = 'Salmon'.
classList – gotowy zestaw cech
Gdy zmiana wyglądu to więcej niż jedna właściwość (tło + kolor + ramka + przekreślenie), zamiast pięciu linii style.* zdefiniuj klasę w CSS i dodaj ją ze skryptu. Służy do tego classList:
| Metoda | Co robi | Przykład |
|---|---|---|
classList.add('x') | dodaje klasę (nic nie robi, jeśli już jest) | li.classList.add('wykonane') |
classList.remove('x') | usuwa klasę | img.classList.remove('ramka') |
classList.toggle('x') | dodaje, jeśli nie ma; usuwa, jeśli jest; zwraca true, gdy po operacji klasa jest | body.classList.toggle('ciemny') |
classList.toggle('x', warunek) | wymusza: true = dodaj, false = usuń | img.classList.toggle('ramka', pole.checked) |
classList.contains('x') | sprawdza obecność klasy | if (btn.classList.contains('aktywny')) |
classList.replace('a', 'b') | zamienia jedną klasę na inną | ikona.classList.replace('off', 'on') |
className | cały atrybut class jako napis (odczyt i nadpisanie) | img.className = 'miniatury' |
classList nie zastępuje stylów – przenosi je do CSS, gdzie są czytelniejsze. Przełączanie z toggle jest najkrótszym sposobem na „i tak na zmianę” z arkusza EE.09-07-22.01 (ikona on/off).
Element #box ma klasę karta. Co będzie w jego atrybucie class po wykonaniu kodu?
var box = document.getElementById('box');
box.classList.toggle('aktywna');
box.classList.toggle('aktywna');
box.classList.add('karta');<label><input type="checkbox" id="ramka"> Rysuj ramkę</label>
<button type="button" id="tryb">Tryb nocny</button>
<p id="stan"></p>
<div id="obraz">obraz</div>body.nocny { background: #15171c; color: #eee; }
#obraz { width: 120px; height: 80px; background: #f2d338; display: grid; place-items: center; margin-top: 8px; }
#obraz.ramka { border: 4px solid Navy; }const obraz = document.getElementById('obraz');
const poleRamki = document.getElementById('ramka');
poleRamki.addEventListener('change', () => {
obraz.classList.toggle('ramka', poleRamki.checked); // zaznaczony → dodaj, odznaczony → usuń
});
document.getElementById('tryb').addEventListener('click', () => {
const jestNocny = document.body.classList.toggle('nocny'); // true, gdy klasa dodana
document.getElementById('stan').textContent = jestNocny ? 'Tryb nocny włączony' : 'Tryb dzienny';
});Atrybuty: src, alt, title, setAttribute
Większość atrybutów HTML ma odpowiadającą właściwość elementu o tej samej nazwie: img.src, img.alt, img.title, a.href, input.disabled, input.placeholder. Zapis img.src = '2.jpg' to najprostszy sposób podmiany obrazka – i najczęstszy w arkuszach (galeria 1.jpg…7.jpg, miniatury 1m → 1d).
Uniwersalne metody działają na każdym atrybucie, także własnym (data-*) i takim, który nie ma właściwości:
| Metoda | Przykład |
|---|---|
setAttribute('nazwa', 'wartość') | img.setAttribute('src', 'duzy.jpg') |
getAttribute('nazwa') | img.getAttribute('src') → "duzy.jpg" (dokładnie to, co w HTML) |
removeAttribute('nazwa') | btn.removeAttribute('disabled') |
hasAttribute('nazwa') | if (link.hasAttribute('target')) |
dataset.nazwa | <img data-numer="3"> → img.dataset.numer → "3" |
Różnica między img.src a img.getAttribute('src'): właściwość zwraca pełny adres (http://localhost/galeria/2.jpg), atrybut – dokładnie to, co wpisano (2.jpg). Gdy chcesz sprawdzić, „który obraz jest aktualnie wyświetlony” (styczeń 2026, INF.03-03-26.01), użyj getAttribute('src') albo img.src.includes('1d') – porównanie img.src === '1d.bmp' zawiedzie przez pełny adres.
Na stronie jest <img id='foto' src='kol1.jpg'> i przycisk z atrybutem onclick ustawiającym document.getElementById('foto').src = 'kol2.jpg'. Który obraz będzie widoczny po kliknięciu?
<img id="duzy" alt="duży obraz 1" width="240" height="140">
<p id="opis">Wyświetlany: obraz 1</p>
<img class="miniatura" data-numer="1" alt="miniatura 1" width="60" height="35">
<img class="miniatura" data-numer="2" alt="miniatura 2" width="60" height="35">
<img class="miniatura" data-numer="3" alt="miniatura 3" width="60" height="35">.miniatura { cursor: pointer; border: 2px solid transparent; }
.miniatura.aktywna { border-color: Crimson; }// Na egzaminie masz pliki 1.jpg, 2.jpg… i piszesz: duzy.src = numer + 'd.jpg'
// Tu, bez plików, rysujemy obrazek w locie – ta funkcja to tylko zastępnik plików:
function zrodloObrazka(numer, szerokosc, wysokosc) {
const kolory = ['', 'SteelBlue', 'Olive', 'Indigo'];
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="' + szerokosc + '" height="' + wysokosc + '">' +
'<rect width="100%" height="100%" fill="' + kolory[numer] + '"/>' +
'<text x="50%" y="55%" font-size="' + (wysokosc / 2) + '" fill="white" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif">' + numer + '</text></svg>';
return 'data:image/svg+xml;utf8,' + encodeURIComponent(svg);
}
const duzy = document.getElementById('duzy');
const miniatury = document.querySelectorAll('.miniatura');
// start: miniatury dostają obrazki, duży pokazuje obraz 1
for (const miniatura of miniatury) {
const numer = miniatura.dataset.numer; // "1", "2", "3" – z atrybutu data-numer
miniatura.src = zrodloObrazka(numer, 60, 35); // na egzaminie: numer + 'm.jpg'
miniatura.addEventListener('click', () => pokazDuzy(numer));
}
pokazDuzy(1);
function pokazDuzy(numer) {
duzy.src = zrodloObrazka(numer, 240, 140); // na egzaminie: numer + 'd.jpg'
duzy.alt = 'duży obraz ' + numer;
document.getElementById('opis').textContent = 'Wyświetlany: obraz ' + numer;
for (const m of miniatury) {
m.classList.toggle('aktywna', m.dataset.numer == numer); // == bo "1" vs 1
}
}Filtry CSS sterowane kontrolkami
Arkusz INF.03-12-24.06 kazał nakładać na obrazy filtry CSS z przycisków opcji i suwaków – wyłącznie przez element.style.filter. Wartość filter to napis z jedną lub kilkoma funkcjami oddzielonymi spacją:
| Filtr | Zakres | Efekt |
|---|---|---|
blur(4px) | 0 i więcej px | rozmycie |
sepia(100%) | 0–100 % | odcień sepii |
grayscale(100%) | 0–100 % | czarno-biały |
invert(100%) | 0–100 % | negatyw |
opacity(50%) | 0–100 % | przezroczystość |
brightness(150%) | 0 % i więcej | jasność (100 % = bez zmian) |
none | – | usuwa wszystkie filtry |
<img id="zdjecie" alt="kolorowy gradient" width="240" height="120">
<p>
<label><input type="radio" name="filtr" value="none" checked> Brak</label>
<label><input type="radio" name="filtr" value="blur(4px)"> Rozmycie</label>
<label><input type="radio" name="filtr" value="sepia(100%)"> Sepia</label>
<label><input type="radio" name="filtr" value="invert(100%)"> Negatyw</label>
<button type="button" onclick="zastosujFiltr()">Zastosuj</button>
</p>
<label>Jasność: <input type="range" id="jasnosc" min="0" max="250" value="100"> <span id="jasnoscTekst">100</span>%</label>const zdjecie = document.getElementById('zdjecie');
// zastępnik pliku zdjecie.jpg – kolorowy gradient rysowany w locie
zdjecie.src = 'data:image/svg+xml;utf8,' + encodeURIComponent(
'<svg xmlns="http://www.w3.org/2000/svg" width="240" height="120"><defs><linearGradient id="g">' +
'<stop offset="0" stop-color="#e63946"/><stop offset="0.5" stop-color="#f2d338"/><stop offset="1" stop-color="#2a9d8f"/>' +
'</linearGradient></defs><rect width="100%" height="100%" fill="url(#g)"/></svg>');
function zastosujFiltr() {
const wybrany = document.querySelector('input[name="filtr"]:checked').value; // np. "sepia(100%)"
const jasnosc = document.getElementById('jasnosc').value; // np. "130"
// dwa filtry w jednym napisie, oddzielone spacją
zdjecie.style.filter = wybrany + ' brightness(' + jasnosc + '%)';
}
document.getElementById('jasnosc').addEventListener('input', () => {
document.getElementById('jasnoscTekst').textContent = document.getElementById('jasnosc').value;
zastosujFiltr(); // suwak działa na żywo, bez przycisku
});Przypisanie style.filter = 'sepia(100%)' zastępuje poprzednią wartość – jeśli chcesz dodać efekt do istniejącego, sklej napisy albo trzymaj każdy filtr w osobnej zmiennej i składaj je w jednym miejscu, jak wyżej.
Pętla po kolekcji – zmiana stylu wielu elementów
Pytanie z części pisemnej (EE.09 czerwiec 2022): „co robi pętla po getElementsByClassName?”. Odpowiedź: zmienia styl każdego elementu klasy. Kolekcja sama nie ma style – trzeba przejść po elementach.
<p class="wazne">Pierwszy ważny akapit.</p>
<p>Zwykły akapit.</p>
<p class="wazne">Drugi ważny akapit.</p>
<button type="button" onclick="pogrub()">Pogrub ważne</button>function pogrub() {
var elementy = document.getElementsByClassName('wazne'); // kolekcja – nie ma .style!
for (var i = 0; i < elementy.length; i++) {
elementy[i].style.fontWeight = 'bolder'; // każdy element osobno
elementy[i].style.color = 'Crimson';
}
}Na egzaminie
Ściąga
| Składnia | Co robi | Przykład |
|---|---|---|
el.style.wlasciwosc = 'wartość' | styl inline, camelCase, wartość jako napis z jednostką | p.style.fontSize = '20px' |
el.style.display = 'none' / 'block' / '' | ukryj / pokaż / wróć do CSS | sekcja.style.display = 'block' |
el.hidden = true / false | ukryj / pokaż atrybutem HTML | blok.hidden = true |
el.style.backgroundColor = 'Salmon' | tło (nazwa koloru CSS lub #rrggbb) | aktywny przycisk |
el.style.width = procent + '%' | szerokość paska postępu | pasek.style.width = '36%' |
el.style.filter = 'sepia(100%) blur(2px)' | filtry CSS, kilka po spacji | img.style.filter = 'none' |
getComputedStyle(el).display | wartość wyliczona, także z arkusza CSS | odczyt stanu |
el.classList.add / remove / toggle / contains | zarządzanie klasami | li.classList.add('wykonane') |
el.classList.toggle('x', warunek) | dodaj gdy true, usuń gdy false | img.classList.toggle('ramka', pole.checked) |
el.className = 'a b' | nadpisz cały atrybut class | img.className = 'miniatury' |
img.src = '2.jpg', img.alt, img.title | właściwości = atrybuty | duzy.src = numer + 'd.jpg' |
el.setAttribute('src', 'x.jpg') / getAttribute('src') | dowolny atrybut, dokładna wartość z HTML | sprawdzenie, który obraz jest wyświetlony |
el.removeAttribute('disabled') | usuń atrybut | odblokuj przycisk |
el.dataset.numer | atrybut data-numer | "3" (napis) |
for (const e of kolekcja) e.style.x = … | zmiana stylu wielu elementów | pętla po querySelectorAll |
onclick="f('a', this)" | przekaż kliknięty element do funkcji | this.style.backgroundColor |
Zadania
Wersja dla słabowidzących
Strona ma nagłówek, dwa akapity i dwa przyciski: Większa czcionka (każde kliknięcie zwiększa rozmiar tekstu całej strony – document.body.style.fontSize – o 2 px, startując od 16 px) oraz Kontrast (przełącza klasę kontrast na body: czarne tło, żółty tekst). Pod przyciskami akapit #stan pokazuje aktualny rozmiar, np. Rozmiar: 20px.
Pokaż rozwiązanie
<button type="button" id="wiekszy">Większa czcionka</button>
<button type="button" id="kontrast">Kontrast</button>
<p id="stan">Rozmiar: 16px</p>
<h2>Nasza szkoła</h2>
<p>Zapraszamy na dzień otwarty w sobotę.</p>
<p>Rejestracja w sekretariacie do piątku.</p>body.kontrast { background: black; color: yellow; }let rozmiar = 16; // stan trzymany w zmiennej poza funkcją
document.getElementById('wiekszy').addEventListener('click', () => {
rozmiar += 2;
document.body.style.fontSize = rozmiar + 'px'; // jednostka!
document.getElementById('stan').textContent = 'Rozmiar: ' + rozmiar + 'px';
});
document.getElementById('kontrast').addEventListener('click', () => {
document.body.classList.toggle('kontrast'); // na przemian
});Rezerwacja w trzech krokach
Strona rezerwacja.html zawiera trzy bloki (<div> lub <section>) z formularzem w krokach: blok 1 „Dane” (imię, nazwisko, przycisk „Dalej”), blok 2 „Termin” (pole daty, przycisk „Dalej”), blok 3 „Płatność” (lista: karta / przelew, przycisk „Rezerwuję”). Na starcie widoczny jest tylko blok 1 – bloki 2 i 3 są ukryte w arkuszu CSS.
Skrypt w JavaScript: kliknięcie „Dalej” ukrywa bieżący blok i pokazuje następny, przez zmianę właściwości CSS. Kliknięcie „Rezerwuję” ukrywa blok 3 i w akapicie #podsumowanie pod blokami wypisuje: Rezerwacja dla <imię> <nazwisko> na <data>, płatność: <sposób>. Użyj jednej funkcji z parametrem do przechodzenia między blokami. Stosuj znaczące nazwy.
Kryteria samooceny (0/1):
- JavaScript, funkcja wywoływana przyciskami.
- Na starcie widoczny tylko blok 1 (ukrycie w CSS).
- „Dalej” w bloku 1 ukrywa blok 1 i pokazuje blok 2; w bloku 2 – ukrywa 2 i pokazuje 3 (przez
display). - „Rezerwuję” ukrywa blok 3 i wypisuje podsumowanie z danymi z kontrolek w podanym formacie.
- Funkcja przejścia ma parametr (lub są trzy osobne funkcje).
- Znaczące nazwy.
Pokaż rozwiązanie
<div id="krok1" class="krok">
<h3>1. Dane</h3>
<input type="text" id="imie" placeholder="Imię" value="Ola">
<input type="text" id="nazwisko" placeholder="Nazwisko" value="Nowak">
<button type="button" onclick="przejdzDoKroku(1, 2)">Dalej</button>
</div>
<div id="krok2" class="krok">
<h3>2. Termin</h3>
<input type="date" id="data" value="2026-11-15">
<button type="button" onclick="przejdzDoKroku(2, 3)">Dalej</button>
</div>
<div id="krok3" class="krok">
<h3>3. Płatność</h3>
<select id="platnosc"><option>karta</option><option>przelew</option></select>
<button type="button" onclick="zarezerwuj()">Rezerwuję</button>
</div>
<p id="podsumowanie"></p>.krok { border: 1px solid #ccc; padding: 10px; }
#krok2, #krok3 { display: none; } /* kryterium 2 */// kryterium 5: jedna funkcja z parametrami – skąd i dokąd
function przejdzDoKroku(biezacy, nastepny) {
document.getElementById('krok' + biezacy).style.display = 'none';
document.getElementById('krok' + nastepny).style.display = 'block';
}
function zarezerwuj() {
document.getElementById('krok3').style.display = 'none';
const imie = document.getElementById('imie').value;
const nazwisko = document.getElementById('nazwisko').value;
const data = document.getElementById('data').value; // "2026-11-15"
const platnosc = document.getElementById('platnosc').value;
document.getElementById('podsumowanie').textContent =
'Rezerwacja dla ' + imie + ' ' + nazwisko + ' na ' + data + ', płatność: ' + platnosc;
}Menu z podświetleniem – na najechanie
Strona oferta.html ma trzy bloki nawigacji (<div class="menu"> z tekstem „Kursy”, „Cennik”, „Kontakt”) i trzy sekcje z treścią. Na starcie widoczna jest sekcja „Kursy”, a jej blok menu ma tło LightGreen; pozostałe bloki menu mają tło #2E7D4F i biały tekst.
Skrypt w JavaScript: najechanie myszą na blok menu zmienia jego tło na LightGreen, pozostałym blokom przywraca #2E7D4F, pokazuje odpowiednią sekcję (display: block) i ukrywa pozostałe. Skrypt składa się z jednej funkcji parametrowej lub trzech funkcji, które modyfikują style CSS bloków. Stosuj znaczące nazwy.
Kryteria samooceny (0/1):
- JavaScript, funkcja uruchamiana zdarzeniem najechania (nie kliknięcia).
- Stan początkowy: sekcja „Kursy” widoczna, jej menu
LightGreen, inne#2E7D4F. - Po najechaniu aktywny blok ma tło
LightGreen, pozostałe#2E7D4F– sprawdzane dla dwóch różnych bloków. - Widoczna jest tylko sekcja odpowiadająca najechanemu blokowi.
- Zmiany realizowane przez modyfikację stylów CSS ze skryptu.
- Znaczące nazwy.
Pokaż rozwiązanie
<div class="menu" id="menu-kursy" onmouseover="pokazOferte('kursy')">Kursy</div>
<div class="menu" id="menu-cennik" onmouseover="pokazOferte('cennik')">Cennik</div>
<div class="menu" id="menu-kontakt" onmouseover="pokazOferte('kontakt')">Kontakt</div>
<section id="kursy" class="oferta">Kursy: JavaScript, PHP, SQL.</section>
<section id="cennik" class="oferta">Cennik: od 1200 zł za semestr.</section>
<section id="kontakt" class="oferta">Kontakt: biuro@szkola.example</section>.menu { display: inline-block; padding: 10px 20px; background: #2E7D4F; color: white; cursor: pointer; }
#menu-kursy { background: LightGreen; } /* kryterium 2 */
.oferta { display: none; padding: 12px; }
#kursy { display: block; }function pokazOferte(nazwa) {
const nazwy = ['kursy', 'cennik', 'kontakt'];
for (const n of nazwy) { // wszystkim wyłącz…
document.getElementById('menu-' + n).style.backgroundColor = '#2E7D4F';
document.getElementById(n).style.display = 'none';
}
document.getElementById('menu-' + nazwa).style.backgroundColor = 'LightGreen'; // …jednemu włącz
document.getElementById(nazwa).style.display = 'block';
}Wersja z trzema funkcjami (pokazKursy(), pokazCennik(), pokazKontakt()) też jest akceptowana, ale miałaby trzy razy więcej miejsc na literówkę.
Galeria z aktywną miniaturą
Pod dużym obrazem #duzy są cztery miniatury (<img class="miniatura" data-numer="1"> … 4). Kliknięcie miniatury: podmienia src dużego obrazu na <numer>d.jpg (w placu zabaw użyj funkcji zrodloObrazka z lekcji jako zastępnika plików), ustawia alt na Zdjęcie <numer>, dodaje klikniętej miniaturze klasę aktywna (czerwona ramka), a pozostałym ją usuwa. Dodatkowo przycisk Sprawdź wypisuje w akapicie numer aktualnie wyświetlonego obrazu, odczytany z atrybutu src dużego obrazu (nie ze zmiennej) – użyj getAttribute lub includes.
Pokaż rozwiązanie
<img id="duzy" width="240" height="140" alt="Zdjęcie 1">
<br>
<img class="miniatura" data-numer="1" width="60" height="35" alt="miniatura 1">
<img class="miniatura" data-numer="2" width="60" height="35" alt="miniatura 2">
<img class="miniatura" data-numer="3" width="60" height="35" alt="miniatura 3">
<img class="miniatura" data-numer="4" width="60" height="35" alt="miniatura 4">
<br>
<button type="button" id="sprawdz">Sprawdź</button>
<p id="wynik"></p>.miniatura { cursor: pointer; border: 3px solid transparent; }
.miniatura.aktywna { border-color: red; }// zastępnik plików 1d.jpg…4d.jpg i 1m.jpg…4m.jpg – na egzaminie podajesz zwykłe nazwy plików
function zrodloObrazka(numer, szer, wys) {
const kolory = ['', 'SteelBlue', 'Olive', 'Indigo', 'Crimson'];
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="' + szer + '" height="' + wys + '">' +
'<rect width="100%" height="100%" fill="' + kolory[numer] + '"/>' +
'<text x="50%" y="55%" font-size="' + wys / 2 + '" fill="white" text-anchor="middle" dominant-baseline="middle">' + numer + 'd</text></svg>';
return 'data:image/svg+xml;utf8,' + encodeURIComponent(svg) + '#' + numer + 'd.jpg'; // końcówka ułatwia odczyt numeru
}
const duzy = document.getElementById('duzy');
const miniatury = document.querySelectorAll('.miniatura');
function pokazZdjecie(numer) {
duzy.src = zrodloObrazka(numer, 240, 140); // na egzaminie: duzy.src = numer + 'd.jpg';
duzy.alt = 'Zdjęcie ' + numer;
for (const m of miniatury) {
m.classList.toggle('aktywna', m.dataset.numer === String(numer));
}
}
for (const m of miniatury) {
m.src = zrodloObrazka(m.dataset.numer, 60, 35); // na egzaminie: m.src = numer + 'm.jpg'
m.addEventListener('click', () => pokazZdjecie(m.dataset.numer));
}
pokazZdjecie(1);
document.getElementById('sprawdz').addEventListener('click', () => {
const src = duzy.getAttribute('src'); // dokładna wartość atrybutu
let numer = 0;
for (let i = 1; i <= 4; i++) {
if (src.includes(i + 'd.jpg')) numer = i; // który plik jest w src?
}
document.getElementById('wynik').textContent = 'Wyświetlony obraz: ' + numer;
});Studio efektów
Strona efekty.html zawiera obraz #zdjecie (w placu zabaw: dowolny gradient jako data URI, jak w lekcji) oraz trzy grupy kontrolek:
- przyciski opcji „Sepia” / „Czarno-biały” / „Negatyw” / „Brak” (Brak domyślnie) i przycisk „Zastosuj” – nakłada
sepia(100%),grayscale(100%),invert(100%)albo usuwa filtr; - suwak „Rozmycie” 0–10 – działa na żywo (bez przycisku), dodaje
blur(<wartość>px)do aktualnego filtru z grupy 1; - przyciski „Jaśniej” i „Ciemniej” – każde kliknięcie zmienia jasność o 10 % (start 100 %, nie mniej niż 0 %).
Wszystkie efekty mają działać jednocześnie i wyłącznie przez element.style.filter. Napisz jedną funkcję odswiezFiltr(), która składa trzy części w jeden napis. Stosuj znaczące nazwy.
Kryteria samooceny (0/1):
- JavaScript, funkcje wywoływane zdarzeniami kontrolek.
- Po „Zastosuj” obraz ma filtr zgodny z zaznaczonym radio – dla dwóch różnych opcji.
- Suwak zmienia rozmycie bez klikania przycisku.
- „Jaśniej”/„Ciemniej” zmieniają jasność o 10 %, nie poniżej 0 %.
- Efekty łączą się (np. sepia + rozmycie + jasność jednocześnie).
- Zmiany wyłącznie przez
style.filter; znaczące nazwy.
Pokaż rozwiązanie
<img id="zdjecie" width="240" height="120" alt="gradient">
<p>
<label><input type="radio" name="efekt" value="none" checked> Brak</label>
<label><input type="radio" name="efekt" value="sepia(100%)"> Sepia</label>
<label><input type="radio" name="efekt" value="grayscale(100%)"> Czarno-biały</label>
<label><input type="radio" name="efekt" value="invert(100%)"> Negatyw</label>
<button type="button" onclick="zastosujEfekt()">Zastosuj</button>
</p>
<label>Rozmycie: <input type="range" id="rozmycie" min="0" max="10" value="0"></label>
<button type="button" onclick="zmienJasnosc(10)">Jaśniej</button>
<button type="button" onclick="zmienJasnosc(-10)">Ciemniej</button>
<span id="jasnoscTekst">100%</span>const zdjecie = document.getElementById('zdjecie');
zdjecie.src = 'data:image/svg+xml;utf8,' + encodeURIComponent(
'<svg xmlns="http://www.w3.org/2000/svg" width="240" height="120"><defs><linearGradient id="g">' +
'<stop offset="0" stop-color="#e63946"/><stop offset="0.5" stop-color="#f2d338"/><stop offset="1" stop-color="#2a9d8f"/>' +
'</linearGradient></defs><rect width="100%" height="100%" fill="url(#g)"/></svg>');
// stan trzech części filtru
let efekt = 'none';
let rozmyciePx = 0;
let jasnoscProcent = 100;
function odswiezFiltr() {
// kryterium 5: jeden napis z trzema częściami; 'none' pomijamy, bo unieważniłby resztę
let filtr = '';
if (efekt !== 'none') filtr += efekt + ' ';
filtr += 'blur(' + rozmyciePx + 'px) brightness(' + jasnoscProcent + '%)';
zdjecie.style.filter = filtr;
document.getElementById('jasnoscTekst').textContent = jasnoscProcent + '%';
}
function zastosujEfekt() { // kryterium 2
efekt = document.querySelector('input[name="efekt"]:checked').value;
odswiezFiltr();
}
document.getElementById('rozmycie').addEventListener('input', (zdarzenie) => { // kryterium 3
rozmyciePx = zdarzenie.target.valueAsNumber;
odswiezFiltr();
});
function zmienJasnosc(krok) { // kryterium 4
jasnoscProcent += krok;
if (jasnoscProcent < 0) jasnoscProcent = 0;
odswiezFiltr();
}Test powtórkowy
Test powtórkowy
Format jak w części pisemnej INF.03 – 4 odpowiedzi, 1 poprawna.
Który zapis zmieni kolor tła elementu o id box na żółty?
Aby ukryć blok <div id='reklama'> tak, by nie zajmował miejsca, należy wykonać:
Co zrobi ta pętla w dialekcie egzaminacyjnym?
var elementy = document.getElementsByClassName('styl1');
for (var i = 0; i < elementy.length; i++) {
elementy[i].style.fontWeight = 'bolder';
}Które wywołanie doda klasę aktywny do przycisku btn, nie usuwając jego pozostałych klas?
Element ma klasę on. Co da element.classList.toggle('on') i jaki będzie stan po wywołaniu?
Na stronie jest <img id='ikona' src='off.png'>. Który zapis podmieni obraz na on.png?
Które wywołanie ustawi atrybut title o wartości „Wzór 3” na elemencie img?
Arkusz: „najechanie na blok menu pokazuje sekcję”. Którego zdarzenia użyjesz?
Blok #sekcja2 ma w arkuszu CSS display: none. Co wypisze console.log(document.getElementById('sekcja2').style.display) przed jakimkolwiek kliknięciem?
Który zapis nałoży na obraz jednocześnie sepię i rozmycie 3 px?