INF.03-02-24.06-SGCzerwiec 2024 · 34 kroki · ok. 77 min · 40 kryteriów z klucza
Rozwiązanie krok po kroku: Prototyp front-endu chatu (Nowoczesny kod (grid, addEventListener))
To drugi sposób rozwiązania tego samego arkusza. Wynik jest ten sam - baza chat z pięcioma zapytaniami, przycięte zdjęcie i strona chat.html z oknem rozmowy, do którego skrypt dokłada wiadomości Jolanty i losowe odpowiedzi Krzysztofa - i tak samo spełnia każde kryterium klucza. Inna jest droga:
siatka CSS na całej stronie: grid-template-areas stawia blok boczny obok banera i bloku głównego, a szerokości 80% i 20% stoją w grid-template-columns (klucz R.4.4 przyjmuje je wprost). Dzięki temu kod HTML ma kolejność treści - baner, blok główny, blok boczny, stopka - a nie kolejność, której wymaga float,
kolory w zmiennych CSS,
wiadomość wysyłana formularzem: zdarzenie submit obsługuje kliknięcie „Wyślij” i klawisz Enter jednym kodem, a puste pole zatrzymuje przeglądarka,
szablon wypowiedzi w HTML-u (<template>): skrypt klonuje gotowy blok zamiast składać go z createElement, a dane autorów są w jednym obiekcie,
współczesny JavaScript: const, querySelector, textContent, addEventListener od początku,
zapytanie 1 bez przepisywania liczby: identyfikator dla wiersza logowania baza bierze z relacji sama.
Na końcu krótkie porównanie z wersją podstawową (zakładka obok). Baza, zdjęcia i teksty odpowiedzi pochodzą z prawdziwego archiwum pliki2, zapytania zostały wykonane na tej bazie w MariaDB z XAMPP-a, a działanie skryptu jest sprawdzone w prawdziwej przeglądarce Chrome.
Jak liczą się punkty. Klucz ma 40 kryteriów (R.1.1 - R.5.9), każde za 1 punkt. Próg zdania to 75%, czyli 30 punktów. Przy każdym kroku jest napisane, które kryteria spełnia.
Suwak i strzałki obok niego - albo ←→ na klawiaturze - przechodzą krok po kroku; wyjaśnienie, pliki i podgląd zmieniają się razem z krokiem.
Lista „Etap” przenosi od razu do wybranego etapu.
„Rozwiązuję samodzielnie” chowa rozwiązanie kroku - najpierw własna próba, potem odsłonięcie.
„Tryb prezentacji” pokazuje same kroki, bez menu strony - na rzutnik.
Etap 1: Baza danych
Kroki 1-8 · po tym etapie masz 7 z 40 kryteriów (pkt)
Krok 1: Baza danych chat
ok. 2 min
Polecenie z arkusza
Utwórz bazę danych o nazwie chat, z zestawem polskich znaków (np. utf8_unicode_ci)
Archiwum pliki2.zip rozpakuj hasłem ChaT_Ch@t (wielkość liter ma znaczenie) do folderu z numerem zdającego. W phpMyAdmin Nowa → chat, porównywanie utf8_unicode_ci, albo zapytaniem:
CREATE DATABASE chat CHARACTER SET utf8 COLLATE utf8_unicode_ci;
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
Import → baza.sql. Dwie tabele z obrazu 1: logowanie (nick i hasło, na razie 2 wiersze) i uczestnicy (3 osoby). Pole logowanie_id uczestnika wskazuje jego wiersz w logowanie - Jeremi Kowalski ma już logowanie_id = 3, choć takiego wiersza jeszcze nie ma.
Krok 3: Zrzut ekranu import.png
Kryteria:
R.1.1 Wykonano import tabel do bazy danych chat 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ń. Uwaga na formaty: import w PNG, zrzuty zapytań w JPEG (kw1.jpg - kw5.jpg).
Typowe błędy
Wykadrowany zrzut albo zrzut bez paska zadań nie jest oceniany (uwaga w kluczu przy R.1).
Krok 4: Zapytanie 1: dane logowania Jeremiego
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 wstawiające do tabeli logowanie nick "Jeremi" z hasłem „Jer123” o id=3. W pliku z kwerendami lub na zrzucie istnieje zapis np.: INSERT INTO `logowanie`(`id`, `nick`, `haslo`) VALUES (3, 'Jeremi','Jer123'); oraz wynik działania udokumentowano zrzutem, na którym jest widoczne pomyślnie wykonane zapytanie lub tabela ze wstawionym wierszem o id=3
ok. 3 min
Polecenie z arkusza
Zapytanie 1: wstawiające do tabeli logowanie nick „Jeremi” z hasłem „Jer123”. Wstawianemu wierszowi należy nadać identyfikator, odpowiadający wartości klucza obcego dla wiersza z danymi „Jeremi Kowalski” z tabeli uczestnicy
Zamiast odczytać liczbę 3 w phpMyAdmin i przepisać ją do VALUES, zapytanie bierze ją z relacji samo - INSERT ... SELECT:
INSERT INTO logowanie (id, nick, haslo) - do których kolumn,
SELECT logowanie_id, 'Jeremi', 'Jer123' FROM uczestnicy WHERE ... - wartości: klucz obcy z wiersza Jeremiego Kowalskiego i dwa stałe napisy.
Dokładnie to mówi polecenie: identyfikator „odpowiadający wartości klucza obcego” - i nie da się go pomylić przy przepisywaniu. Wynik: w logowanie wiersz 3, Jeremi, Jer123, jak w kluczu (R.1.3 podaje wariant z VALUES (3, ...) jako przykład). Zapytania zapisz w kwerendy.txt, zrzut jako kw1.jpg.
Typowe błędy
Gdyby w tabeli było dwóch Jeremich Kowalskich, SELECT zwróciłby dwa wiersze i wstawienie drugiego skończyłoby się błędem duplikatu klucza - warunek WHERE musi wskazać jedną osobę.
kwerendy.txtTekstnowy plik
-- Zapytanie 1INSERT INTO logowanie (id, nick, haslo)SELECT logowanie_id, 'Jeremi', 'Jer123'FROM uczestnicyWHERE imie = 'Jeremi' AND nazwisko = 'Kowalski';
Podgląd strony po tym kroku
Krok 5: Zapytanie 2: średni rok urodzenia zaokrąglony w dół
Kryteria:
R.1.4 Wykonano zapytanie 2 obliczające średni rok urodzenia uczestników. Wybrana kolumna powinna nosić nazwę "Średni rok urodzenia", a obliczony wynik powinien być zaokrąglony do najbliższej mniejszej liczby całkowitej. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT FLOOR(AVG(rokUr)) AS "Średni rok urodzenia" FROM uczestnicy; oraz wynik działania udokumentowano zrzutem, na którym jest widoczna wartość całkowita 2001, nazwa kolumny (alias) "Średni rok urodzenia"
ok. 2 min
Polecenie z arkusza
Zapytanie 2: obliczające średni rok urodzenia uczestników. Wybrana kolumna powinna mieć nazwę (alias) „Średni rok urodzenia”, a obliczony wynik powinien być zaokrąglony w dół do liczby całkowitej
AVG(rokUr) - średnia, FLOOR(...) - zaokrąglenie w dół (tabela 3 arkusza; ROUND zaokrągla do najbliższej, CEIL w górę). Alias ze spacjami w odwróconych apostrofach - w MySQL i MariaDB to znak dla nazw. Wynik: 2001. Zrzut: kw2.jpg.
Typowe błędy
Alias bez cudzysłowu (AS Średni rok urodzenia) to błąd składni.
kwerendy.txtTekstzmienione: 4 linie
-- Zapytanie 1INSERT INTO logowanie (id, nick, haslo)SELECT logowanie_id, 'Jeremi', 'Jer123'FROM uczestnicyWHERE imie = 'Jeremi' AND nazwisko = 'Kowalski';-- Zapytanie 2SELECT FLOOR(AVG(rokUr)) AS `Średni rok urodzenia`FROM uczestnicy;
Podgląd strony po tym kroku
Krok 6: Zapytanie 3: uczestnicy na J z danymi logowania
Kryteria:
R.1.5 Wykonano zapytanie 3 wybierające jedynie imię i nazwisko uczestnika oraz odpowiadające mu nick i hasło dla imion rozpoczynających się literą J. W pliku z kwerendami lub na zrzucie istnieje zapis np.: SELECT imie, nazwisko, nick, haslo FROM uczestnicy JOIN logowanie ON logowanie_id = logowanie.id WHERE imie LIKE "J%"; (możliwe również INNER JOIN lub bez JOIN i porównanie kluczy po WHERE) oraz wynik działania udokumentowano zrzutem, na którym są widoczne dokładnie 2 rekordy: Jolanta Nowak Jolka Jol123; Jeremi Kowalski Jeremi Jer123. Jeżeli nie wykonano R.1.3 jest widoczny dokładnie 1 rekord dla Jolanty
ok. 2 min
Polecenie z arkusza
Zapytanie 3: wybierające jedynie imię i nazwisko uczestnika oraz odpowiadające mu nick i hasło dla imion rozpoczynających się literą J. Należy posłużyć się relacją
Aliasy tabel u (uczestnicy) i l (logowanie): przy każdej kolumnie widać, skąd pochodzi, a ON l.id = u.logowanie_id pokazuje parę kluczy relacji. LIKE 'J%' - imię zaczyna się od J. Wynik: Jolanta Nowak Jolka Jol123 i Jeremi Kowalski Jeremi Jer123 - Jeremi jest w wyniku tylko dzięki zapytaniu 1. Zrzut: kw3.jpg.
kwerendy.txtTekstzmienione: 6 linii
-- Zapytanie 1INSERT INTO logowanie (id, nick, haslo)SELECT logowanie_id, 'Jeremi', 'Jer123'FROM uczestnicyWHERE imie = 'Jeremi' AND nazwisko = 'Kowalski';-- Zapytanie 2SELECT FLOOR(AVG(rokUr)) AS `Średni rok urodzenia`FROM uczestnicy;-- Zapytanie 3SELECT u.imie, u.nazwisko, l.nick, l.hasloFROM uczestnicy AS uJOIN logowanie AS l ON l.id = u.logowanie_idWHERE u.imie LIKE 'J%';
Podgląd strony po tym kroku
Krok 7: Zapytanie 4: użytkownik uczestnik
Kryteria:
R.1.6 Wykonano zapytanie 4 tworzące użytkownika uczestnik na localhost z hasłem Ucz123& W pliku z kwerendami lub na zrzucie istnieje zapis np.: CREATE USER uczestnik@localhost IDENTIFIED BY "Ucz123&" oraz wynik działania udokumentowano zrzutem, na którym widoczne jest poprawnie wykonane zapytanie
ok. 2 min
Polecenie z arkusza
Zapytanie 4: tworzące użytkownika uczestnik na localhost z hasłem Ucz123&
CREATE USER 'uczestnik'@'localhost' - konto serwera bazy (nie wiersz tabeli): nazwa i host, z którego wolno się logować; IDENTIFIED BY - hasło. Zapytanie nie zwraca wierszy, zrzut kw4.jpg pokazuje komunikat o wykonaniu.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1INSERT INTO logowanie (id, nick, haslo)SELECT logowanie_id, 'Jeremi', 'Jer123'FROM uczestnicyWHERE imie = 'Jeremi' AND nazwisko = 'Kowalski';-- Zapytanie 2SELECT FLOOR(AVG(rokUr)) AS `Średni rok urodzenia`FROM uczestnicy;-- Zapytanie 3SELECT u.imie, u.nazwisko, l.nick, l.hasloFROM uczestnicy AS uJOIN logowanie AS l ON l.id = u.logowanie_idWHERE u.imie LIKE 'J%';-- Zapytanie 4CREATE USER 'uczestnik'@'localhost' IDENTIFIED BY 'Ucz123&';
Podgląd strony po tym kroku
Krok 8: Zapytanie 5: prawa SELECT i UPDATE do tabeli uczestnicy
Kryteria:
R.1.7 Wykonano zapytanie 5 nadające utworzonemu użytkownikowi prawa do wybierania i aktualizacji danych jedynie dla tabeli uczestnicy . W pliku z kwerendami lub na zrzucie istnieje zapis np.: GRANT SELECT, UPDATE ON chat.uczestnicy TO uczestnik@localhost; oraz wynik działania udokumentowano zrzutem, na którym widoczne jest poprawnie wykonane zapytanie lub użytkownik z przydzielonymi prawami SELECT, UPDATE
ok. 2 min
Polecenie z arkusza
Zapytanie 5: nadające utworzonemu użytkownikowi prawa do wybierania i aktualizacji danych jedynie dla tabeli uczestnicy
GRANT SELECT, UPDATE ON chat.uczestnicy - tylko te dwa prawa i tylko ta tabela (chat.* dałoby dostęp do wszystkich tabel bazy). To zasada najmniejszych uprawnień: konto aplikacji dostaje tyle, ile potrzebuje, więc nawet przejęte nie odczyta haseł z logowanie. Sprawdzone: SHOW GRANTS pokazuje GRANT SELECT, UPDATE ON chat.uczestnicy. Zrzut: kw5.jpg.
kwerendy.txtTekstzmienione: 3 linie
-- Zapytanie 1INSERT INTO logowanie (id, nick, haslo)SELECT logowanie_id, 'Jeremi', 'Jer123'FROM uczestnicyWHERE imie = 'Jeremi' AND nazwisko = 'Kowalski';-- Zapytanie 2SELECT FLOOR(AVG(rokUr)) AS `Średni rok urodzenia`FROM uczestnicy;-- Zapytanie 3SELECT u.imie, u.nazwisko, l.nick, l.hasloFROM uczestnicy AS uJOIN logowanie AS l ON l.id = u.logowanie_idWHERE u.imie LIKE 'J%';-- Zapytanie 4CREATE USER 'uczestnik'@'localhost' IDENTIFIED BY 'Ucz123&';-- Zapytanie 5GRANT SELECT, UPDATE ON chat.uczestnicy TO 'uczestnik'@'localhost';
Podgląd strony po tym kroku
Etap 2: Grafika i strona HTML
Kroki 9-18 · po tym etapie masz 18 z 40 kryteriów (pkt)
Krok 9: Jolka.jpg: kadr do kwadratu i skala 70 × 70 px
Kryteria:
R.2.1 Plik Jolka.jpg wykadrowano do kwadratu, tak, aby była widoczna cała twarz. Wymiary grafiki to 70 px na 70 px
ok. 4 min
Polecenie z arkusza
Grafika Jolka.jpg przygotowana, podobnie jak Krzysiek.jpg. Grafikę Jolka.jpg należy wykadrować do kwadratu tak, aby była widoczna tylko cała twarz. Następnie należy przeskalować dokładnie do rozmiaru 70 px na 70 px.
Grafika jest taka sama jak w wersji podstawowej. Wzorem jest Krzysiek.jpg: sama twarz, 70 × 70 px. W GIMP-ie na Jolka.jpg (640 × 427):
Zaznaczanie prostokątne z opcją Stałe: Proporcje 1:1, obrys od czoła do brody, Obraz → Przytnij do zaznaczenia (tu kwadrat 180 × 180 od punktu 165, 70),
Obraz → Skaluj obraz: 70 × 70 - kadr jest kwadratem, więc twarz się nie spłaszcza,
Plik → Nadpisz Jolka.jpg.
Obraz obok to sam kadr przed skalowaniem.
Typowe błędy
Skalowanie całego zdjęcia do 70 × 70 bez kadrowania spłaszcza postać i nie pokazuje „tylko twarzy”.
Podgląd strony po tym kroku
Krok 10: Plik chat.html: HTML5, język, kodowanie
Kryteria:
R.2.2 Witrynę internetową zapisano w pliku chat.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 chat.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">, <meta charset="UTF-8"> jako pierwszy element <head> (R.2.2). Strona nie ma PHP, więc wystarczy rozszerzenie .html - plik otwiera się w przeglądarce prosto z folderu.
R.3.5 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
Tytuł strony widoczny na karcie przeglądarki: „Chat”. Arkusz stylów w pliku o nazwie styl.css prawidłowo połączony z kodem strony
<title> (R.2.3), <link> do styl.css (R.3.5) i viewport, żeby telefon nie pomniejszał strony.
R.2.4 Układ strony zdefiniowano dzieląc ją na bloki: banera, boczny, główny 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 i pod nim blok główny, obok obu bloków blok boczny oraz 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, blok główny main, blok boczny aside, stopka footer (R.2.4). Kolejność w kodzie to kolejność treści: najpierw okno rozmowy, potem lista chatów i uczestników. W tej kolejności czyta stronę czytnik ekranu i tak ułoży ją telefon. W wersji podstawowej aside musiał stać przed main, bo tego wymagało ułożenie bloków przez float; siatka CSS umieści bloki niezależnie od kolejności w kodzie.
R.2.8 W bloku bocznym umieszczono jedną listę punktowaną o dwóch elementach, z czego drugi zagnieżdża jedną listę numerowaną o czterech elementach. Zastosowano znaczniki <ul>, <ol>, <li>, zagnieżdżenie wewnątrz znacznika <li>
ok. 2 min
Polecenie z arkusza
Zawartość banera: nagłówek drugiego stopnia o treści „Chat”. Zawartość bloku bocznego: Nagłówek trzeciego stopnia o treści „Chaty”. Lista punktowana z elementami: „Ogólny” , „Tematyczne”. Drugi element zagnieżdża listę numerowaną z elementami „Turystyczny”, „Żeglarski”, „Filatelistyczny”, „Hodowla zwierzątek domowych”
<h2> w banerze, <h3> i <ul> w bloku bocznym. „Zagnieżdża” znaczy: <ol> stoi wewnątrz<li> z tekstem „Tematyczne”, przed jego </li> (R.2.8). Lista <ol> po </li> byłaby błędem - w <ul> mogą stać tylko elementy <li>.
R.2.7 W bloku bocznym obraz Jolka.jpg ma tekst alternatywny Jolanta Nowak a obraz Krzysiek.jpg ma tekst alternatywny Krzysztof Łukasiński
ok. 2 min
Polecenie z arkusza
Nagłówek trzeciego stopnia o treści „Uczestnicy”. Paragraf (akapit) o treści „Jolanta Nowak”. Obraz Jolka.jpg z tekstem alternatywnym "Jolanta Nowak". Paragraf o treści „Krzysztof Łukasiński”. Obraz Krzysiek.jpg z tekstem alternatywnym "Krzysztof Łukasiński".
Drugi <h3>, dwa akapity z imionami i dwa zdjęcia z tekstem alternatywnym (R.2.7). Nazwy plików z wielką literą, jak w archiwum - na serwerze wielkość liter w nazwach plików ma znaczenie.
R.2.6 W oknie chatu oraz bloku bocznym umieszczono dwa obrazy Jolka.jpg i Krzysiek.jpg
R.3.2 W bloku głównym zdefiniowano blok okna chatu zawierający dwa bloki
ok. 3 min
Polecenie z arkusza
Zawartość bloku głównego: Blok chatu zawierający: Jeden blok z wypowiedzią Jolanty: Obraz Jolka.jpg i paragraf: „Cześć idziesz jutro do kina?”. Jeden blok z wypowiedzią Krzysztofa: Obraz Krzysiek.jpg i paragraf: „Tak! A ty?”
okno rozmowy to <div id="chat"> - jedno na stronie, więc identyfikator; po nim skrypt znajdzie okno (R.3.2),
wypowiedź to <div> z dwiema klasami: message (wspólny wygląd) i jolanta albo krzysztof (kolor i strona zdjęcia). Wypowiedzi będzie wiele, więc klasy, nie identyfikatory - klucz R.4.9 wprost uznaje identyfikator za błąd,
w obu blokach zdjęcie stoi przed akapitem; na prawą stronę zdjęcie Krzysztofa przeniesie CSS.
Zdjęcia obojga są teraz i w oknie chatu, i w bloku bocznym (R.2.6).
Krok 16: Formularz: napis, pole edycyjne i przycisk „Wyślij”
ok. 3 min
Polecenie z arkusza
Obok siebie: napis „Wpisz wiadomość:”, pole edycyjne, przycisk o treści „Wyślij”. Kliknięcie przycisku powoduje wywołanie funkcji skryptu
Trzy elementy w formularzu<form id="message-form">:
<label for="text"> powiązany z polem - kliknięcie napisu ustawia kursor w polu,
pole z required (pustego formularza przeglądarka nie wyśle i sama pokaże podpowiedź) i autocomplete="off" (przeglądarka nie podsuwa starych wiadomości),
<button> w formularzu jest przyciskiem wysyłającym.
Po co formularz, skoro nic nie idzie na serwer? Bo formularz ma zdarzenie submit, które zachodzi i po kliknięciu „Wyślij”, i po naciśnięciu Enter w polu - skrypt obsłuży oba jednym kodem. Elementy są liniowe, więc stoją obok siebie bez CSS.
R.2.9 W bloku głównym umieszczono pole edycyjne oraz przyciski: "Wyślij" i "Generuj losową odpowiedź"
ok. 1 min
Polecenie z arkusza
Poniżej: przycisk o treści: „Generuj losową odpowiedź”. Kliknięcie przycisku powoduje wywołanie funkcji skryptu
Przycisk stoi poza formularzem, a formularz jest elementem blokowym - więc przycisk trafia do nowej linii bez <br>. type="button" mówi jasno, że niczego nie wysyła; identyfikator generate pozwoli podpiąć do niego funkcję. Blok główny ma już pole i oba przyciski (R.2.9).
R.2.5 W bloku banera zapisano nagłówek h2 "Chat", w bloku bocznym h3: "Chaty" i "Uczestnicy", poniżej dwa paragrafy, w bloku stopki nagłówek h5: "Chat wykonał: " z numerem zdającego. W oknie chatu zapisano dwa paragrafy
ok. 1 min
Polecenie z arkusza
Zawartość stopki: nagłówek piątego stopnia o treści: „Chat wykonał: ”, dalej wstawiony numer zdającego.
Tym razem nagłówek <h5>, nie akapit. Na egzaminie po dwukropku wpisujesz swój numer zdającego (PESEL), tu stoi autor rozwiązania. Komplet nagłówków i akapitów to R.2.5.
Domyślne formatowanie wszystkich selektorów: krój czcionki Garamond
Kolory z arkusza w zmiennych CSS na :root - Tomato występuje w banerze, stopce, przyciskach i ramce okna chatu. Selektor * z Garamondem i zapasowym krojem szeryfowym (Garamond jest szeryfowy); krój dostają też przyciski i pole, które nie dziedziczą go po <body> (R.4.1).
R.3.1 Układ bloków po uruchomieniu strony w przeglądarce jest zgodny z obrazem 2 w arkuszu egzaminacyjnym, nie należy brać pod uwagę zawartości bloku głównego (prawidłowo zastosowano właściwości CSS decydujące o układzie strony, np. float i clear albo display flex albo grid)
ok. 3 min
Polecenie z arkusza
Podział strony na baner i pod nim blok główny, obok obu bloków blok boczny oraz 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
grid-template-areas rysuje obraz 2 słowami: w lewej kolumnie baner, pod nim blok główny, w prawej - blok boczny w obu wierszach („obok obu bloków”), na dole stopka na całą szerokość (R.3.1). grid-template-columns: 80% 20% to od razu szerokości (klucz R.4.4 przyjmuje je w tej postaci), a align-items: start - bloki mają swoje wysokości z arkusza, zamiast rozciągać się do wiersza.
Kolejność bloków w kodzie nie ma tu znaczenia: aside stoi w HTML-u po main, a i tak trafia obok banera.
Dla banera: kolor tła Tomato, biały kolor czcionki, wyrównanie tekstu do środka, szerokość 80%, wysokość 80 px. Dla bloku głównego: szerokość 80%, wysokość 600 px. Dla bloku bocznego: kolor tła Coral, szerokość 20%, wysokość 680 px. Dla stopki: kolor tła Tomato, biały kolor czcionki, wyrównanie tekstu do środka.
Cechy z arkusza dopisane do reguł z polami siatki. Szerokości 80% i 20% dają kolumny - dodatkowe width: 80% liczyłoby się od kolumny. 680 px bloku bocznego = 80 px banera + 600 px bloku głównego, więc blok boczny sięga od góry banera do dołu bloku głównego, jak na obrazie 2.
Dla selektora obrazu: zaokrąglenie rogów 50%, marginesy wewnętrzne lewy i prawy 10 px
border-radius: 50% robi z kwadratowego zdjęcia koło (R.4.8). padding-inline: 10px - właściwość logiczna, jednocześnie lewy i prawy margines wewnętrzny, bez ruszania górnego i dolnego (to samo co padding: 0 10px). Zgodnie z uwagą arkusza selektor to sam znacznik img.
R.4.3 Ustawiono wysokość bloków banera 80px, głównego 600px i bocznego 680px oraz bloku chatu 470px
ok. 2 min
Polecenie z arkusza
Dla bloku chatu: obramowanie linią ciągłą o szerokości 1 px i kolorze Tomato, marginesy zewnętrzne 15 px, wysokość 470 px, paski przewijania zawsze widoczne na stronie
„Paski przewijania zawsze widoczne” to overflow: scroll (przy auto pojawiłyby się dopiero po zapełnieniu okna). Stała wysokość 470 px sprawia, że kolejne wypowiedzi nie rozciągają strony, tylko okno się przewija. Wysokości banera, bloków i okna chatu to komplet R.4.3.
R.4.9 Ustawiono styl dla obu bloków z wypowiedziami: zaokrąglenie rogów 5px, szerokość 90%, wysokość 70px, marginesy zewnętrzne 2%, marginesy wewnętrzne 3px (np. za pomocą klasy, id jest błędem)
ok. 1 min
Polecenie z arkusza
Wspólne dla bloków z wypowiedziami: zaokrąglenie rogów 5 px, szerokość 90%, wysokość 70 px, marginesy zewnętrzne 2%, marginesy wewnętrzne 3 px
Klasa .message - także przy wypowiedziach dokładanych przez skrypt (R.4.9). Wysokość 70 px to dokładnie wysokość zdjęć.
R.3.3 W bloku z wypowiedziami Jolanty obraz jest opływany tekstem po prawej stronie a z wypowiedziami Krzysztofa po stronie lewej
R.4.10 Ustawiono kolor tła bloku wypowiedzi Jolanty #EEE oraz wypowiedzi Krzysztofa #CCC, wypowiedzi Krzysztofa są wyrównane do prawej strony
ok. 2 min
Polecenie z arkusza
Dodatkowo dla bloków z wypowiedziami Jolanty: kolor tła #EEE, obraz opływany tekstem z prawej strony (obraz po lewej stronie). Dodatkowo dla bloków z wypowiedziami Krzysztofa: kolor tła #CCC, wyrównanie tekstu do prawej strony, obraz opływany tekstem z lewej strony (obraz po prawej stronie).
Tu float zostaje, bo robi dokładnie to, do czego powstał: opływanie obrazu tekstem - arkusz mówi to wprost, a klucz R.3.3 ocenia opływanie. Siatka służy do układu bloków strony, float do obrazka w akapicie. Selektor .jolanta img dotyczy tylko zdjęć w wypowiedziach Jolanty, więc zdjęcia w bloku bocznym zostają na miejscu (R.3.3, R.4.10).
R.4.2 Ustawiono kolor tła Tomato dla bloków banera, stopki i przycisków; Coral dla bloku bocznego oraz biały kolor czcionki dla banera i stopki
R.4.4 Ustawiono szerokość bloków banera i głównego 80%, bloku bocznego 20% (width lub grid- template-columns lub flex) oraz pola edycyjnego 500px
R.4.5 Ustawiono wyrównanie tekstu do środka dla banera i stopki oraz czcionkę pogrubioną dla przycisków
R.4.6 Ustawiono marginesy wewnętrzne (padding) lewy i prawy 10px dla selektora img, 5px dla przycisków oraz marginesy zewnętrzne (margin) dla bloku chatu 15px
R.4.7 Ustawiono obramowanie linią ciągłą o szerokości 1px i kolorze Tomato dla bloku chatu oraz obramowanie linią ciągłą o szerokości 1px i kolorze DarkRed dla przycisków oraz paski przewijania zawsze widoczne na stronie (overflow: scroll;) dla bloku chatu
ok. 2 min
Polecenie z arkusza
Dla obu przycisków: kolor tła Tomato, obramowanie linią ciągłą o szerokości 1 px i kolorze DarkRed, marginesy wewnętrzne 5 px, czcionka pogrubiona. Dla pola edycyjnego tekstowego: szerokość 500 px
Selektor button obejmuje oba przyciski - także ten w formularzu. Ta reguła domyka kolory tła (R.4.2), pogrubienie obok wyśrodkowania banera i stopki (R.4.5), marginesy wewnętrzne i zewnętrzne (R.4.6) oraz obramowania razem z przewijaniem chatu (R.4.7). Pole przez identyfikator - z szerokościami kolumn to R.4.4.
Kroki 27-32 · po tym etapie masz 40 z 40 kryteriów (pkt)
Krok 27: Wyślij: tekst z pola na końcu okna chatu
Kryteria: , ,
R.5.1 Skrypt zapisano w języku JavaScript i zawiera on przynajmniej jedną instrukcję zapisaną zgodnie ze składnią
R.5.2 Funkcja wywoływana przyciskiem Wyślij pobiera dane z pola edycyjnego
R.5.3 Dane z pola edycyjnego są wyświetlane w oknie chatu
ok. 3 min
Polecenie z arkusza
Działanie funkcji wywoływanej po kliknięciu przycisku Wyślij: Pobierany jest tekst z pola edycyjnego i umieszczany w oknie chatu jako ostatni
Skrypt na końcu <body> - gdy przeglądarka go czyta, wszystkie elementy strony już istnieją.
const - stałe na elementy strony: okno chatu, formularz i pole. querySelector przyjmuje selektor CSS (#chat), ten sam co w arkuszu stylów,
addEventListener("submit", ...) - funkcja (tu zapisana strzałką (event) => { ... }) wykona się po kliknięciu „Wyślij” albo po Enterze w polu,
event.preventDefault() - bez tego formularz zrobiłby to, do czego służy: przeładowałby stronę i wiadomość by zniknęła,
textField.value - tekst z pola (R.5.2), textContent wpisuje go do nowego akapitu jako zwykły tekst, a append dokłada akapit na koniec okna - jako ostatni (R.5.3).
Na razie tekst pojawia się bez tła i zdjęcia. Podgląd działa: wpisz coś i naciśnij Enter.
Krok 28: Wyślij: blok wypowiedzi Jolanty z szablonu
Kryteria:
R.5.4 Dane z funkcji związanej z przyciskiem Wyślij są formatowane jako wypowiedzi Jolanty (tak samo jak pierwsza wypowiedź w chacie)
ok. 4 min
Polecenie z arkusza
Tekst jest formatowany jako wypowiedź Jolanty, zgodnie z obrazem 3, czyli utworzony jest blok z wypowiedzią zawierający obraz Jolka.jpg i paragraf zgodny z tekstem wpisanym do pola edycyjnego
w HTML-u, pod formularzem, <template> z wzorem wypowiedzi: div.message z obrazem i akapitem. Zawartości szablonu przeglądarka nie wyświetla ani nie wczytuje (pusty src niczego nie pobiera) - to tylko wzór do kopiowania,
obiekt AUTHORS trzyma dane obojga uczestników: plik zdjęcia i podpis. Klucz obiektu (jolanta) jest też nazwą klasy CSS,
funkcja addMessage(text, authorKey): cloneNode(true) kopiuje wzór z całą zawartością, classList.add dokłada klasę autora, a potem uzupełnia zdjęcie, tekst alternatywny i akapit. Blok ma tę samą budowę co pierwsza wypowiedź w HTML-u (R.5.4).
Wygląd wypowiedzi jest więc opisany w jednym miejscu, w HTML-u, a skrypt tylko wypełnia dane. Sprawdzone w Chrome: wiadomość „Ok, cieszę się” dostaje ten sam wygląd co „Cześć idziesz jutro do kina?” (obraz 3).
R.5.5 Po zapełnieniu bloku chatu następuje przewinięcie do nowo wstawionej wypowiedzi dla przynajmniej jednej funkcji.
ok. 2 min
Polecenie z arkusza
Jeśli blok chatu jest cały wypełniony, powinien być przewinięty do nowo wstawionej wypowiedzi
scrollTop to odległość przewinięcia okna od góry, a scrollHeight - wysokość całej jego zawartości. Ustawienie pierwszego na drugie przewija okno chatu na sam dół, do nowej wypowiedzi (R.5.5). Gdy okno nie jest pełne, nie ma czego przewijać - warunek „jeśli wypełniony” spełnia się sam. Przewija się tylko okno chatu; scrollIntoView() z tabeli arkusza przewinąłby przy okazji całą stronę.
R.5.6 W kodzie zdefiniowano tablicę z dziewięcioma wypowiedziami Krzysztofa
ok. 2 min
Polecenie z arkusza
Losowana jest wypowiedź Krzysztofa z wcześniej zadeklarowanej tablicy. Tablica zawiera 9 elementów, którymi są wypowiedzi. Należy je skopiować z pliku pomocniczego tekstyDoChatu.txt rozpakowanego z archiwum
Plik tekstyDoChatu.txt jest gotowy do wklejenia: teksty w cudzysłowach, z przecinkami. Wystarczy objąć je nawiasami kwadratowymi i nazwać tablicę - replies, jako const: tablica nie zostanie podmieniona na inną. Stoi poza funkcjami, więc powstaje raz, przy wczytaniu strony („wcześniej zadeklarowana”) (R.5.6).
Krok 31: Generuj: losowa odpowiedź jako wypowiedź Krzysztofa
Kryteria: , ,
R.3.4 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.7 Funkcja wywoływana przyciskiem Generuj… losuje index tablicy z wypowiedziami Krzysztofa (liczba od 0 do 8), wypowiedź o tym indeksie jest wyświetlana w oknie chatu (sprawdzić w kodzie i w przeglądarce)
R.5.8 Dane z funkcji związanej z przyciskiem Generuj... są formatowane jako wypowiedzi Krzysztofa (tak samo jak druga wypowiedź w chacie)
ok. 3 min
Polecenie z arkusza
Losowana liczba z przedziału od 0 do 8 jest indeksem tablicy. Wypowiedź jest umieszczana w oknie chatu jako ostatnia. Tekst jest formatowany jako wypowiedź Krzysztofa, zgodnie z obrazem 4, czyli utworzony jest blok z wypowiedzią zawierający obraz Krzysiek.jpg i paragraf zgodny z wylosowanym tekstem
addEventListener("click", ...) na przycisku #generate - kliknięcie wywołuje funkcję (R.3.4),
Math.random() daje ułamek od 0 (włącznie) do 1 (bez jedynki); po pomnożeniu przez replies.length, czyli 9, i obcięciu Math.floor wychodzi liczba całkowita od 0 do 8 - poprawny indeks tablicy (R.5.7). Długość tablicy zamiast wpisanej 9: dopisanie dziesiątego tekstu nie wymaga zmiany losowania,
ta sama addMessage z kluczem krzysztof - zdjęcie po prawej, ciemniejsze tło, tekst do prawej (obraz 4) i przewinięcie okna (R.5.8). Formatowania i przewijania nie trzeba pisać drugi raz.
Krok 32: Pusta wiadomość pominięta, pole czyszczone
Kryteria:
R.5.9 Zastosowano znaczące nazewnictwo dla wszystkich zmiennych i funkcji w języku polskim lub angielskim. Nazwy odzwierciedlają cel zastosowania.
ok. 3 min
Dodatek spoza arkusza - klucz go nie ocenia. required w polu zatrzymuje pusty formularz, ale wiadomość z samych spacji przechodzi. Dlatego:
trim() obcina spacje z początku i końca, a dla pustego napisu funkcja kończy się od razu (return),
po wysłaniu messageForm.reset() czyści pole, a focus() zostawia w nim kursor - kolejną wiadomość można pisać od razu.
Sprawdzone w prawdziwym Chrome: wiadomość „Ok, cieszę się” trafia na koniec okna jako message jolanta ze zdjęciem i podpisem, pole jest czyszczone; losowanie (przy Math.random zwracającym 0,95) daje ostatni tekst tablicy w bloku message krzysztof; po 12 kolejnych odpowiedziach okno chatu jest przewinięte do końca, a strona stoi w miejscu; spacje i puste pole nie dodają niczego; <b>X</b> wyświetla się dosłownie, bo textContent nie tworzy znaczników. Nazwy zmiennych i funkcji mówią, do czego służą (R.5.9).
dwie funkcje z createElement (w dobrych praktykach addMessage)
<template> + cloneNode i obiekt AUTHORS
tekst wiadomości
innerText
textContent
przewijanie
scrollIntoView() (przewija też stronę)
scrollTop = scrollHeight (tylko okno chatu)
zmienne
let
const
Na egzaminie wersja podstawowa trzyma się funkcji z tabel arkusza i łatwiej ją napisać bez podpowiedzi. Nowoczesna ma wygląd wypowiedzi w jednym miejscu (szablon), a dodanie trzeciego uczestnika to jeden wpis w AUTHORS i jedna reguła CSS. float został w obu wersjach tam, gdzie jest naturalny - przy zdjęciu opływanym tekstem.
Krok 34 · po tym etapie masz 40 z 40 kryteriów (pkt)
Krok 34: 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 nazwa przeglądarki, w której była sprawdzana strona. W folderze z numerem zdającego: chat.html, styl.css, kwerendy.txt, import.png, kw1.jpg - kw5.jpg, przycięte Jolka.jpg, Krzysiek.jpg i przeglądarka.txt. Nagraj płytę, sprawdź jej odczyt i opisz ją numerem zdającego.
Symulacja ekranu w przeglądarce - w Android Studio / Visual Studio wygląd może się nieco różnić.
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: Bartosz Bryniarski. 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.