Temat 16 · 2 × 45 minINF.03
Tworzenie i usuwanie elementów
Do tej pory zmieniałeś elementy, które już były w HTML. Od czerwca 2024 arkusze INF.03 wymagają więcej: dokleić nową wiadomość do chatu, dodać pozycję do koszyka, wygenerować w pętli dziesięć miniatur, dopisać zadanie do listy razem z przyciskiem, który działa. To wszystko robi się trzema krokami: utwórz element, ustaw mu treść i atrybuty, dołącz do strony. W tej lekcji przejdziesz te kroki, poznasz usuwanie i zamianę elementów oraz napiszesz dwa klasyki egzaminu: chat z losową odpowiedzią i listę zadań. Potrzebujesz pętli (lekcja 6), tablic (lekcja 8) oraz stylów i atrybutów z lekcji 15.
Trzy kroki: utwórz, ustaw, dołącz
document.createElement('p') tworzy nowy, pusty element – istnieje w pamięci, ale nie ma go jeszcze na stronie. Dopóki go gdzieś nie dołączysz, użytkownik nic nie zobaczy. To najczęstszy błąd początkujących: element utworzony, ustawiony, a zapomniane appendChild.
// 1. utwórz
const akapit = document.createElement('p');
// 2. ustaw treść i atrybuty
akapit.textContent = 'Nowa wiadomość';
akapit.className = 'wiadomosc';
// 3. dołącz na koniec rodzica
document.getElementById('chat').appendChild(akapit);Co zobaczy użytkownik po wykonaniu tego kodu?
var li = document.createElement('li');
li.innerHTML = 'Kup mleko';
li.style.color = 'green';<input type="text" id="nowe" placeholder="Nowy produkt" value="mleko">
<button type="button" onclick="dodajProdukt()">Dodaj</button>
<ul id="lista">
<li>chleb</li>
</ul>function dodajProdukt() {
const pole = document.getElementById('nowe');
const nazwa = pole.value.trim();
if (nazwa === '') return; // nie dodawaj pustych
const pozycja = document.createElement('li'); // 1. utwórz
pozycja.textContent = nazwa; // 2. ustaw
document.getElementById('lista').appendChild(pozycja); // 3. dołącz na koniec <ul>
pole.value = ''; // wyczyść pole po dodaniu
pole.focus();
}Gdzie dołączyć: appendChild, append, prepend, insertBefore
| Metoda | Dołącza | Uwagi |
|---|---|---|
rodzic.appendChild(el) | na koniec rodzica | tylko jeden element; zwraca dołączony element; klasyk z tabeli CKE |
rodzic.append(a, b, 'tekst') | na koniec | wiele argumentów, także zwykłe napisy; nic nie zwraca |
rodzic.prepend(el) | na początek rodzica | np. najnowsza wiadomość na górze |
rodzic.insertBefore(nowy, istniejacy) | przed wskazanym dzieckiem rodzica | starszy zapis; istniejacy musi być dzieckiem rodzica |
el.before(nowy) / el.after(nowy) | przed / za elementem el | nowoczesny, krótki |
el.insertAdjacentHTML('beforeend', '<p>…</p>') | wstawia HTML z napisu w jednym z 4 miejsc | nie kasuje istniejących nasłuchiwaczy (w odróżnieniu od innerHTML +=) |
appendChild i append robią na egzaminie to samo – wybierz appendChild, bo jest w tabeli pomocniczej arkusza, albo append, jeśli dołączasz kilka rzeczy naraz.
Treść i atrybuty nowego elementu
Nowy element ustawiasz dokładnie tak, jak istniejący (patrz lekcja 15):
const obraz = document.createElement('img');
obraz.src = 'kot.png'; // właściwość = atrybut
obraz.alt = 'kot.png';
obraz.title = 'Wzór 3'; // dymek po najechaniu
obraz.className = 'miniatury'; // atrybut class (albo classList.add)
obraz.setAttribute('width', '120'); // dowolny atrybut
obraz.style.border = '1px solid gray'; // styl inlineDla tekstu wybieraj textContent – innerHTML też działa, ale jeśli wstawiasz tekst wpisany przez użytkownika, textContent nie zinterpretuje przypadkowych znaczników.
Element może mieć dzieci: tworzysz div, do niego dołączasz img i p, a dopiero cały div – do strony. Tak buduje się „blok wiadomości” z arkusza chat (czerwiec 2024) albo „pozycję koszyka” (czerwiec 2025):
<div id="koszyk"><h3>Koszyk</h3></div>
<label>Nazwa: <input type="text" id="nazwa" value="plakat.png"></label>
<label>Kopie: <input type="number" id="kopie" value="2" min="1"></label>
<button type="button" id="dodaj">Dodaj do koszyka</button>.pozycja { display: flex; gap: 12px; align-items: center; border-bottom: 1px solid #ddd; padding: 6px 0; }
.pozycja img { width: 48px; height: 48px; background: #f2d338; }
.pozycja p { margin: 0; }document.getElementById('dodaj').addEventListener('click', () => {
const nazwaPliku = document.getElementById('nazwa').value;
const kopie = parseInt(document.getElementById('kopie').value);
const pozycja = document.createElement('div'); // rodzic bloku
pozycja.className = 'pozycja';
const miniatura = document.createElement('img');
miniatura.alt = nazwaPliku; // na egzaminie: miniatura.src = nazwaPliku
const opis = document.createElement('p');
opis.textContent = 'Liczba kopii: ' + kopie;
const cena = document.createElement('p');
cena.textContent = 'Cena: ' + (kopie * 1.5).toFixed(2) + ' zł';
pozycja.append(miniatura, opis, cena); // dzieci do bloku…
document.getElementById('koszyk').appendChild(pozycja); // …blok do koszyka
});Pętla generująca elementy
Arkusz ze stycznia 2026 (INF.03-09-26.01) kazał pętlą utworzyć 10 obrazów 1.jpg…10.jpg z klasą wzory, każdy z dymkiem (title) zawierającym numer. Schemat: pętla for od 1 do 10, w każdym obiegu nowy createElement, atrybuty zbudowane z licznika, appendChild.
Ile elementów img znajdzie się w #galeria po wykonaniu kodu i jaki title będzie miał ostatni?
var galeria = document.getElementById('galeria');
for (var i = 1; i <= 10; i++) {
var obraz = document.createElement('img');
obraz.src = i + '.jpg';
obraz.title = 'Wzór ' + i;
galeria.appendChild(obraz);
}<div id="galeria"></div>
<p>Najedź na miniaturę – zobaczysz dymek z numerem.</p>#galeria img.wzory { width: 44px; height: 44px; margin: 2px; border: 1px solid #999; }// zastępnik plików 1.jpg…10.jpg (na egzaminie: obraz.src = i + '.jpg')
function zrodloObrazka(numer) {
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="44" height="44">' +
'<rect width="100%" height="100%" fill="hsl(' + numer * 36 + ',60%,55%)"/>' +
'<text x="50%" y="55%" font-size="18" fill="white" text-anchor="middle" dominant-baseline="middle">' + numer + '</text></svg>';
return 'data:image/svg+xml;utf8,' + encodeURIComponent(svg);
}
const galeria = document.getElementById('galeria');
for (let numer = 1; numer <= 10; numer++) {
const obraz = document.createElement('img'); // NOWY element w każdym obiegu
obraz.src = zrodloObrazka(numer); // na egzaminie: numer + '.jpg'
obraz.alt = 'wzór ' + numer;
obraz.title = 'Wzór nr ' + numer; // dymek z numerem
obraz.className = 'wzory';
galeria.appendChild(obraz);
}Nowy element ze zdarzeniem
Arkusz z czerwca 2025 (INF.03-02-25.06): lista zadań ma przy każdym li przycisk „Wykonane”, który przekreśla tekst; nowe zadanie dodane z pola ma dostać taki sam przycisk podpięty do tej samej funkcji. Czyli: tworząc element, od razu podpinasz mu zdarzenie – addEventListener albo przypisanie onclick.
Funkcja obsługi musi wiedzieć, którego li dotyczy kliknięcie. Dwa sposoby: przekazać element jako argument (przycisk.onclick = () => oznaczWykonane(pozycja)) albo wyjść od klikniętego przycisku do jego rodzica (event.target.parentElement).
<ul id="zadania">
<li>Powtórzyć DOM <button type="button" onclick="oznaczWykonane(this)">Wykonane</button></li>
<li>Zrobić zadanie z pętlą <button type="button" onclick="oznaczWykonane(this)">Wykonane</button></li>
</ul>
<input type="text" id="noweZadanie" placeholder="Dodaj zadanie…" value="Napisać chat">
<button type="button" id="dodaj">Dodaj</button>li { margin: 4px 0; }
li.wykonane { text-decoration: line-through; color: gray; }// ta sama funkcja dla istniejących i nowych przycisków
// przycisk = kliknięty przycisk (this z atrybutu lub event.target)
function oznaczWykonane(przycisk) {
const pozycja = przycisk.parentElement; // <li>, w którym siedzi przycisk
pozycja.classList.add('wykonane'); // lub: pozycja.style.textDecoration = 'line-through'
przycisk.disabled = true;
}
document.getElementById('dodaj').addEventListener('click', () => {
const pole = document.getElementById('noweZadanie');
if (pole.value.trim() === '') return;
const pozycja = document.createElement('li');
pozycja.textContent = pole.value + ' '; // tekst zadania
const przycisk = document.createElement('button');
przycisk.type = 'button';
przycisk.textContent = 'Wykonane';
przycisk.addEventListener('click', () => oznaczWykonane(przycisk)); // podpięcie do tej samej funkcji
pozycja.appendChild(przycisk);
document.getElementById('zadania').appendChild(pozycja);
pole.value = '';
});Usuwanie i zamiana
| Metoda | Co robi |
|---|---|
el.remove() | usuwa element ze strony – najkrótszy zapis |
rodzic.removeChild(el) | to samo, przez rodzica; zapis z tabeli CKE; zwraca usunięty element |
rodzic.replaceChild(nowy, stary) | zamienia stary na nowy (uwaga na kolejność: najpierw nowy) |
stary.replaceWith(nowy) | to samo, krócej |
rodzic.innerHTML = '' | usuwa wszystkie dzieci |
rodzic.replaceChildren() | także usuwa wszystkie dzieci; z argumentami – wstawia nowe |
rodzic.firstElementChild / lastElementChild | pierwsze / ostatnie dziecko (do usunięcia „najstarszej wiadomości”) |
Usunięty element nie ginie – jeśli trzymasz go w zmiennej, możesz go dołączyć ponownie.
<ul id="lista">
<li>Ala <button type="button" class="usun">×</button></li>
<li>Bartek <button type="button" class="usun">×</button></li>
<li>Celina <button type="button" class="usun">×</button></li>
</ul>
<button type="button" id="cofnij" disabled>Cofnij ostatnie usunięcie</button>
<button type="button" id="wyczysc">Wyczyść listę</button>const lista = document.getElementById('lista');
const cofnij = document.getElementById('cofnij');
let ostatnioUsuniety = null;
for (const przycisk of document.querySelectorAll('.usun')) {
przycisk.addEventListener('click', () => {
ostatnioUsuniety = przycisk.parentElement; // <li>
ostatnioUsuniety.remove(); // lub: lista.removeChild(ostatnioUsuniety)
cofnij.disabled = false;
});
}
cofnij.addEventListener('click', () => {
if (ostatnioUsuniety) {
lista.appendChild(ostatnioUsuniety); // element wraca na koniec listy
ostatnioUsuniety = null;
cofnij.disabled = true;
}
});
document.getElementById('wyczysc').addEventListener('click', () => {
lista.innerHTML = ''; // wszystkie dzieci znikają
});Przewijanie do nowego elementu i losowanie z tablicy
Gdy chat się zapełni, nowa wiadomość ląduje poza widocznym obszarem. element.scrollIntoView() przewija kontener (lub stronę) tak, by element był widoczny; scrollIntoView({ behavior: 'smooth' }) robi to płynnie. Wywołujesz je po dołączeniu elementu.
Losowa odpowiedź z tablicy to jedna linia, którą warto znać na pamięć: tablica[Math.floor(Math.random() * tablica.length)]. Math.random() daje liczbę z zakresu od 0 (włącznie) do 1 (wyłącznie), pomnożona przez długość tablicy i obcięta Math.floor daje indeks od 0 do length - 1.
const odpowiedzi = ['Jasne!', 'Nie dzisiaj.', 'Zapytaj później.', 'Brzmi dobrze.'];
for (let i = 0; i < 3; i++) {
const indeks = Math.floor(Math.random() * odpowiedzi.length); // 0, 1, 2 lub 3
console.log(indeks, odpowiedzi[indeks]);
}Chat z arkusza INF.03-02-24.06 w wersji ćwiczeniowej – „Wyślij” dokleja blok z twoją wiadomością, „Losowa odpowiedź” dokleja blok z napisem wylosowanym z tablicy, a okno przewija się do najnowszego wpisu:
<div id="okno"></div>
<input type="text" id="tekst" placeholder="Napisz wiadomość…" value="Cześć, jak tam projekt?">
<button type="button" id="wyslij">Wyślij</button>
<button type="button" id="losuj">Losowa odpowiedź</button>#okno { height: 150px; overflow-y: auto; border: 1px solid #ccc; padding: 8px; }
.wiadomosc { display: flex; gap: 8px; align-items: center; margin-bottom: 6px; }
.wiadomosc .awatar { width: 28px; height: 28px; border-radius: 50%; flex: none; }
.ja .awatar { background: SteelBlue; } .bot .awatar { background: Olive; }
.wiadomosc p { margin: 0; background: #f3f3f3; padding: 4px 8px; border-radius: 8px; }const odpowiedzi = ['Idzie dobrze!', 'Jeszcze nie zaczęłam.', 'Skończę do piątku.', 'Potrzebuję pomocy z CSS.',
'Działa, ale nie wiem dlaczego.', 'Zrobione na 80 %.', 'Czekam na dane od Krzyśka.', 'Zapytaj jutro.', 'A ty?'];
const okno = document.getElementById('okno');
function dodajWiadomosc(tekst, klasaAutora) {
const blok = document.createElement('div');
blok.className = 'wiadomosc ' + klasaAutora; // dwie klasy: "wiadomosc ja" / "wiadomosc bot"
const awatar = document.createElement('span'); // na egzaminie: <img src="Jolka.jpg">
awatar.className = 'awatar';
const akapit = document.createElement('p');
akapit.textContent = tekst;
blok.append(awatar, akapit);
okno.appendChild(blok);
blok.scrollIntoView({ behavior: 'smooth' }); // przewiń do najnowszej wiadomości
}
document.getElementById('wyslij').addEventListener('click', () => {
const pole = document.getElementById('tekst');
if (pole.value.trim() === '') return;
dodajWiadomosc(pole.value, 'ja');
pole.value = '';
});
document.getElementById('losuj').addEventListener('click', () => {
const indeks = Math.floor(Math.random() * odpowiedzi.length); // 0–8
dodajWiadomosc(odpowiedzi[indeks], 'bot');
});Na egzaminie
Ściąga
| Składnia | Co robi | Przykład |
|---|---|---|
document.createElement('tag') | tworzy pusty element (jeszcze nie na stronie) | const li = document.createElement('li'); |
el.textContent = '…' / el.innerHTML = '…' | treść nowego elementu | li.textContent = zadanie; |
el.src, el.alt, el.title, el.className | atrybuty przez właściwości | img.className = 'miniatury'; |
el.setAttribute('a', 'v') | dowolny atrybut | img.setAttribute('width', '120'); |
rodzic.appendChild(el) | dołącz na koniec (zwraca el) | lista.appendChild(li); |
rodzic.append(a, b, 'tekst') | dołącz wiele na koniec | blok.append(img, p); |
rodzic.prepend(el) | dołącz na początek | okno.prepend(nowa); |
rodzic.insertBefore(nowy, istniejacy) | wstaw przed elementem | ul.insertBefore(li, ul.firstElementChild); |
el.insertAdjacentHTML('beforeend', html) | wstaw HTML z napisu bez kasowania nasłuchiwaczy | zamiast innerHTML += |
for (let i = 1; i <= 10; i++) { const img = document.createElement('img'); … } | pętla generująca | createElement w pętli |
nowy.addEventListener('click', fn) / nowy.onclick = fn | zdarzenie na nowym elemencie | btn.onclick = () => oznacz(li); |
przycisk.parentElement | rodzic klikniętego elementu | event.target.parentElement |
el.remove() / rodzic.removeChild(el) | usuń element | li.remove(); |
rodzic.replaceChild(nowy, stary) / stary.replaceWith(nowy) | zamień element | kolejność: nowy, stary |
rodzic.innerHTML = '' / rodzic.replaceChildren() | usuń wszystkie dzieci | wyczyść listę |
el.cloneNode(true) | kopia elementu z zawartością | powielenie szablonu |
el.scrollIntoView({ behavior: 'smooth' }) | przewiń do elementu | po appendChild |
tab[Math.floor(Math.random() * tab.length)] | losowy element tablicy | losowa odpowiedź |
Zadania
Lista obecności
Pole tekstowe „Imię i nazwisko”, przycisk Dodaj i pusta lista <ol id="obecni">. Kliknięcie dodaje nową pozycję li z wpisanym tekstem na koniec listy i czyści pole. Pod listą akapit #licznik pokazuje Obecnych: <liczba> – liczbę odczytaj z lista.children.length, nie z osobnej zmiennej. Puste pole nie dodaje pozycji.
Pokaż rozwiązanie
<input type="text" id="osoba" placeholder="Imię i nazwisko" value="Anna Kowalska">
<button type="button" onclick="dodajOsobe()">Dodaj</button>
<ol id="obecni"></ol>
<p id="licznik">Obecnych: 0</p>function dodajOsobe() {
const pole = document.getElementById('osoba');
const lista = document.getElementById('obecni');
if (pole.value.trim() === '') return;
const pozycja = document.createElement('li');
pozycja.textContent = pole.value.trim();
lista.appendChild(pozycja);
document.getElementById('licznik').textContent = 'Obecnych: ' + lista.children.length;
pole.value = '';
}Katalog wzorów w pętli
Strona wzory.html zawiera pustą sekcję <section id="katalog">. Skrypt w JavaScript, uruchamiany po załadowaniu strony (bez przycisku), tworzy w pętli 12 obrazów w1.jpg … w12.jpg (w placu zabaw użyj zastępnika zrodloObrazka(i) z lekcji) i dołącza je do sekcji. Każdy obraz ma: klasę wzor, atrybut alt równy nazwie pliku, dymek (title) o treści Wzór numer <i>. Obrazy o numerach podzielnych przez 3 mają dodatkowo klasę promocja (w CSS: czerwona ramka). Stosuj znaczące nazwy.
Kryteria samooceny (0/1):
- JavaScript, skrypt wykonuje się po załadowaniu strony.
- Użyto pętli tworzącej elementy – dokładnie 12 obrazów.
- Każdy obraz ma inne
src(w1.jpg…w12.jpg) ialtrówny nazwie pliku. - Każdy obraz ma klasę
wzor;titlezawiera właściwy numer. - Obrazy 3, 6, 9, 12 mają dodatkowo klasę
promocja. - Znaczące nazwy.
Pokaż rozwiązanie
<section id="katalog"></section>.wzor { width: 48px; height: 48px; margin: 3px; border: 2px solid transparent; }
.wzor.promocja { border-color: red; }function zrodloObrazka(numer) { // zastępnik plików w1.jpg…w12.jpg
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48">' +
'<rect width="100%" height="100%" fill="hsl(' + numer * 30 + ',55%,50%)"/>' +
'<text x="50%" y="55%" font-size="18" fill="white" text-anchor="middle" dominant-baseline="middle">' + numer + '</text></svg>';
return 'data:image/svg+xml;utf8,' + encodeURIComponent(svg);
}
const katalog = document.getElementById('katalog');
for (let numer = 1; numer <= 12; numer++) { // kryterium 2
const nazwaPliku = 'w' + numer + '.jpg';
const obraz = document.createElement('img');
obraz.src = zrodloObrazka(numer); // na egzaminie: obraz.src = nazwaPliku;
obraz.alt = nazwaPliku; // kryterium 3
obraz.title = 'Wzór numer ' + numer; // kryterium 4
obraz.classList.add('wzor');
if (numer % 3 === 0) {
obraz.classList.add('promocja'); // kryterium 5
}
katalog.appendChild(obraz);
}Planer dnia
Strona planer.html zawiera listę <ul id="plan"> z trzema gotowymi pozycjami, każda z tekstem i przyciskiem „Zrobione”, oraz pod listą pole tekstowe „Nowe zadanie” i przycisk „Dodaj”.
Skrypt w JavaScript: kliknięcie „Zrobione” przy pozycji przekreśla jej tekst (przez zmianę właściwości CSS) i zmienia napis przycisku na „Cofnij”; ponowne kliknięcie usuwa przekreślenie i przywraca napis „Zrobione”. Kliknięcie „Dodaj” tworzy nową pozycję na końcu listy z wpisanym tekstem i przyciskiem „Zrobione” podpiętym do tej samej funkcji; pole jest czyszczone. Pozycje nie są usuwane. Stosuj znaczące nazwy.
Kryteria samooceny (0/1):
- JavaScript, funkcje wywoływane przyciskami.
- „Zrobione” przekreśla tekst pozycji przez CSS (
text-decoration) – działa dla każdej z trzech pozycji. - Ponowne kliknięcie cofa przekreślenie; napis przycisku zmienia się Zrobione ↔ Cofnij.
- „Dodaj” tworzy nowy
liz tekstem z pola na końcu listy. - Nowy
lima przycisk, który działa tak samo jak istniejące. - Znaczące nazwy.
Pokaż rozwiązanie
<ul id="plan">
<li><span>Powtórka z DOM</span> <button type="button" onclick="przelaczZrobione(this)">Zrobione</button></li>
<li><span>Trening 30 min</span> <button type="button" onclick="przelaczZrobione(this)">Zrobione</button></li>
<li><span>Zakupy</span> <button type="button" onclick="przelaczZrobione(this)">Zrobione</button></li>
</ul>
<input type="text" id="noweZadanie" placeholder="Nowe zadanie" value="Oddać książki">
<button type="button" onclick="dodajZadanie()">Dodaj</button>// kryteria 2–3: jedna funkcja dla starych i nowych przycisków
function przelaczZrobione(przycisk) {
const tekst = przycisk.parentElement.querySelector('span'); // <span> z treścią w tym samym <li>
if (tekst.style.textDecoration === 'line-through') {
tekst.style.textDecoration = 'none';
przycisk.textContent = 'Zrobione';
} else {
tekst.style.textDecoration = 'line-through';
przycisk.textContent = 'Cofnij';
}
}
// kryteria 4–5
function dodajZadanie() {
const pole = document.getElementById('noweZadanie');
if (pole.value.trim() === '') return;
const pozycja = document.createElement('li');
const tekst = document.createElement('span');
tekst.textContent = pole.value;
const przycisk = document.createElement('button');
przycisk.type = 'button';
przycisk.textContent = 'Zrobione';
przycisk.onclick = () => przelaczZrobione(przycisk); // ta sama funkcja
pozycja.append(tekst, ' ', przycisk);
document.getElementById('plan').appendChild(pozycja);
pole.value = '';
}Warunek tekst.style.textDecoration === 'line-through' działa, bo przekreślenie ustawiamy ze skryptu (styl inline). Gdyby było w CSS, trzeba by użyć classList.toggle.
Koszyk fotograficzny z plikiem
Strona koszyk.html zawiera: pole wyboru pliku (accept="image/*"), pole numeryczne „Liczba odbitek” (domyślnie 1), dwa przyciski opcji „Format 10×15 – 1,20 zł” (domyślnie) i „Format 15×21 – 2,50 zł”, przycisk „Dodaj do koszyka” oraz blok <div id="koszyk"> z nagłówkiem „Koszyk”.
Skrypt w JavaScript po kliknięciu: ustala nazwę pliku bez ścieżki dostępu (gdy pliku nie wybrano – wypisuje w akapicie #komunikat tekst Wybierz zdjęcie. i kończy), oblicza cenę (cena formatu × liczba odbitek) i dokleja do bloku koszyka nową pozycję: element img z atrybutami src i alt równymi nazwie pliku oraz klasą miniatura, a pod nim dwa akapity: Zdjęcie: <nazwa>, odbitek: <liczba> i Cena: <kwota> zł. Kolejne kliknięcia dopisują kolejne pozycje. Pod koszykiem akapit #suma pokazuje Razem: <suma> zł (suma wszystkich pozycji). Stosuj znaczące nazwy.
W placu zabaw src ustawione na samą nazwę pliku nie wyświetli obrazu (plik jest na dysku użytkownika, nie na serwerze) – zobaczysz alt; na egzaminie pliki leżą obok strony, więc obraz się pokaże. Jeśli chcesz podgląd, zamiast nazwy możesz podstawić URL.createObjectURL(plik.files[0]).
Kryteria samooceny (0/1):
- JavaScript, funkcja wywoływana przyciskiem.
- Nazwa pliku ustalona z pola
filebez ścieżki (C:\fakepath\wycięte). - Cena = cena wybranego formatu × liczba odbitek – poprawna dla obu formatów.
- Do koszyka dołączony nowy
imgzsrc,altrównymi nazwie i klasąminiatura. - Dwa akapity w podanym formacie; kolejne kliknięcia dodają kolejne pozycje.
- Akapit
#sumaaktualizowany po każdym dodaniu. - Znaczące nazwy.
Pokaż rozwiązanie
<label>Zdjęcie: <input type="file" id="zdjecie" accept="image/*"></label><br>
<label>Liczba odbitek: <input type="number" id="odbitki" min="1" value="1"></label><br>
<input type="radio" name="format" value="1.2" id="maly" checked> <label for="maly">Format 10×15 – 1,20 zł</label>
<input type="radio" name="format" value="2.5" id="duzy"> <label for="duzy">Format 15×21 – 2,50 zł</label><br>
<button type="button" onclick="dodajDoKoszyka()">Dodaj do koszyka</button>
<p id="komunikat"></p>
<div id="koszyk"><h3>Koszyk</h3></div>
<p id="suma">Razem: 0 zł</p>.pozycja { border-top: 1px solid #ddd; padding: 6px 0; }
.pozycja p { margin: 2px 0; }
.miniatura { max-width: 80px; max-height: 60px; display: block; }let sumaKoszyka = 0; // stan poza funkcją – rośnie z każdą pozycją
function dodajDoKoszyka() {
const polePliku = document.getElementById('zdjecie');
const komunikat = document.getElementById('komunikat');
// kryterium 2: nazwa bez ścieżki
if (polePliku.files.length === 0) {
komunikat.textContent = 'Wybierz zdjęcie.';
return;
}
komunikat.textContent = '';
const sciezka = polePliku.value; // "C:\fakepath\kot.jpg"
const nazwaPliku = sciezka.slice(sciezka.lastIndexOf('\\') + 1); // "kot.jpg" (lub files[0].name)
// kryterium 3: cena
const odbitki = parseInt(document.getElementById('odbitki').value);
const cenaFormatu = parseFloat(document.querySelector('input[name="format"]:checked').value);
const cena = cenaFormatu * odbitki;
// kryterium 4: obraz
const pozycja = document.createElement('div');
pozycja.className = 'pozycja';
const miniatura = document.createElement('img');
miniatura.src = URL.createObjectURL(polePliku.files[0]); // na egzaminie: miniatura.src = nazwaPliku;
miniatura.alt = nazwaPliku;
miniatura.className = 'miniatura';
// kryterium 5: dwa akapity
const opis = document.createElement('p');
opis.textContent = 'Zdjęcie: ' + nazwaPliku + ', odbitek: ' + odbitki;
const akapitCeny = document.createElement('p');
akapitCeny.textContent = 'Cena: ' + cena.toFixed(2) + ' zł';
pozycja.append(miniatura, opis, akapitCeny);
document.getElementById('koszyk').appendChild(pozycja); // dokłada, nie nadpisuje
// kryterium 6: suma
sumaKoszyka += cena;
document.getElementById('suma').textContent = 'Razem: ' + sumaKoszyka.toFixed(2) + ' zł';
}Test powtórkowy
Test powtórkowy
Format jak w części pisemnej INF.03 – 4 odpowiedzi, 1 poprawna.
Która metoda tworzy nowy element akapitu?
Element nowy został utworzony i ma treść. Który zapis umieści go na końcu bloku #chat?
Co stanie się po wykonaniu kodu w dialekcie egzaminacyjnym?
var obraz = document.createElement('img');
obraz.setAttribute('src', 'kot.jpg');
obraz.setAttribute('alt', 'kot.jpg');
obraz.className = 'miniatury';Ile elementów li doda ta pętla do listy?
for (var i = 0; i < 5; i++) {
var li = document.createElement('li');
li.innerHTML = 'Pozycja ' + (i + 1);
lista.appendChild(li);
}Które wywołanie ustawi na nowym obrazie dymek z numerem z pętli?
Który zapis usunie element li ze strony?
W bloku #lista są przyciski z nasłuchiwaczami dodanymi przez addEventListener. Co stanie się po lista.innerHTML += '<li>Nowe</li>'?
Które wyrażenie zwraca losowy element tablicy odp o 9 elementach?
Która metoda przewinie okno chatu tak, by nowo dodana wiadomość blok była widoczna?
Które wywołanie zamieni element stary na element nowy w ich wspólnym rodzicu rodzic?