Lekce 10 - Dokončení objektového diáře v JavaScriptu
V minulé lekci, OOP diář v JavaScriptu - Formátování a mazání záznamů, jsme do našeho objektového diáře v JavaScriptu přidali několik dalších funkcí.
V dnešním tutoriálu objektově orientovaného programování v JavaScriptu do našeho diáře přidáme tlačítko pro splnění úkolu a jednoduchou validaci dat. Diář nakonec i celý dokončíme doplněním pár CSS stylů.
Změna splnění záznamů
Poslední funkcionalita, která nám chybí, je možnost označit úkoly jako splněné. Pro tuto funkcionalitu přidáme do diáře nové tlačítko.
Obecná metoda pro tvorbu tlačítek
Protože tlačítko na splnění úkolu bude vypadat a fungovat velmi
podobně jako mazací tlačítko, nebudeme do aplikace zbytečně vkládat
duplicitní kód, ale upravíme ten stávající. Nejprve si do třídy
Diar
přidáme novou pomocnou metodu
#vytvorTlacitko()
:
#vytvorTlacitko(titulek, obsluha) { const button = document.createElement("button"); button.onclick = obsluha; button.innerText = titulek; return button; }
Metoda dělá přesně to, co naše metoda
#vytvorMazaciTlacitko()
. Titulek a obslužnou metodu tlačítka
ovšem nastavuje z parametru, takže ji můžeme použít pro
vytvoření různých tlačítek s různými titulky a
funkcemi.
Úprava metody
#vytvorMazaciTlacitko()
Nově vytvořenou metodu můžeme uplatnit ve zmíněné metodě
#vytvorMazaciTlacitko()
. Upravíme ji následujícím
způsobem:
#vytvorMazaciTlacitko(zaznam) { return this.#vytvorTlacitko("Smazat", () => { if (confirm("Opravdu si přejete odstranit úkol?")) { this.#zaznamy = this.#zaznamy.filter(z => z !== zaznam); this.#ulozZaznamy(); this.vypisZaznamy(); } }); }
Tělo metody #vytvorMazaciTlacitko()
je nyní tvořeno pouze
jedním voláním metody #vytvorTlacitko()
. Té jsme jako první
parametr zadali popisek tlačítka Smazat
a jako druhý anonymní
funkci s logikou pro smazání záznamu.
Don't Repeat Yourself
Pomocnou metodu #vytvorTlacitko()
jsme si vytvořili záměrně
až nyní a ne již před přidáním prvního tlačítka. To abychom si
ukázali, jak se v praxi řeší situace, kdy potřebujeme do aplikace vložit
nějaký velmi podobný kód. Stávající kód vyčleníme do pomocné
metody a parametrizujeme jej.
Prezence duplicitního kódu porušuje princip DRY (Don't Repeat Yourself), jedno z nejdůležitějších pravidel kvalitního objektového návrhu. Více se o něm dočteme v lekci Best practices pro vývoj softwaru - Základní praktiky.
Tlačítko na splnění záznamu
Po malé odbočce se vraťme zpět k novému tlačítku. To budeme vytvářet
pomocí nové pomocné metody #vytvorTlacitkoSplneni()
. Přidejme
si ji do třídy Diar
:
#vytvorTlacitkoSplneni(zaznam) { const titulek = "Označit jako " + (zaznam.splneno ? "nesplněný" : "splněný"); return this.#vytvorTlacitko(titulek, () => { zaznam.splneno = !zaznam.splneno; this.#ulozZaznamy(); this.vypisZaznamy(); }); }
Metoda se moc neliší od metody #vytvorMazaciTlacitko()
. Má
pouze jeden parametr, kterým přijímá označovaný záznam. Na základě
hodnoty vlastnosti splneno
vytváříme titulek tlačítka. Titulek
následně spolu s obslužnou funkcí tlačítka předáváme metodě
#vytvorTlacitko()
.
Vytvoření tlačítka
Nyní už jen zbývá rozšířit metodu vypisZaznamy()
.
Tlačítko na splnění zde stejně jako mazací tlačítko vytvoříme ke
každému záznamu a vložíme jej do elementu pro výpis:
vypisZaznamy() { this.#seradZaznamy(); this.#vypisElement.innerHTML = ""; let posledniDatum = null; for (const zaznam of this.#zaznamy) { /* Zbývající kód cyklu... */ const smazatButton = this.#vytvorMazaciTlacitko(zaznam); this.#vypisElement.appendChild(smazatButton); const splnitButton = this.#vytvorTlacitkoSplneni(zaznam); this.#vypisElement.appendChild(splnitButton); this.#vypisElement.insertAdjacentHTML("beforeend", "<hr>"); } }
Výsledek si můžeme vyzkoušet:
Ošetření vstupu
Máme tedy plně funkční diář s ukládáním do úložiště
localStorage
. Jediné, co nám ještě chybí, je ošetřit vstupy.
Pokud totiž uživatel nezadá datum, bude se nám vypisovat jako
Invalid Date
a diář nebude správně fungovat.
Doplníme proto obslužnou funkci v metodě #nastavUdalosti()
naší třídy Diar
o jednoduchou validaci:
#nastavUdalosti() { this.#potvrditButton.onclick = () => { if (this.#nazevInput.value.length === 0) { alert("Musíte vyplnit název!"); return; } if (this.#datumInput.value === "") { alert("Musíte vyplnit datum!"); return; } const zaznam = new Zaznam(this.#nazevInput.value, this.#datumInput.value); this.#zaznamy.push(zaznam); this.#ulozZaznamy(); this.vypisZaznamy(); }; }
Díky tomu, že <input type="date">
vrací
value
jako prázdný řetězec, když je datum neúplné, není
těžké uživatele na tento stav upozornit. Podobně to děláme u názvu, kde
pro jednoduchost bráníme uživateli vložit pouze prázdný řetězec, čili
délka hodnoty inputu nesmí být 0
.
Pokud nyní nebude zadáno datum správně, nebo uživatel nezadá alespoň
jeden znak do názvu úkolu, upozorníme uživatele funkcí
alert()
. V opačném případě nový záznam uložíme
Design
Nakonec zbývá už jen design, který si rychle prolétneme a jen
minimálně upravíme v JavaScriptu. V projektu si nejprve vytvoříme složku
css/
a přidáme do ní soubor styly.css
. Jeho obsah
bude následující:
* { font-family: Segoe UI Light, "Calibri Light", sans-serif; } body { margin-inline: auto; padding-inline: 1.5rem; max-width: 960px; } button { padding: 0.75rem 1rem; font-weight: 600; background: #2792e0; color: #fff; border: none; cursor: pointer; transition: .5s; } button:hover { background: #2954c2; } button:active { background: #204199; } input { min-width: 250px; padding: 0.5rem; border: 1px solid #c5c5c5; } button, input { margin-top: 1rem; outline: none; } .ukol { padding: 1rem; margin: 1rem auto; border: 1px solid #c5c5c5; } .ukol h3 { margin-top: 0; margin-bottom: 0.75rem; } .zelene { color: green; } .cervene { color: red; } .tucne { font-weight: bold; }
Styly nalinkujeme v hlavičce stránky index.html
:
<head> <meta charset="UTF-8"> <title>Diář</title> <link href="css/styly.css" rel="stylesheet"> </head>
Poslední úpravy výpisu
A nyní jen lehce upravíme výpis záznamů. Přesuneme se tedy naposledy do
metody vypisZaznamy()
a obsah každého záznamu obalíme elementem
<article>
:
vypisZaznamy() { this.#seradZaznamy(); this.#vypisElement.innerHTML = ""; let posledniDatum = null; for (const zaznam of this.#zaznamy) { if (zaznam.datum !== posledniDatum) { const naformatovaneDatum = this.#naformatujDatum(zaznam.datum); this.#vypisElement.insertAdjacentHTML("beforeend", `<h2>${naformatovaneDatum}</h2>`); } posledniDatum = zaznam.datum; // Následující kód byl upraven const ukol = document.createElement("article"); ukol.className = "ukol"; ukol.insertAdjacentHTML( "beforeend", `<h3>${zaznam.nazev}</h3> <span> úkol ${!zaznam.splneno ? "<span class='cervene tucne'>ne" : "<span class='zelene tucne'>"}splněn</span> </span> <br>`); const smazatButton = this.#vytvorMazaciTlacitko(zaznam); ukol.appendChild(smazatButton); const splnitButton = this.#vytvorTlacitkoSplneni(zaznam); ukol.appendChild(splnitButton); this.#vypisElement.appendChild(ukol); } }
Ihned po případném vypsání data vytváříme zmiňovaný element
<article>
s nastavenou CSS třídou .ukol
. Do
něj pak vkládáme všechen obsah záznamu včetně názvu, splněnosti a obou
tlačítek. Za zmínku zde stojí upravený výpis splněnosti úkolu, který
obarvujeme buď červeně, anebo zeleně. Samotný element
<article>
nakonec vkládáme do elementu pro výpis.
Výsledek
Podívejme se na náš vylepšený diář v prohlížeči:
Tak a je hotovo! Máme
celkem pěkně vypadající diář, který ukládá data a lze jej reálně
používat.
V příští lekci, AJAX v JavaScriptu - Základní dotazy, na nás čeká populární technologie AJAX a tvorba malého projektu.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 1354x (4.1 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript