Przejdź do głównej treści
INF.03-12-24.06-SGCzerwiec 2024 · 36 kroków · ok. 69 min · 41 kryteriów z klucza

Rozwiązanie krok po kroku: Filtry obrazów i baza pracowników (Nowoczesny kod (grid))

To drugi sposób rozwiązania tego samego arkusza. Wynik jest ten sam - baza baza z czterema zapytaniami, przeskalowane zdjęcie i strona obrazki.html z czterema blokami, w których skrypt nakłada na zdjęcia filtry CSS - i tak samo spełnia każde kryterium klucza. Inna jest droga:

  • siatka CSS: cztery bloki po dwa w rzędzie dzięki grid-template-columns: repeat(2, 50%) w <main> (klucz R.4.5 przyjmuje szerokość w tej postaci),
  • kolory w zmiennych CSS, płynna zmiana filtra (transition) i kolor pól formularza z arkusza (accent-color),
  • pola opcji z etykietami - kliknięcie w napis zaznacza pole - ułożone przez CSS, bez <br>; suwaki z opisem dla czytnika ekranu,
  • jedna funkcja applyFilter dla wszystkich bloków, filtry pól opcji w obiekcie, const, szablony tekstowe i addEventListener od początku,
  • SQL czytelniej: aliasy tabel, zaokrąglona średnia z nazwą kolumny, grupowanie po identyfikatorze stanowiska i sortowanie.

Na końcu krótkie porównanie z wersją podstawową (zakładka obok). Baza i zdjęcia pochodzą z prawdziwego archiwum pliki12, zapytania zostały wykonane na tej bazie w MariaDB z XAMPP-a, a skrypt jest sprawdzony w prawdziwej przeglądarce Chrome: każde pole opcji, oba przyciski bloku 2 i oba suwaki.

