Przejdź do głównej treści
INF.03-12-26.01-SGStyczeń 2026 · 49 kroków · ok. 81 min · 39 kryteriów z klucza

Rozwiązanie krok po kroku: Witryna studia tatuażu (Wersja podstawowa)

Witryna studia tatuażu to baza studiotatuazu (tatuaże i style połączone relacją) z czterema zapytaniami - dwa warunki z sortowaniem malejąco, COUNT z GROUP BY, złączenie JOIN i UPDATE podnoszący cenę o 10% - oraz logo przygotowane w edytorze grafiki i jedna strona index.html. Strona korzysta z czcionki Dancing Script dołączonej regułą @font-face, ma galerię z paskami przewijania i formularz „Dodaj wzór”, z którego skrypt JavaScript odczytuje nazwę wybranego pliku PNG, kolor i cenę, wyświetla komunikat i dokłada do galerii nową miniaturę.

Kroki idą zdanie po zdaniu za treścią arkusza - przy każdym jest polecenie z arkusza, a kod pokazuje dokładnie te linie, które je spełniają. Skrypt jest najpierw napisany najprościej, funkcjami z tabeli 1 arkusza (getElementById, lastIndexOf, createElement, appendChild, zdarzenie onclick), a na końcu przerobiony na wersję z prawdziwych projektów: nasłuchiwacz zdarzenia, sprawdzenie pustych pól i nazwa pliku wprost z obiektu File.

To jest wersja podstawowa. W zakładce „Nowoczesny kod (grid, osobny skrypt)” jest drugi sposób rozwiązania tego samego arkusza: układ na siatce CSS z nazwanymi obszarami zamiast float, skrypt w osobnym pliku z nasłuchiwaczem zdarzenia, sprawdzeniem pustych pól i szablonem tekstowym od pierwszej linii - obie wersje są zgodne z kluczem.

Baza, wzory tatuaży i pliki czcionki pochodzą z prawdziwego archiwum pliki16 (załącznik do arkusza, hasło w treści zadania). Zrzuty wyników zapytań są odtworzone z tej bazy - na egzaminie robisz je sam, z całego ekranu. Logo jest przycięte i przeskalowane z oryginalnego logo.png, a działanie skryptu sprawdzone w prawdziwej przeglądarce Chrome z wybranym plikiem rozeta.png.