Jak liczą się punkty. Klucz ma 41 kryteriów (R.1.1 - R.5.10), każde za 1 punkt. Próg zdania to 75%, czyli 31 punktów. Przy każdym kroku jest napisane, które kryteria spełnia.

  1. Etap 1: Baza danych

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

    Krok 1: Baza danych baza

    ok. 2 min
    Polecenie z arkusza

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

    Archiwum pliki12.zip rozpakuj hasłem #TransfoRm@cje (krzyżyk na początku, wielkie T i R, małpa zamiast „a”) do folderu z numerem zdającego. W phpMyAdmin Nowa → baza (tak, baza nazywa się po prostu „baza”), porównywanie utf8_unicode_ci, albo zapytaniem:

    CREATE DATABASE baza CHARACTER SET utf8 COLLATE utf8_unicode_ci;
    
  2. Krok 2: Import tabel z pliku baza.sql

    ok. 2 min
    Polecenie z arkusza

    Do bazy zaimportuj tabele z pliku baza.sql z rozpakowanego archiwum

    Zaznaczona baza baza, Import → baza.sql. Dwie tabele z obrazu 1: pracownicy (imię, nazwisko, pensja, staż w latach, klucz obcy stanowiska_id) i stanowiska.

  3. Krok 3: Zrzut ekranu import.png

    Kryteria:

    R.1.1 Wykonano import tabel do bazy danych baza czynność udokumentowano plikiem o nazwie import w formacie PNG

    ok. 2 min
    Polecenie z arkusza

    Wykonaj zrzut ekranu po imporcie. Zrzut zapisz w formacie PNG i nazwij 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.

    Cały ekran z paskiem zadań, w PNG. Zrzuty zapytań idą do JPEG (kw1.jpg - kw4.jpg).

    Typowe błędy

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

  4. Krok 4: Zapytanie 1: staż krótszy niż 5 lat

    Kryteria: ,

    R.1.2 Zapisano plik kwerendy.txt zawierający co najmniej jedno zapytanie SQL, wynikające z treści zadania

    R.1.3 Wykonano zapytanie 1 wybierające jedynie imię i pensję pracowników ze stażem mniejszym niż 5 lat. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, pensja FROM pracownicy WHERE staz < 5; oraz wynik działania udokumentowano zrzutem, na którym są widoczne dokładnie 2 rekordy z danymi: Janusz 4700, Andżelika 4700 (na wynik może mieć wpływ wielokrotne wykonanie kwerendy 4)

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 1: wybierające jedynie imię i pensję pracowników ze stażem mniejszym niż 5 lat

    WHERE staz < 5 - „mniejszym niż”, bez równości. Wynik: 2 wiersze - Janusz i Andżelika, po 4700. Wykonaj je przed zapytaniem 4: po podniesieniu stażu wynik mógłby się zmienić (klucz o tym wspomina). Zapytania zapisz w kwerendy.txt, zrzut jako kw1.jpg.

    kwerendy.txt Tekst nowy plik
    -- Zapytanie 1
    SELECT imie, pensja
    FROM pracownicy
    WHERE staz < 5;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 4
  5. Krok 5: Zapytanie 2: średnia pensja na stanowisku

    Kryteria:

    R.1.4 Wykonano zapytanie 2 : liczące średnią pensję pracowników ze względu na rodzaj stanowiska. Zapytanie pokazuje średnią pensję na danym stanowisku i nazwę stanowiska. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT AVG(pensja), nazwa FROM pracownicy JOIN stanowiska ON stanowiska_id = stanowiska.id GROUP BY nazwa; (możliwe również INNER JOIN lub porównanie kluczy po WHERE) oraz wynik działania udokumentowano zrzutem, na którym jest widocznych dokładnie 5 rekordów z danymi (dowolne zaokrąglenie): 8000 Dyrektor, 5000 Kadrowa, 6000 Kierownik, 4890 Logistyk, 3920 Operator

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 2: liczące średnią pensję pracowników ze względu na rodzaj stanowiska. Zapytanie pokazuje średnią pensję na danym stanowisku i nazwę stanowiska. Należy posłużyć się relacją

    • ROUND(AVG(p.pensja), 2) AS sredniaPensja - średnia zaokrąglona do groszy i nazwana; bez aliasu kolumna nazywałaby się dosłownie AVG(pensja), a bez ROUND miałaby cztery miejsca po przecinku,
    • aliasy p i s, ON s.id = p.stanowiska_id - relacja przez klucz obcy,
    • GROUP BY s.id, s.nazwa - grupa to jedno stanowisko. Grupowanie po samej nazwie skleiłoby dwa różne stanowiska o tej samej nazwie; identyfikator jest jednoznaczny, a nazwa w GROUP BY pozwala ją wybrać w SELECT,
    • ORDER BY s.nazwa - stała kolejność wierszy.

    Wynik: 5 wierszy - Dyrektor 8000, Kadrowa 5000, Kierownik 6000, Logistyk 4890, Operator 3920 (klucz dopuszcza dowolne zaokrąglenie). Zrzut: kw2.jpg.

    Typowe błędy

    Bez GROUP BY zapytanie zwraca jedną średnią dla całej firmy - zrzut nie ma pięciu wierszy.

    kwerendy.txt Tekst zmienione: 7 linii
    -- Zapytanie 1
    SELECT imie, pensja
    FROM pracownicy
    WHERE staz < 5;
    
    -- Zapytanie 2
    SELECT ROUND(AVG(p.pensja), 2) AS sredniaPensja, s.nazwa
    FROM pracownicy AS p
    JOIN stanowiska AS s ON s.id = p.stanowiska_id
    GROUP BY s.id, s.nazwa
    ORDER BY s.nazwa;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 5
  6. Krok 6: Zapytanie 3: najwyższa pensja z podzapytania

    Kryteria:

    R.1.5 Wykonano zapytanie 3 wybierające jedynie imię, nazwisko i pensję pracownika, którego pensja jest najwyższa. Zapytanie musi mieć charakter uniwersalny, a najwyższa pensja powinna zostać wyliczona. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, nazwisko, pensja FROM pracownicy WHERE pensja = (SELECT MAX(pensja) FROM pracownicy); dopuszcza się również zastosowanie MAX(pensja) lub LIMIT 1 oraz wynik działania udokumentowano zrzutem, na którym jest widoczny dokładnie 1 rekord: Krzysztof Dobromilski 8000

    ok. 3 min
    Polecenie z arkusza

    Zapytanie 3: wybierające jedynie imię, nazwisko i pensję pracownika, którego pensja jest najwyższa. Zapytanie musi mieć charakter uniwersalny, a najwyższa pensja powinna zostać wyliczona np. przez zagnieżdżone zapytanie (podzapytanie)

    Podzapytanie (SELECT MAX(pensja) FROM pracownicy) zwraca jedną liczbę - najwyższą pensję - i warunek porównuje z nią każdy wiersz. To jest „uniwersalne”: 8000 nie jest wpisane na sztywno. Przewaga nad ORDER BY pensja DESC LIMIT 1 (klucz też go przyjmuje): przy dwóch osobach z tą samą najwyższą pensją podzapytanie pokaże obie, a LIMIT 1 - przypadkowo jedną. Wynik: Krzysztof Dobromilski, 8000. Zrzut: kw3.jpg.

    Typowe błędy

    WHERE pensja = 8000 daje dziś ten sam wynik, ale nie jest uniwersalne - klucz wymaga, żeby najwyższa pensja była wyliczona. Uwaga też na SELECT imie, nazwisko, MAX(pensja) FROM pracownicy: klucz go przyjmuje, ale imię i nazwisko pochodzą wtedy z pierwszego wiersza tabeli, a nie od osoby z najwyższą pensją - sprawdzone: po podwyżce Joanny Trojanowskiej do 9000 takie zapytanie pokazuje „Krzysztof Dobromilski 9000”, a wersja z podzapytaniem - Trojanowską.

    kwerendy.txt Tekst zmienione: 5 linii
    -- Zapytanie 1
    SELECT imie, pensja
    FROM pracownicy
    WHERE staz < 5;
    
    -- Zapytanie 2
    SELECT ROUND(AVG(p.pensja), 2) AS sredniaPensja, s.nazwa
    FROM pracownicy AS p
    JOIN stanowiska AS s ON s.id = p.stanowiska_id
    GROUP BY s.id, s.nazwa
    ORDER BY s.nazwa;
    
    -- Zapytanie 3
    SELECT imie, nazwisko, pensja
    FROM pracownicy
    WHERE pensja = (SELECT MAX(pensja) FROM pracownicy);
    Podgląd strony po tym kroku
    Podgląd strony po kroku 6
  7. Krok 7: Zapytanie 4: staż wszystkich większy o rok

    Kryteria:

    R.1.6 Wykonano zapytanie 4 aktualizujące staż wszystkich pracowników, nowa wartość stażu jest wyższa o jeden rok. W pliku z kwerendami lub na zrzucie istnieje zapis np.: UPDATE pracownicy SET staz = staz + 1; oraz wynik działania udokumentowano zrzutem, na którym widoczne jest poprawnie wykonane zapytanie lub dane ze zwiększonym stażem o 1

    ok. 2 min
    Polecenie z arkusza

    Zapytanie 4: aktualizujące staż wszystkich pracowników, nowa wartość stażu jest wyższa o jeden rok

    SET staz = staz + 1 - po prawej stronie stoi stara wartość pola, więc każdy wiersz dostaje swój staż powiększony o 1. Brak WHERE jest tu celowy: „wszystkich pracowników” - 14 zmienionych wierszy. Wykonaj je raz: każde kolejne kliknięcie dodaje następny rok. Zrzut: kw4.jpg.

    kwerendy.txt Tekst zmienione: 4 linie
    -- Zapytanie 1
    SELECT imie, pensja
    FROM pracownicy
    WHERE staz < 5;
    
    -- Zapytanie 2
    SELECT ROUND(AVG(p.pensja), 2) AS sredniaPensja, s.nazwa
    FROM pracownicy AS p
    JOIN stanowiska AS s ON s.id = p.stanowiska_id
    GROUP BY s.id, s.nazwa
    ORDER BY s.nazwa;
    
    -- Zapytanie 3
    SELECT imie, nazwisko, pensja
    FROM pracownicy
    WHERE pensja = (SELECT MAX(pensja) FROM pracownicy);
    
    -- Zapytanie 4
    UPDATE pracownicy
    SET staz = staz + 1;
    Podgląd strony po tym kroku
    Podgląd strony po kroku 7
  8. Etap 2: Grafika i strona HTML

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

    Krok 8: Grafika pszczola.jpg: szerokość 500 px

    Kryteria:

    R.2.1 Plik pszczola.jpg przeskalowano z zachowaniem proporcji do szerokości 500 px, odpowiadająca temu wysokość to 330 px (± 5 px)

    ok. 2 min
    Polecenie z arkusza

    Grafikę pszczola.jpg należy przeskalować z zachowaniem proporcji do szerokości 500 px.

    Grafika jest taka sama jak w wersji podstawowej. Oryginał ma 592 × 391 px; w GIMP-ie Obraz → Skaluj obraz, szerokość 500 px przy zamkniętym łańcuchu proporcji - wysokość wychodzi 330 px (klucz: 330 ±5), tyle co pozostałe trzy zdjęcia.

    Podgląd strony po tym kroku
    Podgląd strony po kroku 8
  9. Krok 9: Plik obrazki.html: HTML5, język, kodowanie

    Kryteria:

    R.2.2 Witrynę internetową zapisano w pliku obrazki.html oraz zapisano jawnie standard kodowania polskich znaków i deklarację HTML5 <!DOCTYPE HTML> i zadeklarowano język witryny polski np.<HTML lang="pl">. Strona zawiera sekcje head i body

    ok. 2 min
    Polecenie z arkusza

    Składa się ze strony o nazwie obrazki.html zapisanej w języku HTML5. Ustawiony język zawartości strony na polski. Jawnie zastosowany właściwy standard kodowania polskich znaków

    <!DOCTYPE html>, <html lang="pl"> i <meta charset="UTF-8"> jako pierwszy element <head> - razem R.2.2.

    obrazki.html HTML nowy plik
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  10. Krok 10: Tytuł strony

    Kryteria:

    R.2.3 Nadano tytuł stronie: Efekty obrazu

    ok. 1 min
    Polecenie z arkusza

    Tytuł strony widoczny na karcie przeglądarki: „Efekty obrazu”

    <title> i viewport. Uwaga: tytuł to „Efekty obrazu”, a nagłówek w banerze - „Efekty na obrazach”.

    obrazki.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Efekty obrazu</title>
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  11. Krok 11: Podpięcie arkusza stylów

    Kryteria:

    R.3.6 Strona zawiera działające połączenie z zewnętrznym arkuszem stylów o nazwie styl.css , formatowanie CSS pochodzi jedynie z tego arkusza Uwaga: kryterium to nie jest spełnione również, gdy zdający źle przypisał co najmniej jeden selektor do bloku (np. kropka zamiast #)

    ok. 1 min
    Polecenie z arkusza

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

    Całe formatowanie pochodzi ze styl.css (R.3.6). Skrypt zmienia style.filter zdjęć - to działanie skryptu, nie formatowanie zapisane w HTML-u.

    Typowe błędy

    Klucz odbiera R.3.6 także wtedy, gdy choć jeden selektor nie trafia w blok (np. kropka zamiast #).

    obrazki.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Efekty obrazu</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  12. Krok 12: Bloki: baner, cztery bloki, stopka

    Kryteria:

    R.2.4 Układ strony zdefiniowano dzieląc ją na bloki: banera, cztery bloki, oraz stopkę. Zastosowano semantyczne znaczniki sekcji HTML5 zgodnie z ich znaczeniem, w tym do części nagłówkowej - header, stopki - footer, dopuszcza się zagnieżdżenie bloków div w znacznikach semantycznych

    ok. 2 min
    Polecenie z arkusza

    Podział strony na baner, poniżej cztery bloki, na dole stopka. Podział zrealizowany wyłącznie za pomocą semantycznych znaczników sekcji języka HTML5 tak, aby po uruchomieniu w przeglądarce wygląd układu bloków był zgodny z obrazem 2

    Baner <header>, stopka <footer> (R.2.4), cztery bloki to <section> we wspólnym <main> - <main> będzie siatką, która ułoży je po dwa w rzędzie. Identyfikatory block1 - block4 pozwolą skryptowi znaleźć blok, a w nim zdjęcie, pole i przycisk.

    obrazki.html HTML zmienione: 14 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Efekty obrazu</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
        </header>
        <main>
            <section id="block1">
            </section>
            <section id="block2">
            </section>
            <section id="block3">
            </section>
            <section id="block4">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  13. Krok 13: Baner: nagłówek drugiego stopnia

    ok. 1 min
    Polecenie z arkusza

    Zawartość banera: nagłówek drugiego stopnia o treści „Efekty na obrazach”

    <h2>, jak każe arkusz.

    obrazki.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Efekty obrazu</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Efekty na obrazach</h2>
        </header>
        <main>
            <section id="block1">
            </section>
            <section id="block2">
            </section>
            <section id="block3">
            </section>
            <section id="block4">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  14. Krok 14: Blok 1: zdjęcie pszczoły

    ok. 1 min
    Polecenie z arkusza

    Zawartość pierwszego bloku: Obraz pszczola.jpg z tekstem alternatywnym o treści „pszczoła na fioletowym kwiatku”

    Obraz bez identyfikatora - skrypt znajdzie go jako jedyny obraz w bloku #block1.

    obrazki.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Efekty obrazu</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Efekty na obrazach</h2>
        </header>
        <main>
            <section id="block1">
                <img src="pszczola.jpg" alt="pszczoła na fioletowym kwiatku">
            </section>
            <section id="block2">
            </section>
            <section id="block3">
            </section>
            <section id="block4">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  15. Krok 15: Blok 1: trzy pola opcji w jednej grupie

    Kryteria: ,

    R.2.7 W bloku pierwszym umieszczono trzy pola typu radio: "Blur", "Sepia", "Negatyw"

    R.3.3 Pola typu radio są zgrupowane tak, że jednocześnie może być wybrane tylko jedno z nich

    ok. 3 min
    Polecenie z arkusza

    Poniżej trzy pola opcji: „Blur”, „Sepia” i „Negatyw”, zgrupowane tak, że jednocześnie może być wybrane tylko jedno pole

    • grupę tworzy wspólne name="effect" - przeglądarka pozwala zaznaczyć tylko jedno pole z grupy (R.3.3),
    • każde pole stoi wewnątrz <label> z napisem: kliknięcie w „Sepia” zaznacza pole, a czytnik ekranu odczyta nazwę pola,
    • value mówi, który efekt pole oznacza (blur, sepia, invert) - skrypt nie potrzebuje identyfikatorów pól,
    • <div role="radiogroup" aria-label="..."> nazywa całą grupę dla czytnika ekranu.

    Pod sobą ustawi je CSS - bez <br> (R.2.7).

    Typowe błędy

    Trzy różne wartości name (albo brak name) pozwalają zaznaczyć wszystkie trzy pola naraz - punkt za grupowanie przepada.

    obrazki.html HTML zmienione: 5 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Efekty obrazu</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Efekty na obrazach</h2>
        </header>
        <main>
            <section id="block1">
                <img src="pszczola.jpg" alt="pszczoła na fioletowym kwiatku">
                <div role="radiogroup" aria-label="Efekt dla zdjęcia pszczoły">
                    <label><input type="radio" name="effect" value="blur"> Blur</label>
                    <label><input type="radio" name="effect" value="sepia"> Sepia</label>
                    <label><input type="radio" name="effect" value="invert"> Negatyw</label>
                </div>
            </section>
            <section id="block2">
            </section>
            <section id="block3">
            </section>
            <section id="block4">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  16. Krok 16: Blok 1: przycisk „Zastosuj”

    ok. 1 min
    Polecenie z arkusza

    Poniżej przycisk „Zastosuj”, którego kliknięcie powoduje transformacje obrazu 1

    <button type="button"> - przycisk niczego nie wysyła, tylko uruchomi skrypt.

    obrazki.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Efekty obrazu</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Efekty na obrazach</h2>
        </header>
        <main>
            <section id="block1">
                <img src="pszczola.jpg" alt="pszczoła na fioletowym kwiatku">
                <div role="radiogroup" aria-label="Efekt dla zdjęcia pszczoły">
                    <label><input type="radio" name="effect" value="blur"> Blur</label>
                    <label><input type="radio" name="effect" value="sepia"> Sepia</label>
                    <label><input type="radio" name="effect" value="invert"> Negatyw</label>
                </div>
                <button type="button">Zastosuj</button>
            </section>
            <section id="block2">
            </section>
            <section id="block3">
            </section>
            <section id="block4">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  17. Krok 17: Blok 2: zdjęcie i dwa przyciski

    ok. 2 min
    Polecenie z arkusza

    Zawartość drugiego bloku: Obraz pomarancza.jpg z tekstem alternatywnym o treści „drzewo pomarańczy”. Poniżej przycisk „Kolorowy” oraz przycisk „Czarno-biały”, ich kliknięcie powoduje transformację obrazu 2

    Zdjęcie i dwa przyciski z identyfikatorami colorButton i grayButton. Uwaga: w opisie skryptu arkusz nazywa pierwszy przycisk „Kolory”, a w zawartości bloku i w kluczu (R.2.8) jest „Kolorowy” - ta nazwa trafia na przycisk.

    obrazki.html HTML zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Efekty obrazu</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Efekty na obrazach</h2>
        </header>
        <main>
            <section id="block1">
                <img src="pszczola.jpg" alt="pszczoła na fioletowym kwiatku">
                <div role="radiogroup" aria-label="Efekt dla zdjęcia pszczoły">
                    <label><input type="radio" name="effect" value="blur"> Blur</label>
                    <label><input type="radio" name="effect" value="sepia"> Sepia</label>
                    <label><input type="radio" name="effect" value="invert"> Negatyw</label>
                </div>
                <button type="button">Zastosuj</button>
            </section>
            <section id="block2">
                <img src="pomarancza.jpg" alt="drzewo pomarańczy">
                <button type="button" id="colorButton">Kolorowy</button>
                <button type="button" id="grayButton">Czarno-biały</button>
            </section>
            <section id="block3">
            </section>
            <section id="block4">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  18. Krok 18: Blok 3: zdjęcie, suwak 0-100 i przycisk

    Kryteria:

    R.3.4 Przynajmniej jedno pole typu range ma ustawione wartości min=0 oraz max=100 (blok 3) lub max=250 (blok 4) oraz suwak w bloku 3 ma ustawione value=100

    ok. 2 min
    Polecenie z arkusza

    Zawartość trzeciego bloku: Obraz owoce.jpg z tekstem alternatywnym o treści „Kosz pełen owoców”. Poniżej pole edycyjne w postaci suwaka z wartością minimalną 0 i maksymalną 100, wartość ustawiona w stanie początkowym to 100. Poniżej przycisk „Zastosuj”, którego kliknięcie powoduje transformację obrazu 3

    Suwak <input type="range"> z min="0", max="100" i value="100" - startuje przy prawej krawędzi (R.3.4). Suwak nie ma widocznego podpisu, więc aria-label mówi czytnikowi ekranu, co ustawia.

    Typowe błędy

    Bez value="100" suwak staje na środku (połowa zakresu) - klucz wymaga wartości początkowej 100.

    obrazki.html HTML zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Efekty obrazu</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Efekty na obrazach</h2>
        </header>
        <main>
            <section id="block1">
                <img src="pszczola.jpg" alt="pszczoła na fioletowym kwiatku">
                <div role="radiogroup" aria-label="Efekt dla zdjęcia pszczoły">
                    <label><input type="radio" name="effect" value="blur"> Blur</label>
                    <label><input type="radio" name="effect" value="sepia"> Sepia</label>
                    <label><input type="radio" name="effect" value="invert"> Negatyw</label>
                </div>
                <button type="button">Zastosuj</button>
            </section>
            <section id="block2">
                <img src="pomarancza.jpg" alt="drzewo pomarańczy">
                <button type="button" id="colorButton">Kolorowy</button>
                <button type="button" id="grayButton">Czarno-biały</button>
            </section>
            <section id="block3">
                <img src="owoce.jpg" alt="Kosz pełen owoców">
                <input type="range" min="0" max="100" value="100" id="opacityRange" aria-label="Przezroczystość zdjęcia (%)">
                <button type="button">Zastosuj</button>
            </section>
            <section id="block4">
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  19. Krok 19: Blok 4: zdjęcie, suwak 0-250 i przycisk

    Kryteria: , ,

    R.2.6 W blokach umieszczono obrazy, blok 1: pszczola.jpg , blok 2: pomarancza.jpg , blok 3: owoce.jpg , blok 4: zolw.jpg , każdy z nich ma tekst alternatywny opisujący zdjęcie

    R.2.8 W bloku drugim umieszczono dwa przyciski "Kolorowy" i "Czarno-biały" oraz w bloku pierwszym, trzecim i czwartym przycisk "Zastosuj"

    R.2.9 W bloku trzecim i czwartym umieszczono pole typu range

    ok. 2 min
    Polecenie z arkusza

    Zawartość czwartego bloku: Obraz zolw.jpg z tekstem alternatywnym o treści „Żółw w wodzie”. Poniżej pole edycyjne w postaci suwaka z wartością minimalną 0 i maksymalną 250. Poniżej przycisk „Zastosuj”, którego kliknięcie powoduje transformację obrazu 4

    Wartości początkowej arkusz nie podaje, więc suwak staje w połowie zakresu (125), jak na obrazie 2. Komplet: zdjęcia z tekstami alternatywnymi w czterech blokach (R.2.6), suwaki w blokach 3 i 4 (R.2.9), przyciski „Kolorowy”, „Czarno-biały” i trzy „Zastosuj” (R.2.8).

    obrazki.html HTML zmienione: 3 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Efekty obrazu</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Efekty na obrazach</h2>
        </header>
        <main>
            <section id="block1">
                <img src="pszczola.jpg" alt="pszczoła na fioletowym kwiatku">
                <div role="radiogroup" aria-label="Efekt dla zdjęcia pszczoły">
                    <label><input type="radio" name="effect" value="blur"> Blur</label>
                    <label><input type="radio" name="effect" value="sepia"> Sepia</label>
                    <label><input type="radio" name="effect" value="invert"> Negatyw</label>
                </div>
                <button type="button">Zastosuj</button>
            </section>
            <section id="block2">
                <img src="pomarancza.jpg" alt="drzewo pomarańczy">
                <button type="button" id="colorButton">Kolorowy</button>
                <button type="button" id="grayButton">Czarno-biały</button>
            </section>
            <section id="block3">
                <img src="owoce.jpg" alt="Kosz pełen owoców">
                <input type="range" min="0" max="100" value="100" id="opacityRange" aria-label="Przezroczystość zdjęcia (%)">
                <button type="button">Zastosuj</button>
            </section>
            <section id="block4">
                <img src="zolw.jpg" alt="Żółw w wodzie">
                <input type="range" min="0" max="250" id="brightnessRange" aria-label="Jasność zdjęcia (%)">
                <button type="button">Zastosuj</button>
            </section>
        </main>
        <footer>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  20. Krok 20: Stopka: odnośnik w nowej karcie i autor

    Kryteria: ,

    R.2.5 W bloku banera zapisano nagłówek h2 "Efekty na obrazach" oraz dwa paragrafy w bloku stopki

    R.3.2 Na stronie umieszczono odnośnik, którego kliknięcie inicjuje otwarcie strony http://www.css.com/. Odnośnik otwiera się w nowej karcie przeglądarki

    ok. 2 min
    Polecenie z arkusza

    Zawartość stopki: Paragraf (akapit) z odnośnikiem do adresu http://www.css.com/, o treści „Zobacz inne efekty obrazu”. Odnośnik otwiera się w nowej karcie przeglądarki. Paragraf o treści: „Stronę wykonał: ”, dalej wstawiony numer zdającego.

    target="_blank" otwiera nową kartę (R.3.2), rel="noopener" odcina ją od karty z obrazkami (obca strona nie przejmie jej przez window.opener). Drugi akapit z autorem - na egzaminie po dwukropku wpisujesz swój numer zdającego (PESEL). <h2> i dwa akapity stopki to R.2.5.

    Typowe błędy

    Bez target="_blank" strona otwiera się w tej samej karcie - druga część kryterium R.3.2 nie jest spełniona.

    obrazki.html HTML zmienione: 2 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Efekty obrazu</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Efekty na obrazach</h2>
        </header>
        <main>
            <section id="block1">
                <img src="pszczola.jpg" alt="pszczoła na fioletowym kwiatku">
                <div role="radiogroup" aria-label="Efekt dla zdjęcia pszczoły">
                    <label><input type="radio" name="effect" value="blur"> Blur</label>
                    <label><input type="radio" name="effect" value="sepia"> Sepia</label>
                    <label><input type="radio" name="effect" value="invert"> Negatyw</label>
                </div>
                <button type="button">Zastosuj</button>
            </section>
            <section id="block2">
                <img src="pomarancza.jpg" alt="drzewo pomarańczy">
                <button type="button" id="colorButton">Kolorowy</button>
                <button type="button" id="grayButton">Czarno-biały</button>
            </section>
            <section id="block3">
                <img src="owoce.jpg" alt="Kosz pełen owoców">
                <input type="range" min="0" max="100" value="100" id="opacityRange" aria-label="Przezroczystość zdjęcia (%)">
                <button type="button">Zastosuj</button>
            </section>
            <section id="block4">
                <img src="zolw.jpg" alt="Żółw w wodzie">
                <input type="range" min="0" max="250" id="brightnessRange" aria-label="Jasność zdjęcia (%)">
                <button type="button">Zastosuj</button>
            </section>
        </main>
        <footer>
            <p><a href="http://www.css.com/" target="_blank" rel="noopener">Zobacz inne efekty obrazu</a></p>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  21. Etap 3: Styl CSS

    Kroki 21-28 · po tym etapie masz 30 z 41 kryteriów (pkt)

    Krok 21: Plik styl.css: zmienne, krój Century, wyśrodkowanie

    Kryteria:

    R.4.1 Ustawiono domyślne formatowanie wszystkich selektorów (dla *): krój czcionki Century, Serif (tylko taka kolejność jest poprawna) oraz wyrównanie tekstu do środka

    ok. 1 min
    Polecenie z arkusza

    Domyślne formatowanie wszystkich selektorów: krój czcionki Century, w przypadku jego braku Serif, wyrównanie tekstu do środka

    Dwa kolory z arkusza w zmiennych: Indigo (baner, stopka, przycisk pod kursorem) i SlateBlue (przyciski, ramki zdjęć). Selektor *: Century, potem rodzina zapasowa serif - klucz uznaje tylko tę kolejność - i wyśrodkowanie (R.4.1).

    styl.css CSS nowy plik
    :root {
        --indigo: Indigo;
        --slate-blue: SlateBlue;
    }
    
    * {
        font-family: Century, serif;
        text-align: center;
    }
    Podgląd strony po tym kroku (obrazki.html)
  22. Krok 22: Baner i stopka

    Kryteria:

    R.4.6 Ustawiono tekst pochylony dla banera i stopki

    ok. 1 min
    Polecenie z arkusza

    Wspólne dla banera i stopki: kolor tła Indigo, biały kolor czcionki, tekst pochylony, marginesy wewnętrzne 2 px

    Jedna reguła, kolor ze zmiennej, pochylenie font-style: italic (R.4.6).

    styl.css CSS zmienione: 7 linii
    :root {
        --indigo: Indigo;
        --slate-blue: SlateBlue;
    }
    
    * {
        font-family: Century, serif;
        text-align: center;
    }
    
    header, footer {
        background-color: var(--indigo);
        color: white;
        font-style: italic;
        padding: 2px;
    }
    Podgląd strony po tym kroku (obrazki.html)
  23. Krok 23: Cztery bloki na siatce

    Kryteria: ,

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

    R.4.4 Ustawiono wysokość czterech bloków 470px

    ok. 2 min
    Polecenie z arkusza

    Wspólny dla czterech bloków: szerokość 50%, wysokość 470 px

    <main> jest siatką o dwóch kolumnach po 50% (repeat(2, 50%) to skrót od 50% 50%): bloki same układają się po dwa w rzędzie, trzeci przechodzi do drugiego wiersza - jak na obrazie 2 (R.3.1). Szerokość 50% stoi w kolumnach siatki (klucz R.4.5 przyjmuje ją w tej postaci), a bloki mają tylko wysokość 470 px (R.4.4).

    Typowe błędy

    width: 50% dopisane do bloków w kolumnach 50% daje bloki szerokie na 25% strony - procent szerokości elementu siatki liczy się od jego kolumny.

    styl.css CSS zmienione: 9 linii
    :root {
        --indigo: Indigo;
        --slate-blue: SlateBlue;
    }
    
    * {
        font-family: Century, serif;
        text-align: center;
    }
    
    header, footer {
        background-color: var(--indigo);
        color: white;
        font-style: italic;
        padding: 2px;
    }
    
    main {
        display: grid;
        grid-template-columns: repeat(2, 50%);
    }
    
    section {
        height: 470px;
    }
    Podgląd strony po tym kroku (obrazki.html)
  24. Krok 24: Obrazy: ramka kreskowa

    ok. 2 min
    Polecenie z arkusza

    Dla selektora obrazu: marginesy wewnętrzne 3 px, zewnętrzne 10 px, obramowanie linią kreskową o grubości 2 px koloru SlateBlue

    Selektor znacznika img - uwaga arkusza: styl obrazu wyłącznie selektorem znacznika. Linia kreskowa to dashed. transition: filter 0.4s (dodatek) sprawia, że nałożony skryptem filtr pojawia się płynnie, a nie skokiem.

    styl.css CSS zmienione: 7 linii
    :root {
        --indigo: Indigo;
        --slate-blue: SlateBlue;
    }
    
    * {
        font-family: Century, serif;
        text-align: center;
    }
    
    header, footer {
        background-color: var(--indigo);
        color: white;
        font-style: italic;
        padding: 2px;
    }
    
    main {
        display: grid;
        grid-template-columns: repeat(2, 50%);
    }
    
    section {
        height: 470px;
    }
    
    img {
        padding: 3px;
        margin: 10px;
        border: 2px dashed var(--slate-blue);
        transition: filter 0.4s;
    }
    Podgląd strony po tym kroku (obrazki.html)
  25. Krok 25: Odnośnik: biały tekst

    ok. 1 min
    Polecenie z arkusza

    Dla odnośnika: biały kolor czcionki

    Bez tej reguły odnośnik byłby granatowy na fioletowym tle.

    styl.css CSS zmienione: 4 linie
    :root {
        --indigo: Indigo;
        --slate-blue: SlateBlue;
    }
    
    * {
        font-family: Century, serif;
        text-align: center;
    }
    
    header, footer {
        background-color: var(--indigo);
        color: white;
        font-style: italic;
        padding: 2px;
    }
    
    main {
        display: grid;
        grid-template-columns: repeat(2, 50%);
    }
    
    section {
        height: 470px;
    }
    
    img {
        padding: 3px;
        margin: 10px;
        border: 2px dashed var(--slate-blue);
        transition: filter 0.4s;
    }
    
    a {
        color: white;
    }
    Podgląd strony po tym kroku (obrazki.html)
  26. Krok 26: Przyciski

    Kryteria: , , , ,

    R.4.2 Ustawiono kolor tła Indigo dla bloków banera i stopki oraz SlateBlue dla przycisków

    R.4.3 Ustawiono biały kolor czcionki dla banera, stopki, odnośnika i przycisków

    R.4.7 Ustawiono marginesy wewnętrzne (padding) dla banera, stopki 2px, dla selektora img 3px, dla przycisków: górny i dolny 10 px, lewy i prawy 20 px

    R.4.8 Ustawiono marginesy zewnętrzne (margin) dla obrazu 10px i margines górny dla przycisków 10px

    R.4.9 Ustawiono dla obrazu obramowanie linią kreskową o grubości 2 px koloru SlateBlue oraz brak obramowania dla przycisków

    ok. 2 min
    Polecenie z arkusza

    Dla przycisków: kolor tła SlateBlue, biały kolor czcionki, brak obramowania, marginesy wewnętrzne górny i dolny 10 px, lewy i prawy 20 px, margines zewnętrzny górny 10 px

    padding-block: 10px - margines wewnętrzny górny i dolny, padding-inline: 20px - lewy i prawy: dokładnie słowa arkusza, bez pamiętania kolejności wartości w skrócie padding. cursor: pointer - rączka nad przyciskiem bez ramki. Ta reguła domyka kolory tła (R.4.2), białe teksty (R.4.3), marginesy wewnętrzne (R.4.7) i zewnętrzne (R.4.8) oraz obramowania (R.4.9).

    styl.css CSS zmienione: 10 linii
    :root {
        --indigo: Indigo;
        --slate-blue: SlateBlue;
    }
    
    * {
        font-family: Century, serif;
        text-align: center;
    }
    
    header, footer {
        background-color: var(--indigo);
        color: white;
        font-style: italic;
        padding: 2px;
    }
    
    main {
        display: grid;
        grid-template-columns: repeat(2, 50%);
    }
    
    section {
        height: 470px;
    }
    
    img {
        padding: 3px;
        margin: 10px;
        border: 2px dashed var(--slate-blue);
        transition: filter 0.4s;
    }
    
    a {
        color: white;
    }
    
    button {
        background-color: var(--slate-blue);
        color: white;
        border: none;
        padding-block: 10px;
        padding-inline: 20px;
        margin-top: 10px;
        cursor: pointer;
    }
    Podgląd strony po tym kroku (obrazki.html)
  27. Krok 27: Kursor na przycisku

    Kryteria:

    R.4.10 W momencie, gdy kursor myszy znajdzie się na przycisku, jego kolor tła zmienia się na Indigo

    ok. 1 min
    Polecenie z arkusza

    W momencie, gdy kursor myszy znajdzie się na przycisku, jego kolor tła zmienia się na Indigo

    :hover (R.4.10) i :focus-visible - przycisk wybrany klawiszem Tab też ciemnieje, bo bez ramki nie widać, który ma fokus.

    styl.css CSS zmienione: 5 linii
    :root {
        --indigo: Indigo;
        --slate-blue: SlateBlue;
    }
    
    * {
        font-family: Century, serif;
        text-align: center;
    }
    
    header, footer {
        background-color: var(--indigo);
        color: white;
        font-style: italic;
        padding: 2px;
    }
    
    main {
        display: grid;
        grid-template-columns: repeat(2, 50%);
    }
    
    section {
        height: 470px;
    }
    
    img {
        padding: 3px;
        margin: 10px;
        border: 2px dashed var(--slate-blue);
        transition: filter 0.4s;
    }
    
    a {
        color: white;
    }
    
    button {
        background-color: var(--slate-blue);
        color: white;
        border: none;
        padding-block: 10px;
        padding-inline: 20px;
        margin-top: 10px;
        cursor: pointer;
    }
    
    button:hover,
    button:focus-visible {
        background-color: var(--indigo);
    }
    Podgląd strony po tym kroku (obrazki.html)
  28. Krok 28: Tylko suwaki: szerokość 80%; etykiety pod sobą

    Kryteria:

    R.4.5 Ustawiono szerokość czterech bloków 50% oraz jedynie dla pól edycyjnych typu range: szerokość 80%, np. klasą lub input[type=range], lub dla dwóch różnych id

    ok. 2 min
    Polecenie z arkusza

    Jedynie dla pól edycyjnych w postaci suwaka: szerokość 80%

    • input[type="range"] - selektor atrybutu trafia tylko w suwaki, pola opcji zostają małe (R.4.5: kolumny bloków 50% i suwaki 80%). display: block z margin-inline: auto stawia suwak w osobnym wierszu, wyśrodkowany - przycisk „Zastosuj” trafia pod niego, jak każe arkusz, bez <br>,
    • label { display: block } - każda etykieta w osobnym wierszu, pod zdjęciem i pod sobą; to zadanie CSS, a nie <br> w HTML-u,
    • accent-color (dodatek) - pola opcji i suwaki dostają kolor przycisków zamiast domyślnego niebieskiego przeglądarki.
    styl.css CSS zmienione: 14 linii
    :root {
        --indigo: Indigo;
        --slate-blue: SlateBlue;
    }
    
    * {
        font-family: Century, serif;
        text-align: center;
    }
    
    header, footer {
        background-color: var(--indigo);
        color: white;
        font-style: italic;
        padding: 2px;
    }
    
    main {
        display: grid;
        grid-template-columns: repeat(2, 50%);
    }
    
    section {
        height: 470px;
    }
    
    img {
        padding: 3px;
        margin: 10px;
        border: 2px dashed var(--slate-blue);
        transition: filter 0.4s;
    }
    
    a {
        color: white;
    }
    
    button {
        background-color: var(--slate-blue);
        color: white;
        border: none;
        padding-block: 10px;
        padding-inline: 20px;
        margin-top: 10px;
        cursor: pointer;
    }
    
    button:hover,
    button:focus-visible {
        background-color: var(--indigo);
    }
    
    input[type="range"] {
        width: 80%;
        display: block;
        margin-inline: auto;
    }
    
    label {
        display: block;
    }
    
    input {
        accent-color: var(--slate-blue);
    }
    Podgląd strony po tym kroku (obrazki.html)
  29. Etap 4: JavaScript

    Kroki 29-34 · po tym etapie masz 41 z 41 kryteriów (pkt)

    Krok 29: Blok 1: rozmycie dla pola Blur

    Kryteria: , , ,

    R.3.5 Dla dowolnego przycisku zdefiniowano zdarzenie związane z jego kliknięciem , które odwołuje się do funkcji w skrypcie (atrybut onClick lub słuchacz zdarzenia click lub właściwość onclick obiektu DOM)

    R.5.1 Skrypt zapisano w języku JavaScript i zawiera on przynajmniej jedną instrukcję zapisaną zgodnie ze składnią

    R.5.2 Dla obrazu z bloku 1 ustawiono wartość właściwości filter na blur lub invert lub sepia (prawidłowo zapisana operacja ustawiania .style.filter dla elementu) lub sprawdzono przynajmniej dla jednego radio czy jest wciśnięty (w warunku prawidłowo zapisane sprawdzenie wartości checked dla elementu)

    R.5.5 Dla obrazu z bloku 1, dla opcji Blur obraz jest rozmyty, wartość blur jest z przedziału 4 px ÷ 8 px

    ok. 4 min
    Polecenie z arkusza

    Transformacje obrazu 1: Gdy zaznaczono pole Blur na obraz jest nakładany filtr rozmycia o dowolnej wartości z przedziału 4 px ÷ 8 px

    Skrypt na końcu <body>, w pliku strony (klucz sprawdza go „w kodzie strony”).

    • EFFECTS - obiekt: wartość pola opcji → filtr. Na razie jeden wpis, blur(5px) (5 px mieści się w przedziale 4-8 px, R.5.5),
    • applyFilter(block, value) - jedna funkcja dla wszystkich bloków: w podanym bloku znajduje zdjęcie i ustawia mu style.filter,
    • przycisk bloku 1 dostaje nasłuchiwacz addEventListener("click", ...) (R.3.5). [...effectRadios] zamienia listę pól w tablicę, a find zwraca pierwsze pole, którego checked jest prawdą - to sprawdzenie, o którym mówi R.5.2. Bez zaznaczenia find zwraca undefined i nic się nie dzieje.

    W podglądzie: zaznacz „Blur” (albo kliknij sam napis) i „Zastosuj”.

    obrazki.html HTML zmienione: 19 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Efekty obrazu</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Efekty na obrazach</h2>
        </header>
        <main>
            <section id="block1">
                <img src="pszczola.jpg" alt="pszczoła na fioletowym kwiatku">
                <div role="radiogroup" aria-label="Efekt dla zdjęcia pszczoły">
                    <label><input type="radio" name="effect" value="blur"> Blur</label>
                    <label><input type="radio" name="effect" value="sepia"> Sepia</label>
                    <label><input type="radio" name="effect" value="invert"> Negatyw</label>
                </div>
                <button type="button">Zastosuj</button>
            </section>
            <section id="block2">
                <img src="pomarancza.jpg" alt="drzewo pomarańczy">
                <button type="button" id="colorButton">Kolorowy</button>
                <button type="button" id="grayButton">Czarno-biały</button>
            </section>
            <section id="block3">
                <img src="owoce.jpg" alt="Kosz pełen owoców">
                <input type="range" min="0" max="100" value="100" id="opacityRange" aria-label="Przezroczystość zdjęcia (%)">
                <button type="button">Zastosuj</button>
            </section>
            <section id="block4">
                <img src="zolw.jpg" alt="Żółw w wodzie">
                <input type="range" min="0" max="250" id="brightnessRange" aria-label="Jasność zdjęcia (%)">
                <button type="button">Zastosuj</button>
            </section>
        </main>
        <footer>
            <p><a href="http://www.css.com/" target="_blank" rel="noopener">Zobacz inne efekty obrazu</a></p>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
        <script>
            const EFFECTS = {
                blur: "blur(5px)",
            };
    
            function applyFilter(block, value) {
                block.querySelector("img").style.filter = value;
            }
    
            const block1 = document.querySelector("#block1");
            const effectRadios = block1.querySelectorAll('input[name="effect"]');
    
            block1.querySelector("button").addEventListener("click", () => {
                const selected = [...effectRadios].find((radio) => radio.checked);
                if (selected) {
                    applyFilter(block1, EFFECTS[selected.value]);
                }
            });
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  30. Krok 30: Blok 1: sepia

    Kryteria:

    R.5.6 Dla obrazu z bloku 1, dla opcji Sepia obraz jest w pełnych kolorach sepii (100%)

    ok. 1 min
    Polecenie z arkusza

    Gdy zaznaczono pole Sepia na obraz nakładany jest filtr kolorów sepii (efekt starej fotografii) o wartości 100%

    Drugi efekt to jedna linia w obiekcie - kod obsługi przycisku się nie zmienia: pole z value="sepia" wskaże wpis sepia(100%) (R.5.6). Nowy filtr zastępuje poprzedni, bo style.filter dostaje nową wartość.

    obrazki.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Efekty obrazu</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Efekty na obrazach</h2>
        </header>
        <main>
            <section id="block1">
                <img src="pszczola.jpg" alt="pszczoła na fioletowym kwiatku">
                <div role="radiogroup" aria-label="Efekt dla zdjęcia pszczoły">
                    <label><input type="radio" name="effect" value="blur"> Blur</label>
                    <label><input type="radio" name="effect" value="sepia"> Sepia</label>
                    <label><input type="radio" name="effect" value="invert"> Negatyw</label>
                </div>
                <button type="button">Zastosuj</button>
            </section>
            <section id="block2">
                <img src="pomarancza.jpg" alt="drzewo pomarańczy">
                <button type="button" id="colorButton">Kolorowy</button>
                <button type="button" id="grayButton">Czarno-biały</button>
            </section>
            <section id="block3">
                <img src="owoce.jpg" alt="Kosz pełen owoców">
                <input type="range" min="0" max="100" value="100" id="opacityRange" aria-label="Przezroczystość zdjęcia (%)">
                <button type="button">Zastosuj</button>
            </section>
            <section id="block4">
                <img src="zolw.jpg" alt="Żółw w wodzie">
                <input type="range" min="0" max="250" id="brightnessRange" aria-label="Jasność zdjęcia (%)">
                <button type="button">Zastosuj</button>
            </section>
        </main>
        <footer>
            <p><a href="http://www.css.com/" target="_blank" rel="noopener">Zobacz inne efekty obrazu</a></p>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
        <script>
            const EFFECTS = {
                blur: "blur(5px)",
                sepia: "sepia(100%)",
            };
    
            function applyFilter(block, value) {
                block.querySelector("img").style.filter = value;
            }
    
            const block1 = document.querySelector("#block1");
            const effectRadios = block1.querySelectorAll('input[name="effect"]');
    
            block1.querySelector("button").addEventListener("click", () => {
                const selected = [...effectRadios].find((radio) => radio.checked);
                if (selected) {
                    applyFilter(block1, EFFECTS[selected.value]);
                }
            });
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  31. Krok 31: Blok 1: negatyw

    Kryteria:

    R.5.7 Dla obrazu z bloku 1, dla opcji Negatyw obraz jest w pełnym negatywie (100%)

    ok. 1 min
    Polecenie z arkusza

    Gdy zaznaczono pole Negatyw na obraz nakładany jest filtr odwrócenia kolorów (negatyw) w 100%

    Negatyw to filtr invert w 100% - trzecia linia obiektu (R.5.7). Przecinek po ostatnim wpisie jest w JavaScripcie dozwolony: dopisanie czwartego efektu nie wymaga poprawiania linii wyżej.

    obrazki.html HTML zmienione: 1 linia
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Efekty obrazu</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Efekty na obrazach</h2>
        </header>
        <main>
            <section id="block1">
                <img src="pszczola.jpg" alt="pszczoła na fioletowym kwiatku">
                <div role="radiogroup" aria-label="Efekt dla zdjęcia pszczoły">
                    <label><input type="radio" name="effect" value="blur"> Blur</label>
                    <label><input type="radio" name="effect" value="sepia"> Sepia</label>
                    <label><input type="radio" name="effect" value="invert"> Negatyw</label>
                </div>
                <button type="button">Zastosuj</button>
            </section>
            <section id="block2">
                <img src="pomarancza.jpg" alt="drzewo pomarańczy">
                <button type="button" id="colorButton">Kolorowy</button>
                <button type="button" id="grayButton">Czarno-biały</button>
            </section>
            <section id="block3">
                <img src="owoce.jpg" alt="Kosz pełen owoców">
                <input type="range" min="0" max="100" value="100" id="opacityRange" aria-label="Przezroczystość zdjęcia (%)">
                <button type="button">Zastosuj</button>
            </section>
            <section id="block4">
                <img src="zolw.jpg" alt="Żółw w wodzie">
                <input type="range" min="0" max="250" id="brightnessRange" aria-label="Jasność zdjęcia (%)">
                <button type="button">Zastosuj</button>
            </section>
        </main>
        <footer>
            <p><a href="http://www.css.com/" target="_blank" rel="noopener">Zobacz inne efekty obrazu</a></p>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
        <script>
            const EFFECTS = {
                blur: "blur(5px)",
                sepia: "sepia(100%)",
                invert: "invert(100%)",
            };
    
            function applyFilter(block, value) {
                block.querySelector("img").style.filter = value;
            }
    
            const block1 = document.querySelector("#block1");
            const effectRadios = block1.querySelectorAll('input[name="effect"]');
    
            block1.querySelector("button").addEventListener("click", () => {
                const selected = [...effectRadios].find((radio) => radio.checked);
                if (selected) {
                    applyFilter(block1, EFFECTS[selected.value]);
                }
            });
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  32. Krok 32: Blok 2: czarno-biały i z powrotem kolorowy

    Kryteria: ,

    R.5.3 Dla obrazu z bloku 2 ustawiono wartość właściwości filter na grayscale 0 lub 100% lub 1 (prawidłowo zapisana operacja ustawiania .style.filter dla elementu)

    R.5.8 Dla obrazu z bloku 2, gdy wybrano przycisk "Czarno-biały" obraz jest w pełni w kolorach szarości, gdy następnie wybrano przycisk "Kolory" obraz jest kolorowy

    ok. 2 min
    Polecenie z arkusza

    Transformacje obrazu 2: Po wciśnięciu przycisku „Kolory” obraz ma zdjęty filtr odcieni szarości. Po wciśnięciu przycisku „Czarno-biały” na obraz jest nakładany filtr odcieni szarości o wartości 100%

    Dwa nasłuchiwacze, ta sama funkcja: grayscale(100%) - pełne odcienie szarości, grayscale(0%) - zdjęty filtr (0% to oryginał, tabela 3). Funkcje strzałkowe w jednej linii: () => applyFilter(...). Przycisk „Kolory” z opisu skryptu to przycisk „Kolorowy” z bloku (R.5.3, R.5.8).

    obrazki.html HTML zmienione: 4 linie
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Efekty obrazu</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Efekty na obrazach</h2>
        </header>
        <main>
            <section id="block1">
                <img src="pszczola.jpg" alt="pszczoła na fioletowym kwiatku">
                <div role="radiogroup" aria-label="Efekt dla zdjęcia pszczoły">
                    <label><input type="radio" name="effect" value="blur"> Blur</label>
                    <label><input type="radio" name="effect" value="sepia"> Sepia</label>
                    <label><input type="radio" name="effect" value="invert"> Negatyw</label>
                </div>
                <button type="button">Zastosuj</button>
            </section>
            <section id="block2">
                <img src="pomarancza.jpg" alt="drzewo pomarańczy">
                <button type="button" id="colorButton">Kolorowy</button>
                <button type="button" id="grayButton">Czarno-biały</button>
            </section>
            <section id="block3">
                <img src="owoce.jpg" alt="Kosz pełen owoców">
                <input type="range" min="0" max="100" value="100" id="opacityRange" aria-label="Przezroczystość zdjęcia (%)">
                <button type="button">Zastosuj</button>
            </section>
            <section id="block4">
                <img src="zolw.jpg" alt="Żółw w wodzie">
                <input type="range" min="0" max="250" id="brightnessRange" aria-label="Jasność zdjęcia (%)">
                <button type="button">Zastosuj</button>
            </section>
        </main>
        <footer>
            <p><a href="http://www.css.com/" target="_blank" rel="noopener">Zobacz inne efekty obrazu</a></p>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
        <script>
            const EFFECTS = {
                blur: "blur(5px)",
                sepia: "sepia(100%)",
                invert: "invert(100%)",
            };
    
            function applyFilter(block, value) {
                block.querySelector("img").style.filter = value;
            }
    
            const block1 = document.querySelector("#block1");
            const effectRadios = block1.querySelectorAll('input[name="effect"]');
    
            block1.querySelector("button").addEventListener("click", () => {
                const selected = [...effectRadios].find((radio) => radio.checked);
                if (selected) {
                    applyFilter(block1, EFFECTS[selected.value]);
                }
            });
    
            const block2 = document.querySelector("#block2");
            document.querySelector("#colorButton").addEventListener("click", () => applyFilter(block2, "grayscale(0%)"));
            document.querySelector("#grayButton").addEventListener("click", () => applyFilter(block2, "grayscale(100%)"));
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  33. Krok 33: Blok 3: przezroczystość z suwaka

    Kryteria:

    R.5.4 Dla obrazu z bloku 3 ustawiono wartość właściwości filter na opacity lub dla obrazu z bloku 4 na brightness (wystarczy dla jednego bloku). Dowolna wartość (prawidłowo zapisana operacja ustawiania .style.filter dla elementu) lub pobrano wartość suwaka (prawidłowo zapisane pobranie wartości value dla elementu) (dopuszcza się w bloku 3 zastosowanie właściwości opacity)

    ok. 2 min
    Polecenie z arkusza

    Transformacje obrazu 3: Po wciśnięciu przycisku „Zastosuj” na obraz jest nakładany filtr przezroczystości o wartości, która została wskazana suwakiem

    value suwaka (0-100) trafia do filtra opacity przez szablon tekstowy `opacity(${...}%)` - bez sklejania plusami (R.5.4). Filtr działa na cały element <img>, więc blednie też kreskowa ramka. Test w Chrome: suwak na 40 - opacity(40%).

    obrazki.html HTML zmienione: 6 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Efekty obrazu</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Efekty na obrazach</h2>
        </header>
        <main>
            <section id="block1">
                <img src="pszczola.jpg" alt="pszczoła na fioletowym kwiatku">
                <div role="radiogroup" aria-label="Efekt dla zdjęcia pszczoły">
                    <label><input type="radio" name="effect" value="blur"> Blur</label>
                    <label><input type="radio" name="effect" value="sepia"> Sepia</label>
                    <label><input type="radio" name="effect" value="invert"> Negatyw</label>
                </div>
                <button type="button">Zastosuj</button>
            </section>
            <section id="block2">
                <img src="pomarancza.jpg" alt="drzewo pomarańczy">
                <button type="button" id="colorButton">Kolorowy</button>
                <button type="button" id="grayButton">Czarno-biały</button>
            </section>
            <section id="block3">
                <img src="owoce.jpg" alt="Kosz pełen owoców">
                <input type="range" min="0" max="100" value="100" id="opacityRange" aria-label="Przezroczystość zdjęcia (%)">
                <button type="button">Zastosuj</button>
            </section>
            <section id="block4">
                <img src="zolw.jpg" alt="Żółw w wodzie">
                <input type="range" min="0" max="250" id="brightnessRange" aria-label="Jasność zdjęcia (%)">
                <button type="button">Zastosuj</button>
            </section>
        </main>
        <footer>
            <p><a href="http://www.css.com/" target="_blank" rel="noopener">Zobacz inne efekty obrazu</a></p>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
        <script>
            const EFFECTS = {
                blur: "blur(5px)",
                sepia: "sepia(100%)",
                invert: "invert(100%)",
            };
    
            function applyFilter(block, value) {
                block.querySelector("img").style.filter = value;
            }
    
            const block1 = document.querySelector("#block1");
            const effectRadios = block1.querySelectorAll('input[name="effect"]');
    
            block1.querySelector("button").addEventListener("click", () => {
                const selected = [...effectRadios].find((radio) => radio.checked);
                if (selected) {
                    applyFilter(block1, EFFECTS[selected.value]);
                }
            });
    
            const block2 = document.querySelector("#block2");
            document.querySelector("#colorButton").addEventListener("click", () => applyFilter(block2, "grayscale(0%)"));
            document.querySelector("#grayButton").addEventListener("click", () => applyFilter(block2, "grayscale(100%)"));
    
            const block3 = document.querySelector("#block3");
            const opacityRange = document.querySelector("#opacityRange");
            block3.querySelector("button").addEventListener("click", () => {
                applyFilter(block3, `opacity(${opacityRange.value}%)`);
            });
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  34. Krok 34: Blok 4: jasność z suwaka

    Kryteria: ,

    R.5.9 Dla obrazu z bloku 3 zatwierdzona zmiana położenia suwaka zmienia przezroczystość obrazu oraz dla obrazu z bloku 4 zatwierdzona zmiana położenia suwaka zmienia jasność obrazu

    R.5.10 Zastosowano znaczące nazewnictwo dla wszystkich zmiennych i funkcji w języku polskim lub angielskim. Nazwy odzwierciedlają cel zastosowania

    ok. 2 min
    Polecenie z arkusza

    Transformacje obrazu 4: Po wciśnięciu przycisku „Zastosuj” na obraz jest nakładany filtr zmiany jasności o wartości, która została wskazana suwakiem.

    Ten sam wzór z filtrem brightness: 100% to oryginał, mniej przyciemnia, więcej rozjaśnia - suwak sięga 250% (R.5.9). Nazwy mówią, co robią i co przechowują: EFFECTS, applyFilter, effectRadios, selected, opacityRange, brightnessRange (R.5.10).

    obrazki.html HTML zmienione: 6 linii
    <!DOCTYPE html>
    <html lang="pl">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Efekty obrazu</title>
        <link rel="stylesheet" href="styl.css">
    </head>
    <body>
        <header>
            <h2>Efekty na obrazach</h2>
        </header>
        <main>
            <section id="block1">
                <img src="pszczola.jpg" alt="pszczoła na fioletowym kwiatku">
                <div role="radiogroup" aria-label="Efekt dla zdjęcia pszczoły">
                    <label><input type="radio" name="effect" value="blur"> Blur</label>
                    <label><input type="radio" name="effect" value="sepia"> Sepia</label>
                    <label><input type="radio" name="effect" value="invert"> Negatyw</label>
                </div>
                <button type="button">Zastosuj</button>
            </section>
            <section id="block2">
                <img src="pomarancza.jpg" alt="drzewo pomarańczy">
                <button type="button" id="colorButton">Kolorowy</button>
                <button type="button" id="grayButton">Czarno-biały</button>
            </section>
            <section id="block3">
                <img src="owoce.jpg" alt="Kosz pełen owoców">
                <input type="range" min="0" max="100" value="100" id="opacityRange" aria-label="Przezroczystość zdjęcia (%)">
                <button type="button">Zastosuj</button>
            </section>
            <section id="block4">
                <img src="zolw.jpg" alt="Żółw w wodzie">
                <input type="range" min="0" max="250" id="brightnessRange" aria-label="Jasność zdjęcia (%)">
                <button type="button">Zastosuj</button>
            </section>
        </main>
        <footer>
            <p><a href="http://www.css.com/" target="_blank" rel="noopener">Zobacz inne efekty obrazu</a></p>
            <p>Stronę wykonał: Bartosz Bryniarski</p>
        </footer>
        <script>
            const EFFECTS = {
                blur: "blur(5px)",
                sepia: "sepia(100%)",
                invert: "invert(100%)",
            };
    
            function applyFilter(block, value) {
                block.querySelector("img").style.filter = value;
            }
    
            const block1 = document.querySelector("#block1");
            const effectRadios = block1.querySelectorAll('input[name="effect"]');
    
            block1.querySelector("button").addEventListener("click", () => {
                const selected = [...effectRadios].find((radio) => radio.checked);
                if (selected) {
                    applyFilter(block1, EFFECTS[selected.value]);
                }
            });
    
            const block2 = document.querySelector("#block2");
            document.querySelector("#colorButton").addEventListener("click", () => applyFilter(block2, "grayscale(0%)"));
            document.querySelector("#grayButton").addEventListener("click", () => applyFilter(block2, "grayscale(100%)"));
    
            const block3 = document.querySelector("#block3");
            const opacityRange = document.querySelector("#opacityRange");
            block3.querySelector("button").addEventListener("click", () => {
                applyFilter(block3, `opacity(${opacityRange.value}%)`);
            });
    
            const block4 = document.querySelector("#block4");
            const brightnessRange = document.querySelector("#brightnessRange");
            block4.querySelector("button").addEventListener("click", () => {
                applyFilter(block4, `brightness(${brightnessRange.value}%)`);
            });
        </script>
    </body>
    </html>
    Podgląd strony po tym kroku (obrazki.html)
  35. Etap 5: Porównanie z wersją podstawową

    Krok 35 · po tym etapie masz 41 z 41 kryteriów (pkt)

    Krok 35: Co jest inaczej i którą wersję wybrać na egzaminie

    ok. 2 min

    Obie wersje dają komplet 41 punktów. Różnice:

    wersja podstawowawersja nowoczesna
    układ bloków<main> z flex-wrap: wrap, width: 50% bloków<main> jako siatka repeat(2, 50%)
    pola opcjitekst obok pola, <br><label> wokół pola, role="radiogroup", display: block w CSS
    wybrany efekttrzy osobne if z getElementById(...).checkedfind(radio => radio.checked) i obiekt EFFECTS
    nakładanie filtracztery funkcje, każda z getElementByIdjedna applyFilter(block, value)
    wartość suwakasklejanie "opacity(" + ... + "%)"szablon tekstowy `opacity(${...}%)`
    zdarzeniaatrybuty onclickaddEventListener
    SQL zapytania 2AVG bez nazwy, GROUP BY nazwaROUND(...) AS sredniaPensja, GROUP BY s.id, s.nazwa, ORDER BY

    Na egzaminie wersja podstawowa trzyma się elementów z tabeli 2 arkusza i każdą jej część łatwo sprawdzić osobno. Nowoczesna jest krótsza i łatwiej ją rozbudować: nowy efekt to jedna linia w EFFECTS i jedno pole w HTML-u. Sprawdzenie checked zostało w obu wersjach - klucz (R.5.2) mówi o nim wprost.

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

  36. Etap 6: Oddanie pracy

    Krok 36 · po tym etapie masz 41 z 41 kryteriów (pkt)

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

    ok. 5 min
    Polecenie z arkusza

    UWAGA: 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 nazwa przeglądarki, w której sprawdzana była strona - przy filtrach CSS to ważne, bo starsze przeglądarki ich nie obsługują. W folderze z numerem zdającego: import.png, kw1.jpg - kw4.jpg, kwerendy.txt, obrazki.html, owoce.jpg, pomarancza.jpg, pszczola.jpg, przeglądarka.txt, styl.css, zolw.jpg. Nagraj płytę, sprawdź jej odczyt i opisz ją numerem zdającego.

    przeglądarka.txt Tekst nowy plik
    Google Chrome

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

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.