Jak liczą się punkty. Klucz ma 39 kryteriów (R.1.1 - R.5.8), każde za 1 punkt. Próg zdania części praktycznej to 75%, czyli 30 punktów - można stracić 9 kryteriów i nadal zdać. Przy każdym kroku jest napisane, które kryteria spełnia; egzaminator ocenia spełnienie kryteriów z klucza, nie zgodność z tym kodem.

  1. Etap 1: Baza danych

    Kroki 1-7 · po tym etapie masz 6 z 39 kryteriów (pkt)

    Krok 1: Baza danych studiotatuazu

    ok. 2 min
    Polecenie z arkusza

    Utwórz bazę danych o nazwie studiotatuazu, z zestawem polskich znaków (np. utf8_polish_ci)

    Najpierw archiwum pliki16.7z z pulpitu. Hasło to <Studio&T@tu> razem z nawiasami ostrymi - w arkuszu są pogrubione jak reszta hasła, więc łatwo je pominąć. Potem folder z numerem zdającego. W phpMyAdmin: Nowa, nazwa studiotatuazu (bez „ż” i „ą”), porównywanie utf8_polish_ci.

    Typowe błędy

    Hasło bez nawiasów < i > nie otwiera archiwum - a bez niego nie ma bazy, wzorów ani czcionki.

  2. Krok 2: Import tabel z pliku studiotatuazu.sql

    ok. 2 min
    Polecenie z arkusza

    Z rozpakowanego archiwum zaimportuj tabele z pliku studiotatuazu.sql do utworzonej bazy

    Zaznaczona baza studiotatuazu, potem Import → studiotatuazu.sql → Wykonaj. Powstają dwie tabele z ilustracji 1: style (6 stylów) i tatuaze (22 tatuaże: wzór, plik graficzny, kolor, cena i style_id - klucz obcy do stylu).

  3. Krok 3: Zrzut ekranu import.png

    Kryteria:

    R.1.1 Wykonany import tabel do bazy danych studiotatuazu - plik import.png

    ok. 2 min
    Polecenie z arkusza

    Wykonaj zrzut ekranu po imporcie. Zapisz zrzut w formacie PNG pod nazwą import. Nie kadruj zrzutu. Powinien on obejmować cały ekran monitora, z widocznym paskiem zadań. Na zrzucie powinny być widoczne elementy wskazujące na poprawnie wykonany import tabel

    Print Screen, wklejenie do edytora grafiki i zapis jako import.png. W tym arkuszu wszystkie zrzuty (import i kw1-kw4) są w PNG.

    Typowe błędy

    Wykadrowany zrzut albo zrzut bez paska zadań nie jest oceniany (uwaga w kluczu przy R.1).

  4. Krok 4: Zapytanie 1: czarne tatuaże droższe niż 100 zł

    Kryteria: ,

    R.1.2 W pliku kwerendy.txt zapisane co najmniej jedno zapytanie SQL, wynikające z treści zadania

    R.1.3 Wykonane zapytanie 1 wybierające jedynie wzór i cenę tatuaży, tylko dla czarnych tatuaży, których cena jest większa niż 100 zł, posortowane według ceny malejąco. W pliku z kwerendami lub na zrzucie istnieje zapis np. SELECT wzor, cena FROM tatuaze WHERE kolor = "czarny" AND cena > 100 ORDER BY cena DESC; oraz na zrzucie widoczne są dane: koliber 200, anioł 200, kwiat 130

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 1: wybierające jedynie wzór i cenę tatuaży, dla tatuaży w kolorze czarnym, których cena jest większa niż 100 zł, posortowane według ceny malejąco

    • SELECT wzor, cena - dwa pola,
    • FROM tatuaze,
    • WHERE kolor = 'czarny' AND cena > 100 - oba warunki naraz; „większa niż” to ostra nierówność, więc tygrys za dokładnie 100 zł odpada,
    • ORDER BY cena DESC - malejąco.

    Wynik: koliber 200, anioł 200, kwiat 130 - jak w kluczu (dwa wzory po 200 zł mogą stanąć w dowolnej kolejności). Zapytania trafiają do kwerendy.txt, zrzut do kw1.png.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT wzor, cena FROM tatuaze WHERE kolor = 'czarny' AND cena > 100 ORDER BY cena DESC;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: liczba tatuaży w każdym kolorze

    Kryteria:

    R.1.4 Wykonane zapytanie 2 wybierające nazwę koloru tatuażu i zliczające ile jest tatuaży danego koloru. W pliku z kwerendami lub na zrzucie istnieje zapis np. SELECT kolor, COUNT(*) FROM tatuaze GROUP BY kolor; oraz na zrzucie widoczne są jedynie dane: czarny 8, czerwony 4, niebieski 3, szary 1, wielokolorowy 1, zielony 3, złoty 1, żółty 1

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 2: wybierające nazwę koloru tatuażu i zliczające ile jest tatuaży danego koloru. Należy zastosować grupowanie

    • SELECT kolor, COUNT(*) - kolor i liczba wierszy w grupie,
    • FROM tatuaze,
    • GROUP BY kolor - jeden wiersz wyniku na każdy kolor.

    Wynik: 8 wierszy - czarny 8, czerwony 4, niebieski 3, szary 1, wielokolorowy 1, zielony 3, złoty 1 i zółty 1. Zrzut: kw2.png.

    ⚠️ Rozbieżność arkusz-klucz: z bazy z archiwum wychodzi wiersz „zółty 1” (bez kropki nad „z” - literówka w danych CKE), klucz CKE zapisuje go jako „żółty 1”. Zapytanie jest poprawne, liczby się zgadzają - na egzaminie punkt daje poprawne zapytanie, nie trzeba poprawiać danych.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT wzor, cena FROM tatuaze WHERE kolor = 'czarny' AND cena > 100 ORDER BY cena DESC;
    
    -- Zapytanie 2
    SELECT kolor, COUNT(*) FROM tatuaze GROUP BY kolor;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: zielone tatuaże i ich styl

    Kryteria:

    R.1.5 Wykonane zapytanie 3 wybierające jedynie wzór tatuażu i odpowiadającą mu nazwę stylu dla tatuaży w kolorze zielonym. W pliku z kwerendami lub na zrzucie istnieje zapis np. SELECT wzor, nazwa FROM tatuaze JOIN style ON style_id = style.id WHERE kolor = 'zielony'; (lub porównanie kluczy po WHERE ) oraz na zrzucie widoczne są dane: waz hanpoke, smok orientalne, kwiat orientalne

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 3: wybierające jedynie wzór tatuażu i odpowiadającą mu nazwę stylu dla tatuaży w kolorze zielonym. Należy posłużyć się relacją

    • SELECT wzor, nazwa - wzór z tabeli tatuaze, nazwa stylu z tabeli style,
    • FROM tatuaze JOIN style - złączenie dwóch tabel,
    • ON tatuaze.style_id = style.id - warunek relacji z ilustracji 1: klucz obcy tatuażu wskazuje identyfikator stylu,
    • WHERE kolor = 'zielony'.

    Wynik: waz - hanpoke, smok - orientalne, kwiat - orientalne, jak w kluczu. Zrzut: kw3.png.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT wzor, cena FROM tatuaze WHERE kolor = 'czarny' AND cena > 100 ORDER BY cena DESC;
    
    -- Zapytanie 2
    SELECT kolor, COUNT(*) FROM tatuaze GROUP BY kolor;
    
    -- Zapytanie 3
    SELECT wzor, nazwa FROM tatuaze JOIN style ON tatuaze.style_id = style.id WHERE kolor = 'zielony';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: czerwone tatuaże drożeją o 10%

    Kryteria:

    R.1.6 Wykonane zapytanie 4 aktualizujące cenę tatuażu. Cena wzrasta o 10% dla tatuaży w kolorze czerwonym. W pliku z kwerendami lub na zrzucie istnieje zapis np. UPDATE tatuaze SET cena = cena * 1.1 WHERE kolor='czerwony'; oraz na zrzucie widoczny jest komunikat o poprawnym działaniu zapytania lub zmienione ceny produktów dla koloru czerwonego

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 4: aktualizujące cenę tatuażu. Cena wzrasta o 10% dla tatuaży w kolorze czerwonym

    • UPDATE tatuaze - zmiana istniejących wierszy,
    • SET cena = cena * 1.1 - nowa cena liczona ze starej: wzrost o 10% to pomnożenie przez 1,1 (w SQL kropka dziesiętna),
    • WHERE kolor = 'czerwony' - bez warunku podrożałyby wszystkie 22 tatuaże.

    Zmienione 4 rekordy: przed zapytaniem smok 150, rozeta 60, kwiaty 40, kwiat 140, po nim 165, 66, 44 i 154. Pole cena jest liczbą całkowitą, więc wynik mnożenia zostaje zaokrąglony - tu wszystkie wychodzą równe. Zrzut z komunikatem „Zmodyfikowanych rekordów: 4” albo z nowymi cenami: kw4.png.

    Typowe błędy

    SET cena = 1.1 zamiast cena * 1.1 wpisuje wszystkim czerwonym tatuażom cenę 1 zł.

    kwerendy.txt Tekst zmienione: 3 linie
    -- Zapytanie 1
    SELECT wzor, cena FROM tatuaze WHERE kolor = 'czarny' AND cena > 100 ORDER BY cena DESC;
    
    -- Zapytanie 2
    SELECT kolor, COUNT(*) FROM tatuaze GROUP BY kolor;
    
    -- Zapytanie 3
    SELECT wzor, nazwa FROM tatuaze JOIN style ON tatuaze.style_id = style.id WHERE kolor = 'zielony';
    
    -- Zapytanie 4
    UPDATE tatuaze SET cena = cena * 1.1 WHERE kolor = 'czerwony';
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Etap 2: Grafika i strona HTML

    Kroki 8-30 · po tym etapie masz 20 z 39 kryteriów (pkt)

    Krok 8: Logo: przycięcie do krawędzi ptaka

    ok. 2 min
    Polecenie z arkusza

    Skadrowana do krawędzi kształtu ptaka i przeskalowana z zachowaniem proporcji do wysokości 300 px

    Plik logo.png z archiwum ma 640 × 360 pikseli i przezroczyste tło, a ptak zajmuje tylko środek. W GIMP-ie wystarczy Obraz → Przytnij do zawartości: program obcina przezroczyste brzegi i zostaje prostokąt, w którym ptak dotyka każdej krawędzi - 368 × 356 pikseli.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Krok 9: Logo: skala do wysokości 300 px

    Kryteria:

    R.2.1 Grafika logo.png jest skadrowana do krawędzi kształtu ptaka (sprawdzić bez powiększania ) i przeskalowana do wysokości 300 px

    ok. 2 min
    Polecenie z arkusza

    Skadrowana do krawędzi kształtu ptaka i przeskalowana z zachowaniem proporcji do wysokości 300 px

    Obraz → Skaluj obraz, łańcuch między szerokością a wysokością zamknięty (proporcje zachowane), wysokość 300 px. Szerokość program liczy sam: 368 · 300 / 356 ≈ 310 px. Kolejność ma znaczenie - przy skalowaniu przed kadrowaniem ptak miałby mniej niż 300 px wysokości.

    Typowe błędy

    Skalowanie bez zamkniętego łańcucha (np. do 300 × 300) spłaszcza ptaka - proporcje muszą zostać zachowane.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 9
  10. Krok 10: Logo: litery S i T czcionką ozdobną, zrzut czcionka.jpg

    Kryteria:

    R.2.2 W grafice, w prawym dolnym rogu znajdują się litery „S” oraz „T”, litera „T” jest przesunięta w dół względem litery „S”. Wybór czcionki jest udokumentowany na zrzucie ekranu w pliku czcionka.jpg (nieistotna wielkość liter)

    ok. 4 min
    Polecenie z arkusza

    W prawym dolnym rogu należy dodać litery „S” oraz „T”, litera „T” jest przesunięta w dół względem litery „S”. Litery są zapisane dowolną dostępną czcionką ozdobną. Należy wykonać zrzut ekranu z edytora grafiki z ustawioną widoczną nazwą czcionki i zapisać pod nazwą czcionka.jpg

    Narzędzie Tekst, czcionka Freestyle Script (jak na ilustracji 2; może być dowolna ozdobna), kolor czarny. Każda litera to osobna warstwa tekstowa, więc „T” łatwo przesunąć niżej niż „S” narzędziem Przesunięcie. Ilustracja 2 nie podaje jednostki rozmiaru „100”; w tym rozwiązaniu wielkość liter dobrana jest do ilustracji. Gdy litery stoją na miejscu, zrzut ekranu z otwartym narzędziem tekstu (widać nazwę czcionki w opcjach) zapisany jako czcionka.jpg - to dowód wyboru czcionki do R.2.2. Na koniec Plik → Wyeksportuj jako logo.png (format PNG zachowuje przezroczystość).

    Typowe błędy

    Zapis przez Plik → Zapisz tworzy plik .xcf GIMP-a, nie PNG - przeglądarka go nie wyświetli.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 10
  11. Krok 11: Plik index.html w HTML5, wzory i czcionka w folderze

    ok. 2 min
    Polecenie z arkusza

    Składa się ze strony index.html. Zapisana w języku HTML5

    Deklaracja <!DOCTYPE html> i szkielet strony. Do folderu z numerem zdającego trafiają wszystkie wzory PNG z archiwum (angel.png, celtic.png, delfin.png, koliber.png, kwiat.png, kwiaty.png, rozeta.png, smok.png, tygrys.png, waz.png) oraz oba pliki czcionki z folderu czcionki: DancingScript-Regular.woff i DancingScript-Regular.woff2 - tak wymienia je lista plików na końcu arkusza. Skrypt będzie wstawiał do galerii obrazy po samej nazwie pliku, więc wzory muszą leżeć obok strony.

    index.html HTML nowy plik
    <!DOCTYPE html>
    <html>
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  12. Krok 12: Język strony

    Kryteria:

    R.2.3 W pliku index.html znajduje się deklaracja HTML5 <!DOCTYPE HTML> i deklaracja języka zawartości witryny: polski np. <html lang="pl">

    ok. 1 min
    Polecenie z arkusza

    Zadeklarowany polski język zawartości witryny

    Atrybut lang="pl" w znaczniku <html> - razem z deklaracją HTML5 to jedno kryterium klucza.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  13. Krok 13: Kodowanie polskich znaków

    ok. 1 min
    Polecenie z arkusza

    Jawnie zastosowany właściwy standard kodowania polskich znaków

    <meta charset="UTF-8"> jako pierwszy element <head> - bez niego „Tatuaże” i „Dodaj wzór” mogą wyświetlić się krzakami.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  14. Krok 14: Tytuł strony

    Kryteria:

    R.2.4 W sekcji head znajduje się jawnie podany standard kodowania polskich znaków oraz stronie nadano tytuł "Tatuaże"

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony widoczny na karcie przeglądarki: „Tatuaże”

    <title> w <head>. Z kodowaniem to jedno kryterium klucza (R.2.4).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  15. Krok 15: Podpięcie arkusza stylów

    Kryteria:

    R.3.2 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl.css formatowanie CSS pochodzi jedynie z tego arkusza

    ok. 1 min
    Polecenie z arkusza

    Arkusz stylów w pliku o nazwie styl.css prawidłowo połączony z kodem strony

    Nazwa pliku: styl.css (nie style.css). Formatowanie ma pochodzić tylko z tego pliku - także reguła czcionki @font-face trafi do styl.css, a nie do znacznika <style>.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  16. Krok 16: Bloki: dwa nagłówkowe, sekcja, boczny, stopka

    Kryteria:

    R.2.5 W sekcji body zdefiniowany jest podział na bloki za pomocą semantycznych znaczników HTML5: header+header, section, aside, footer (dopuszcza się zastosowanie bloków pomocniczych)

    ok. 2 min
    Polecenie z arkusza

    Podział strony na bloki zrealizowany za pomocą semantycznych znaczników bloków języka HTML5 tak, aby po uruchomieniu w przeglądarce układ bloków na stronie był zgodny z ilustracją 3

    Klucz wymaga wprost header + header, section, aside i footer (R.2.5). Oba nagłówki dostają identyfikatory logo i studio (różne szerokości w CSS), a sekcja gallery - po nim skrypt znajdzie galerię, do której dokłada obrazy. Kolejność w kodzie to kolejność czytania: nagłówki, galeria, formularz, stopka. Układ z ilustracji 3 (blok boczny pod logo, sekcja pod nazwą studia) zrobi CSS.

    index.html HTML zmienione: 10 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
        </header>
        <header id="studio">
        </header>
        <section id="gallery">
        </section>
        <aside>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  17. Krok 17: Blok nagłówkowy 1: logo

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku nagłówkowego 1: obraz logo.png z tekstem alternatywnym „salon”

    Logo przygotowane w edytorze grafiki. Tekst alternatywny w atrybucie alt.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
        </header>
        <section id="gallery">
        </section>
        <aside>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  18. Krok 18: Blok nagłówkowy 2: nagłówek pierwszego stopnia

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku nagłówkowego 2: nagłówek pierwszego stopnia o treści „Studio Tatuażu”

    <h1> z wielkimi literami „S” i „T”, jak w arkuszu.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
        </section>
        <aside>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  19. Krok 19: Sekcja: nagłówek Galeria

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku sekcji: Nagłówek drugiego stopnia o treści „Galeria”

    <h2> na początku sekcji. Pod nim staną dwa wzory, a potem obrazy dokładane przez skrypt.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
        </section>
        <aside>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  20. Krok 20: Sekcja: obraz smok.png z klasą miniatury

    ok. 1 min
    Polecenie z arkusza

    Obraz smok.png z tekstem alternatywnym „smok.png”, z przypisaną klasą miniatury

    Tekst alternatywny to tu dosłownie nazwa pliku - tak samo skrypt będzie podpisywał obrazy dodane z formularza. Nazwa klasy miniatury jest narzucona przez arkusz (dlatego po polsku); na razie obraz ma oryginalną szerokość 320 px, a zmniejszy go reguła CSS dla tej klasy.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
        </section>
        <aside>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  21. Krok 21: Sekcja: obraz koliber.png z klasą miniatury

    Kryteria: ,

    R.2.7 W bloku nagłówkowym 1 znajduje się obraz z logiem z tekstem alternatywnym „salon” w bloku sekcji obrazy smok.png i koliber.png , tekst alternatywny jak nazwa pliku (rozszerzenie pliku opcjonalnie)

    R.3.5 Obrazy z bloku sekcji mają przypisaną klasę miniatury

    ok. 1 min
    Polecenie z arkusza

    Obraz koliber.png z tekstem alternatywnym „koliber.png”, z przypisaną klasą miniatury

    Drugi obraz w tej samej linii. Z logo z bloku nagłówkowego to komplet obrazów strony (R.2.7), a oba obrazy galerii mają klasę miniatury (R.3.5).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  22. Krok 22: Blok boczny: nagłówek trzeciego stopnia

    ok. 1 min
    Polecenie z arkusza

    Zawartość bloku bocznego: Nagłówek trzeciego stopnia o treści „Dodaj wzór”

    <h3> na początku bloku bocznego. Pod nim formularz - bez znacznika <form>, bo dane nie są nigdzie wysyłane: odczyta je skrypt na tej samej stronie.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  23. Krok 23: Etykieta „Wzór:”

    Kryteria:

    R.2.8 Przynajmniej jedna etykieta jest powiązana z kontrolką

    ok. 1 min
    Polecenie z arkusza

    Etykieta o treści „Wzór:”, powiązana z polem edycyjnym do podania nazwy pliku

    Etykieta <label> z atrybutem for="file" - wskazuje identyfikator pola, które za chwilę powstanie. Kliknięcie w napis „Wzór:” otworzy wtedy okno wyboru pliku. <br> przenosi pole do następnej linii („poniżej” w arkuszu).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label><br>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  24. Krok 24: Pole wyboru pliku przyjmujące tylko PNG

    ok. 1 min
    Polecenie z arkusza

    Poniżej pole edycyjne do wyboru pliku w oknie dialogowym, przyjmujące jedynie obrazy w formacie PNG

    type="file" to przycisk „Wybierz plik”, który otwiera okno dialogowe. accept="image/png" każe oknu pokazywać tylko pliki PNG - zapis jest w ramce pod tabelą 1 arkusza (klucz uznaje też accept=".png"). Identyfikator file łączy pole z etykietą i posłuży skryptowi.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label><br>
            <input type="file" id="file" accept="image/png"><br>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  25. Krok 25: Etykieta „Kolor:”

    ok. 1 min
    Polecenie z arkusza

    Poniżej etykieta o treści „Kolor:”, powiązana z listą rozwijaną

    To samo połączenie for - id, tym razem z listą o identyfikatorze color.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label><br>
            <input type="file" id="file" accept="image/png"><br>
            <label for="color">Kolor:</label><br>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  26. Krok 26: Lista rozwijana z czterema kolorami

    Kryteria:

    R.2.10 Pole listy rozwijanej zawiera opcje: „Czarny”, „Czerwony”, „Zielony”, „Niebieski”, użyte znaczniki <select> i <option>

    ok. 2 min
    Polecenie z arkusza

    Poniżej lista rozwijana z opcjami: „Czarny”, „Czerwony”, „Zielony”, „Niebieski”

    <select> z czterema <option>. Bez atrybutu value wartością opcji jest jej tekst - skrypt odczyta więc „Zielony” z wielką literą, dokładnie jak w komunikacie na ilustracji 5. Pierwsza opcja jest wybrana domyślnie.

    index.html HTML zmienione: 6 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label><br>
            <input type="file" id="file" accept="image/png"><br>
            <label for="color">Kolor:</label><br>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select><br>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  27. Krok 27: Etykieta „Cena:”

    ok. 1 min
    Polecenie z arkusza

    Poniżej etykieta o treści „Cena:”, powiązana z polem edycyjnym do wpisania ceny

    Etykieta dla pola o identyfikatorze price.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label><br>
            <input type="file" id="file" accept="image/png"><br>
            <label for="color">Kolor:</label><br>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select><br>
            <label for="price">Cena:</label><br>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  28. Krok 28: Pole liczbowe na cenę

    Kryteria:

    R.3.4 Jedno pole edycyjne jest typu file z atrybutem accept="image/png" (lub accept=".png"), a drugie jest typu number

    ok. 1 min
    Polecenie z arkusza

    Poniżej pole edycyjne typu liczbowego przeznaczone do wpisywania ceny

    type="number" - przeglądarka przyjmie tylko liczbę i doda strzałki do jej zmiany. Z polem typu file to kryterium R.3.4.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label><br>
            <input type="file" id="file" accept="image/png"><br>
            <label for="color">Kolor:</label><br>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select><br>
            <label for="price">Cena:</label><br>
            <input type="number" id="price"><br>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  29. Krok 29: Przycisk „Dodaj Wzór” wywołujący skrypt

    Kryteria: ,

    R.2.9 W bloku bocznym znajdują się dwa pola edycyjne, pole listy rozwijanej oraz przycisk "Dodaj Wzór"

    R.3.3 Zdefiniowane dla przycisku zdarzenie związane z jego wciśnięciem, które uruchamia funkcję skryptu (obsługa zdarzenia zdefiniowana w HTML np. onClick lub w skrypcie np.element.addEventListener(...) element.onClick = …)

    ok. 1 min
    Polecenie z arkusza

    Poniżej przycisk o treści „Dodaj Wzór”. Wciśnięcie przycisku powoduje wywołanie skryptu

    Atrybut onclick (zdarzenie myszy z tabeli 1) wywołuje funkcję addPattern, którą napisze etap JavaScript. Do tego czasu kliknięcie kończy się błędem w konsoli przeglądarki - funkcji jeszcze nie ma. W bloku bocznym są już oba pola edycyjne, lista i przycisk (R.2.9).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label><br>
            <input type="file" id="file" accept="image/png"><br>
            <label for="color">Kolor:</label><br>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select><br>
            <label for="price">Cena:</label><br>
            <input type="number" id="price"><br>
            <button onclick="addPattern()">Dodaj Wzór</button>
        </aside>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  30. Krok 30: Stopka z autorem

    Kryteria:

    R.2.6 W bloku nagłówkowym 2 znajduje się <h1>: "Studio Tatuażu", w bloku sekcji <h2>: "Galeria", w bloku bocznym <h3>: "Dodaj wzór", w stopce <p> z numerem zdającego

    ok. 1 min
    Polecenie z arkusza

    Zawartość stopki: paragraf o treści „Autor strony: ”, dalej wstawiony numer zdającego.

    Na egzaminie w miejscu imienia i nazwiska wpisuje się numer zdającego, czyli PESEL; w tym rozwiązaniu stoi tam „Bartosz Bryniarski”. Strona ma już wszystkie nagłówki i paragraf stopki z klucza (R.2.6).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label><br>
            <input type="file" id="file" accept="image/png"><br>
            <label for="color">Kolor:</label><br>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select><br>
            <label for="price">Cena:</label><br>
            <input type="number" id="price"><br>
            <button onclick="addPattern()">Dodaj Wzór</button>
        </aside>
        <footer>
            <p>Autor strony: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  31. Etap 3: Styl CSS

    Kroki 31-40 · po tym etapie masz 31 z 39 kryteriów (pkt)

    Krok 31: Czcionka Dancing Script przez @font-face

    Kryteria:

    R.4.10 Czcionka Dancing Script działa na stronie, w stylach zdefiniowano dyrektywę @font-face, z rzeczywistymi ścieżkami URL w obu przypadkach

    ok. 3 min
    Polecenie z arkusza

    Styl CSS korzysta z kroju czcionki Dancing Script znajdującej się w folderze czcionki. Czcionkę należy dodać do projektu i zdefiniować jej stosowanie dla wariantu regular (normal). W pliku styl.css należy zapisać reguły dla czcionki. Przykład znajduje się w pliku stylesheet.css

    Reguła @font-face rejestruje czcionkę pod nazwą „Dancing Script” i mówi, skąd ją pobrać. Wzór to stylesheet.css z folderu czcionki - z jedną zmianą, o której przypomina komentarz w tym pliku („add proper URL path if needed”): pliki czcionki leżą obok styl.css, więc ścieżki w url() to same nazwy plików. Dwa źródła, bo przeglądarka bierze pierwszy format, który zna (woff2 jest mniejszy, woff - dla starszych). font-weight: normal i font-style: normal to wariant regular. Klucz sprawdza, czy czcionka naprawdę działa na stronie i czy obie ścieżki są prawdziwe (R.4.10).

    Typowe błędy

    Ścieżka url("czcionki/...") przy plikach skopiowanych obok strony (albo odwrotnie) nie wczytuje czcionki - strona pokazuje wtedy krój zapasowy i R.4.10 przepada.

    styl.css CSS nowy plik
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
    }
    Podgląd strony po tym kroku (index.html)
  32. Krok 32: Ciało strony: czcionka, rozmiar, wyśrodkowanie

    Kryteria:

    R.4.1 styl selektora body: krój czcionki "Dancing Script", serif (dozwolona tylko taka kolejność ), rozmiar czcionki 120%, wyrównanie tekstu do środka

    ok. 1 min
    Polecenie z arkusza

    Dla selektora ciała strony: krój czcionki Dancing Script, w przypadku braku serif, rozmiar czcionki 120%, wyrównanie tekstu do środka

    Nazwa w font-family musi być taka sama jak w @font-face. serif to rodzina zapasowa (krój szeryfowy), gdyby plik czcionki się nie wczytał - klucz dopuszcza tylko taką kolejność. Selektor to sam znacznik body, jak każe uwaga arkusza. Od tego kroku wszystkie napisy na stronie są pisane odręcznym krojem.

    styl.css CSS zmienione: 5 linii
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
    }
    body {
        font-family: "Dancing Script", serif;
        font-size: 120%;
        text-align: center;
    }
    Podgląd strony po tym kroku (index.html)
  33. Krok 33: Blok nagłówkowy 1 i boczny: tło i szerokość

    ok. 1 min
    Polecenie z arkusza

    Dla bloków nagłówkowego 1 i bocznego: kolor tła RosyBrown, szerokość 30%

    Dwa selektory po przecinku dostają te same właściwości. RosyBrown to nazwana barwa CSS (przygaszony róż).

    styl.css CSS zmienione: 4 linie
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
    }
    body {
        font-family: "Dancing Script", serif;
        font-size: 120%;
        text-align: center;
    }
    #logo, aside {
        background-color: RosyBrown;
        width: 30%;
    }
    Podgląd strony po tym kroku (index.html)
  34. Krok 34: Blok boczny: tekst do lewej, wysokość

    Kryteria:

    R.4.5 wyrównanie tekstu: blok boczny - do lewej strony

    ok. 1 min
    Polecenie z arkusza

    Dodatkowo dla bloku bocznego: wyrównanie tekstu do lewej strony, wysokość 350 px

    Druga reguła dla aside dokłada właściwości do poprzedniej. text-align: left nadpisuje wyśrodkowanie odziedziczone z body - formularz stoi przy lewej krawędzi.

    styl.css CSS zmienione: 4 linie
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
    }
    body {
        font-family: "Dancing Script", serif;
        font-size: 120%;
        text-align: center;
    }
    #logo, aside {
        background-color: RosyBrown;
        width: 30%;
    }
    aside {
        text-align: left;
        height: 350px;
    }
    Podgląd strony po tym kroku (index.html)
  35. Krok 35: Blok nagłówkowy 2: tło, szerokość, wysokość

    Kryteria:

    R.4.2 kolor tła: oba bloki nagłówkowe, blok boczny - RosyBrown

    ok. 1 min
    Polecenie z arkusza

    Dla bloku nagłówkowego 2: kolor tła RosyBrown, szerokość 70%, wysokość 100 px

    Tym krokiem oba bloki nagłówkowe i blok boczny mają tło RosyBrown (R.4.2).

    styl.css CSS zmienione: 5 linii
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
    }
    body {
        font-family: "Dancing Script", serif;
        font-size: 120%;
        text-align: center;
    }
    #logo, aside {
        background-color: RosyBrown;
        width: 30%;
    }
    aside {
        text-align: left;
        height: 350px;
    }
    #studio {
        background-color: RosyBrown;
        width: 70%;
        height: 100px;
    }
    Podgląd strony po tym kroku (index.html)
  36. Krok 36: Sekcja: wymiary i paski przewijania

    Kryteria: , ,

    R.4.3 szerokość: blok nagłówkowy 1, boczny - 30%, blok nagłówkowy 2, blok sekcji - 70% (width lub grid-template-columns lub flex )

    R.4.4 wysokość: blok nagłówkowy 2 - 100px, blok boczny - 350px, blok sekcji - 550px

    R.4.6 paski przewijania: blok sekcji - scroll

    ok. 2 min
    Polecenie z arkusza

    Dla bloku sekcji: szerokość 70%, wysokość 550 px, paski przewijania zawsze widoczne

    „Zawsze widoczne” to overflow: scroll - oba paski są rysowane nawet wtedy, gdy zawartość się mieści (ilustracja 2). overflow: auto pokazałby je dopiero po przepełnieniu galerii. Ten krok zamyka szerokości (30% i 70%) oraz wysokości z klucza (100, 350 i 550 px).

    styl.css CSS zmienione: 5 linii
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
    }
    body {
        font-family: "Dancing Script", serif;
        font-size: 120%;
        text-align: center;
    }
    #logo, aside {
        background-color: RosyBrown;
        width: 30%;
    }
    aside {
        text-align: left;
        height: 350px;
    }
    #studio {
        background-color: RosyBrown;
        width: 70%;
        height: 100px;
    }
    section {
        width: 70%;
        height: 550px;
        overflow: scroll;
    }
    Podgląd strony po tym kroku (index.html)
  37. Krok 37: Układ bloków zgodny z ilustracją 3

    Kryteria:

    R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z ilustracją 3 w arkuszu egzaminacyjnym (prawidłowo zastosowano właściwości CSS decydujące o układzie bloków na stronie, np. float i clear albo display flex albo grid albo position)

    ok. 3 min
    Polecenie z arkusza

    Podział strony na bloki zrealizowany za pomocą semantycznych znaczników bloków języka HTML5 tak, aby po uruchomieniu w przeglądarce układ bloków na stronie był zgodny z ilustracją 3

    Ilustracja 3 to dwie kolumny: po lewej logo i blok boczny, po prawej nazwa studia i sekcja. Najprościej oddać to dwoma kierunkami pływania: lewa kolumna float: left, prawa float: right. Bloki płynące w tę samą stronę układają się jeden pod drugim (blok boczny pod logo, sekcja pod nazwą studia), a 30% + 70% mieści się w jednym rzędzie. Gdyby wszystkie cztery bloki płynęły w lewo, blok boczny - sprawdzone w Chrome - spadłby aż pod sekcję, bo pływający element nie może stanąć na lewo od wcześniejszego elementu płynącego w tę samą stronę, jeśli nie zaczyna się poniżej jego dolnej krawędzi. Stopka z clear: both zaczyna się pod najniższą kolumną.

    styl.css CSS zmienione: 9 linii
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
    }
    body {
        font-family: "Dancing Script", serif;
        font-size: 120%;
        text-align: center;
    }
    #logo, aside {
        background-color: RosyBrown;
        width: 30%;
    }
    aside {
        text-align: left;
        height: 350px;
    }
    #studio {
        background-color: RosyBrown;
        width: 70%;
        height: 100px;
    }
    section {
        width: 70%;
        height: 550px;
        overflow: scroll;
    }
    #logo, aside {
        float: left;
    }
    #studio, section {
        float: right;
    }
    footer {
        clear: both;
    }
    Podgląd strony po tym kroku (index.html)
  38. Krok 38: Etykiety: wysokość linii

    Kryteria:

    R.4.7 wysokość linii: selektor label - 50px (line-height)

    ok. 1 min
    Polecenie z arkusza

    Dla selektora etykiety: wysokość linii 50 px

    line-height: 50px rozsuwa formularz w pionie - każda etykieta zajmuje linię wysoką na 50 px.

    styl.css CSS zmienione: 3 linie
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
    }
    body {
        font-family: "Dancing Script", serif;
        font-size: 120%;
        text-align: center;
    }
    #logo, aside {
        background-color: RosyBrown;
        width: 30%;
    }
    aside {
        text-align: left;
        height: 350px;
    }
    #studio {
        background-color: RosyBrown;
        width: 70%;
        height: 100px;
    }
    section {
        width: 70%;
        height: 550px;
        overflow: scroll;
    }
    #logo, aside {
        float: left;
    }
    #studio, section {
        float: right;
    }
    footer {
        clear: both;
    }
    label {
        line-height: 50px;
    }
    Podgląd strony po tym kroku (index.html)
  39. Krok 39: Klasa miniatury: szerokość

    Kryteria:

    R.4.8 styl klasy .miniatury : szerokość 150px

    ok. 1 min
    Polecenie z arkusza

    Dla klasy miniatury przypisanej do obrazów generowanych skryptem: szerokość 150 px

    Selektor klasy z kropką. Wysokość obrazu przeglądarka liczy sama z proporcji, więc smok i koliber zmniejszają się bez zniekształceń. Te same 150 px dostaną obrazy dodane skryptem.

    styl.css CSS zmienione: 3 linie
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
    }
    body {
        font-family: "Dancing Script", serif;
        font-size: 120%;
        text-align: center;
    }
    #logo, aside {
        background-color: RosyBrown;
        width: 30%;
    }
    aside {
        text-align: left;
        height: 350px;
    }
    #studio {
        background-color: RosyBrown;
        width: 70%;
        height: 100px;
    }
    section {
        width: 70%;
        height: 550px;
        overflow: scroll;
    }
    #logo, aside {
        float: left;
    }
    #studio, section {
        float: right;
    }
    footer {
        clear: both;
    }
    label {
        line-height: 50px;
    }
    .miniatury {
        width: 150px;
    }
    Podgląd strony po tym kroku (index.html)
  40. Krok 40: Miniatura pod kursorem: tło i powiększenie z przejściem

    Kryteria:

    R.4.9 gdy kursor znajdzie się na elemencie z przypisaną klasą miniatury , kolor jego tła zmienia się na Bisque, a szerokość na 200px. Widoczna jest animacja powiększania się elementu (transition: width 1s;)

    ok. 2 min
    Polecenie z arkusza

    W momencie, gdy kursor znajdzie się na elemencie z przypisaną klasą miniatury, kolor jego tła zmienia się na Bisque, a szerokość na 200 px. Zmiana szerokości ma zdefiniowane przejście z czasem trwania 1 s (ilustracja 4)

    Pseudoklasa :hover zmienia tło i szerokość. Tło widać w przezroczystych miejscach obrazu PNG - stąd beżowy prostokąt wokół kolibra na ilustracji 4. transition: width 1s stoi w zwykłej regule .miniatury, nie w :hover: wtedy przejście działa w obie strony - obraz powiększa się przez sekundę i tak samo płynnie wraca do 150 px po zjechaniu kursora.

    styl.css CSS zmienione: 5 linii
    @font-face {
        font-family: "Dancing Script";
        src: url("DancingScript-Regular.woff2") format("woff2"),
             url("DancingScript-Regular.woff") format("woff");
        font-weight: normal;
        font-style: normal;
    }
    body {
        font-family: "Dancing Script", serif;
        font-size: 120%;
        text-align: center;
    }
    #logo, aside {
        background-color: RosyBrown;
        width: 30%;
    }
    aside {
        text-align: left;
        height: 350px;
    }
    #studio {
        background-color: RosyBrown;
        width: 70%;
        height: 100px;
    }
    section {
        width: 70%;
        height: 550px;
        overflow: scroll;
    }
    #logo, aside {
        float: left;
    }
    #studio, section {
        float: right;
    }
    footer {
        clear: both;
    }
    label {
        line-height: 50px;
    }
    .miniatury {
        width: 150px;
        transition: width 1s;
    }
    .miniatury:hover {
        background-color: Bisque;
        width: 200px;
    }
    Podgląd strony po tym kroku (index.html)
  41. Etap 4: JavaScript

    Kroki 41-46 · po tym etapie masz 39 z 39 kryteriów (pkt)

    Krok 41: Funkcja addPattern: odczyt danych z kontrolek

    Kryteria: ,

    R.5.1 Skrypt napisano w języku JavaScript i zawiera on przynajmniej jedną poprawną składniowo instrukcję wynikającą z treści zadania

    R.5.2 Skrypt pobiera dane z przynajmniej jednej kontrolki, np. zastosowano funkcję document.getElementById z parametrem, który zdefiniowano w kontrolce jako id

    ok. 2 min
    Polecenie z arkusza

    Pobiera dane z kontrolek

    Skrypt stoi w znaczniku <script> na końcu <body> - wykonuje się po stronie klienta, w przeglądarce. Funkcja addPattern to ta, którą wywołuje onclick przycisku. document.getElementById znajduje kontrolkę po identyfikatorze, a .value oddaje jej zawartość: z pola pliku ścieżkę, z listy tekst wybranej opcji, z pola liczbowego wpisaną cenę (jako tekst). Funkcja jeszcze nic nie wyświetla.

    index.html HTML zmienione: 7 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label><br>
            <input type="file" id="file" accept="image/png"><br>
            <label for="color">Kolor:</label><br>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select><br>
            <label for="price">Cena:</label><br>
            <input type="number" id="price"><br>
            <button onclick="addPattern()">Dodaj Wzór</button>
        </aside>
        <footer>
            <p>Autor strony: Bartosz Bryniarski</p>
        </footer>
        <script>
            function addPattern() {
                let path = document.getElementById("file").value;
                let color = document.getElementById("color").value;
                let price = document.getElementById("price").value;
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  42. Krok 42: Nazwa pliku bez ścieżki dostępu

    Kryteria:

    R.5.3 Nazwa pliku jest ustalana poprzez usunięcie ścieżki dostępu

    ok. 2 min
    Polecenie z arkusza

    Ustala nazwę pliku (bez ścieżki dostępu) na podstawie wartości przekazanej z pola do wyboru pliku

    Przeglądarka nie zdradza stronie prawdziwej ścieżki - pole pliku oddaje C:\fakepath\rozeta.png (ramka pod tabelą 1). lastIndexOf("\\") szuka ostatniego ukośnika wstecznego (w napisie JavaScript zapisuje się go podwójnie, bo pojedynczy rozpoczyna znak specjalny), a substring od pozycji tuż za nim zwraca resztę: rozeta.png.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label><br>
            <input type="file" id="file" accept="image/png"><br>
            <label for="color">Kolor:</label><br>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select><br>
            <label for="price">Cena:</label><br>
            <input type="number" id="price"><br>
            <button onclick="addPattern()">Dodaj Wzór</button>
        </aside>
        <footer>
            <p>Autor strony: Bartosz Bryniarski</p>
        </footer>
        <script>
            function addPattern() {
                let path = document.getElementById("file").value;
                let color = document.getElementById("color").value;
                let price = document.getElementById("price").value;
                let fileName = path.substring(path.lastIndexOf("\\") + 1);
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  43. Krok 43: Komunikat z nazwą pliku, kolorem i ceną

    Kryteria:

    R.5.4 Skrypt wyświetla komunikat: "Wzór: <nazwaPliku>, kolor <kolor> w cenie <cena> zł", gdzie wartości pól <> pobrano z kontrolek (nazwa pliku ze ścieżką lub bez)

    ok. 2 min
    Polecenie z arkusza

    Wyświetla komunikat: "Wzór: <nazwaPliku>, kolor <kolor> w cenie <cena> zł" gdzie pola <> pobrano z kontrolek oraz nazwa pliku nie zawiera ścieżki dostępu (Ilustracja 5)

    alert wyświetla okno „Komunikat z bieżącej strony” z ilustracji 5. Napis jest sklejony operatorem + z kawałków stałych i trzech zmiennych - spacje i przecinek muszą stać w kawałkach stałych. Sprawdzone w Chrome: po wybraniu rozeta.png, koloru „Zielony” i ceny 70 komunikat brzmi „Wzór: rozeta.png, kolor Zielony w cenie 70 zł”.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label><br>
            <input type="file" id="file" accept="image/png"><br>
            <label for="color">Kolor:</label><br>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select><br>
            <label for="price">Cena:</label><br>
            <input type="number" id="price"><br>
            <button onclick="addPattern()">Dodaj Wzór</button>
        </aside>
        <footer>
            <p>Autor strony: Bartosz Bryniarski</p>
        </footer>
        <script>
            function addPattern() {
                let path = document.getElementById("file").value;
                let color = document.getElementById("color").value;
                let price = document.getElementById("price").value;
                let fileName = path.substring(path.lastIndexOf("\\") + 1);
                alert("Wzór: " + fileName + ", kolor " + color + " w cenie " + price + " zł");
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  44. Krok 44: Nowy element obrazu z nazwą pliku

    Kryteria:

    R.5.5 Skrypt tworzy element img ze źródłem i tekstem alternatywnym jak nazwa pliku (nazwa pliku ze ścieżką lub bez)

    ok. 2 min
    Polecenie z arkusza

    Tworzy element obrazu i dodaje go do bloku sekcji (ilustracja 6): Źródłem i tekstem alternatywnym jest nazwa pliku

    document.createElement("img") tworzy obraz w pamięci - jeszcze go nie widać. Atrybuty ustawia się jak pola obiektu (element.attribute_name = "wartość" z tabeli 1): źródło i tekst alternatywny to nazwa pliku bez ścieżki. Dlatego wzory leżą w folderze strony - przeglądarka szuka rozeta.png obok index.html.

    index.html HTML zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label><br>
            <input type="file" id="file" accept="image/png"><br>
            <label for="color">Kolor:</label><br>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select><br>
            <label for="price">Cena:</label><br>
            <input type="number" id="price"><br>
            <button onclick="addPattern()">Dodaj Wzór</button>
        </aside>
        <footer>
            <p>Autor strony: Bartosz Bryniarski</p>
        </footer>
        <script>
            function addPattern() {
                let path = document.getElementById("file").value;
                let color = document.getElementById("color").value;
                let price = document.getElementById("price").value;
                let fileName = path.substring(path.lastIndexOf("\\") + 1);
                alert("Wzór: " + fileName + ", kolor " + color + " w cenie " + price + " zł");
                let image = document.createElement("img");
                image.src = fileName;
                image.alt = fileName;
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  45. Krok 45: Klasa miniatury dla nowego obrazu

    Kryteria:

    R.5.7 Utworzony element img ma przypisaną klasę miniatury (sprawdzić w inspektorze)

    ok. 1 min
    Polecenie z arkusza

    Obraz ma przypisaną klasę miniatury

    W JavaScripcie atrybut class ustawia pole className (słowo class jest w tym języku zarezerwowane). Działa też image.setAttribute("class", "miniatury") z tabeli 1. Dzięki klasie nowy obraz ma 150 px szerokości i reaguje na kursor jak smok i koliber.

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label><br>
            <input type="file" id="file" accept="image/png"><br>
            <label for="color">Kolor:</label><br>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select><br>
            <label for="price">Cena:</label><br>
            <input type="number" id="price"><br>
            <button onclick="addPattern()">Dodaj Wzór</button>
        </aside>
        <footer>
            <p>Autor strony: Bartosz Bryniarski</p>
        </footer>
        <script>
            function addPattern() {
                let path = document.getElementById("file").value;
                let color = document.getElementById("color").value;
                let price = document.getElementById("price").value;
                let fileName = path.substring(path.lastIndexOf("\\") + 1);
                alert("Wzór: " + fileName + ", kolor " + color + " w cenie " + price + " zł");
                let image = document.createElement("img");
                image.src = fileName;
                image.alt = fileName;
                image.className = "miniatury";
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  46. Krok 46: Dodanie obrazu do galerii

    Kryteria: ,

    R.5.6 Utworzony element img jest wyświetlany w bloku sekcji

    R.5.8 W skryptach zastosowana przynajmniej jedna zmienna lub funkcja oraz nazwy wszystkich funkcji i zmiennych są w języku polskim lub angielskim i odzwierciedlają cel zastosowania

    ok. 1 min
    Polecenie z arkusza

    Tworzy element obrazu i dodaje go do bloku sekcji (ilustracja 6)

    appendChild wstawia obraz jako ostatnie dziecko sekcji gallery - za smokiem, kolibrem i wcześniej dodanymi wzorami, jak na ilustracji 6. Gdy obrazy przestaną się mieścić, pojawi się przewijanie sekcji. Zmienne (path, fileName, color, price, image) i funkcja mają nazwy mówiące, co robią (R.5.8).

    index.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label><br>
            <input type="file" id="file" accept="image/png"><br>
            <label for="color">Kolor:</label><br>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select><br>
            <label for="price">Cena:</label><br>
            <input type="number" id="price"><br>
            <button onclick="addPattern()">Dodaj Wzór</button>
        </aside>
        <footer>
            <p>Autor strony: Bartosz Bryniarski</p>
        </footer>
        <script>
            function addPattern() {
                let path = document.getElementById("file").value;
                let color = document.getElementById("color").value;
                let price = document.getElementById("price").value;
                let fileName = path.substring(path.lastIndexOf("\\") + 1);
                alert("Wzór: " + fileName + ", kolor " + color + " w cenie " + price + " zł");
                let image = document.createElement("img");
                image.src = fileName;
                image.alt = fileName;
                image.className = "miniatury";
                document.getElementById("gallery").appendChild(image);
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  47. Etap 5: Dobre praktyki (poza kluczem)

    Kroki 47-48 · po tym etapie masz 39 z 39 kryteriów (pkt)

    Krok 47: Nasłuchiwacz zdarzenia zamiast onclick

    ok. 2 min
    Polecenie z arkusza

    Wykonywany po stronie klienta, po kliknięciu przycisku

    Atrybut onclick miesza HTML z JavaScriptem. W prawdziwych projektach przycisk dostaje identyfikator (add), a zdarzenie podpina skrypt: addEventListener("click", addPattern) - bez nawiasów po nazwie funkcji, bo przekazuje się samą funkcję, a nie wynik jej wywołania. Skrypt stoi na końcu <body>, więc przycisk już istnieje, gdy ta linia się wykonuje. Na egzaminie wystarczy wersja wcześniejsza - klucz uznaje oba sposoby (R.3.3).

    index.html HTML zmienione: 4 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label><br>
            <input type="file" id="file" accept="image/png"><br>
            <label for="color">Kolor:</label><br>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select><br>
            <label for="price">Cena:</label><br>
            <input type="number" id="price"><br>
            <button id="add">Dodaj Wzór</button>
        </aside>
        <footer>
            <p>Autor strony: Bartosz Bryniarski</p>
        </footer>
        <script>
            // <button onclick="addPattern()"> zastąpione nasłuchiwaczem zdarzenia
            document.getElementById("add").addEventListener("click", addPattern);
    
            function addPattern() {
                let path = document.getElementById("file").value;
                let color = document.getElementById("color").value;
                let price = document.getElementById("price").value;
                let fileName = path.substring(path.lastIndexOf("\\") + 1);
                alert("Wzór: " + fileName + ", kolor " + color + " w cenie " + price + " zł");
                let image = document.createElement("img");
                image.src = fileName;
                image.alt = fileName;
                image.className = "miniatury";
                document.getElementById("gallery").appendChild(image);
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  48. Krok 48: Puste pola i nazwa pliku z obiektu File

    ok. 3 min
    Polecenie z arkusza

    Ustala nazwę pliku (bez ścieżki dostępu) na podstawie wartości przekazanej z pola do wyboru pliku

    Wersja egzaminacyjna sprawdzona w Chrome z pustym formularzem: komunikat brzmi „Wzór: , kolor Zielony w cenie zł”, a do galerii trafia obraz bez źródła - pusta miniatura, którą widać dopiero po najechaniu kursorem (beżowe tło). Poprawki: warunek na początku funkcji sprawdza, czy wybrano plik i wpisano cenę, a jeśli nie - wyświetla prośbę i kończy funkcję (return). Nazwę pliku zamiast wycinać ze ścieżki C:\fakepath\rozeta.png daje wprost files[0].name - pole pliku przechowuje listę wybranych plików (File API z ramki pod tabelą 1). Stare linie zostają w komentarzu. Na egzaminie wystarczy wersja wcześniejsza - klucz tego nie sprawdza.

    index.html HTML zmienione: 8 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <title>Tatuaże</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header id="logo">
            <img src="logo.png" alt="salon">
        </header>
        <header id="studio">
            <h1>Studio Tatuażu</h1>
        </header>
        <section id="gallery">
            <h2>Galeria</h2>
            <img src="smok.png" alt="smok.png" class="miniatury">
            <img src="koliber.png" alt="koliber.png" class="miniatury">
        </section>
        <aside>
            <h3>Dodaj wzór</h3>
            <label for="file">Wzór:</label><br>
            <input type="file" id="file" accept="image/png"><br>
            <label for="color">Kolor:</label><br>
            <select id="color">
                <option>Czarny</option>
                <option>Czerwony</option>
                <option>Zielony</option>
                <option>Niebieski</option>
            </select><br>
            <label for="price">Cena:</label><br>
            <input type="number" id="price"><br>
            <button id="add">Dodaj Wzór</button>
        </aside>
        <footer>
            <p>Autor strony: Bartosz Bryniarski</p>
        </footer>
        <script>
            // <button onclick="addPattern()"> zastąpione nasłuchiwaczem zdarzenia
            document.getElementById("add").addEventListener("click", addPattern);
    
            function addPattern() {
                let fileInput = document.getElementById("file");
                let color = document.getElementById("color").value;
                let price = document.getElementById("price").value;
                if (fileInput.files.length == 0 || price == "") {
                    alert("Wybierz plik wzoru i wpisz cenę.");
                    return;
                }
                let fileName = fileInput.files[0].name;
                // let path = document.getElementById("file").value;
                // let fileName = path.substring(path.lastIndexOf("\\") + 1);
                alert("Wzór: " + fileName + ", kolor " + color + " w cenie " + price + " zł");
                let image = document.createElement("img");
                image.src = fileName;
                image.alt = fileName;
                image.className = "miniatury";
                document.getElementById("gallery").appendChild(image);
            }
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (index.html)
  49. Etap 6: Oddanie pracy

    Krok 49 · po tym etapie masz 39 z 39 kryteriów (pkt)

    Krok 49: Plik przeglądarka.txt i nagranie płyty

    ok. 5 min
    Polecenie z arkusza

    Po zakończeniu pracy utwórz plik tekstowy o nazwie przeglądarka.txt. Zapisz w nim nazwę przeglądarki internetowej, w której weryfikowana była poprawność działania witryny. Umieść go w folderze z numerem zdającego. Nagraj płytę z rezultatami pracy.

    W przeglądarka.txt wystarczy nazwa przeglądarki, w której była sprawdzana strona.

    W folderze z numerem zdającego: angel.png, celtic.png, czcionka.jpg, DancingScript-Regular.woff, DancingScript-Regular.woff2, delfin.png, import.png, index.html, koliber.png, kw1.png - kw4.png, kwerendy.txt, kwiat.png, kwiaty.png, logo.png, przeglądarka.txt, rozeta.png, smok.png, styl.css, tygrys.png, waz.png. Po nagraniu płyty trzeba sprawdzić jej odczyt i opisać ją numerem zdającego.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

    Podgląd strony bez zmian - taki jak po kroku 48.

Podgląd

To jedno z możliwych rozwiązań. Egzaminator ocenia spełnienie kryteriów z klucza odpowiedzi, a nie zgodność z tym kodem - inna, poprawna droga też daje punkty.

Autor rozwiązania: . Licencja CC BY-NC 4.0 - kopiowanie i przeróbki do celów niekomercyjnych, z podaniem autora i źródła (link do tej strony) (zasady wykorzystania). Treść arkusza i klucza oceniania pochodzi z CKE.