IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

7. diel - Vylepšenia objektového diáre v JavaScripte

V minulej lekcii, Objekty, JSON a vylepšenia diáre v JavaScripte , sme si vylepšili náš diár o ukladaní do localStorage. Dnes doplníme radenie záznamov podľa dátumu, zoskupovanie záznamov s rovnakým dátumom a odstránenie záznamov.

Výpis záznamov

Najprv si upravíme výpis našich záznamov. Bolo by vhodné záznamy zoradiť podľa dátumu a zoskupiť záznamy v rovnaký deň, ktoré vypíšeme pod sebou v jednom bloku.

Radenie

Najskôr si naimplementujeme metódu na radenie záznamov. K tomu použijeme metódu sort() na poli. Tá dokáže pole zoradiť postupným porovnávaním dvojíc prvkov. Ako parameter prijíma porovnávaciu funkciu, ktorá definuje akým spôsobom sa majú 2 prvky v poli porovnať. Naša metóda k zoradenie záznamov v poli podľa dátumu bude v triede Diar vyzerať nasledovne:

seradZaznamy() {
    this.zaznamy.sort(function (zaznam1, zaznam2) {
        return (new Date(zaznam1.datum) - new Date(zaznam2.datum));
    });
}

Funkcia porovnáva dáta dvoch záznamov, ktorá si naparsujeme na dátum pomocou konštruktory objektu Date. Zo záznamu samozrejme vyberieme vlastnosť datum. Porovnanie dvoch dátumov vykonáme jednoducho pomocou operátora -, čím sa vráti ich rozdiel v milisekundách. Pokiaľ bude prvý dátum až po druhom, vráti sa záporné číslo. Pokiaľ budú rovnaké, vráti sa 0. Inak sa vráti kladné číslo. Práve kladné, záporné alebo nulové číslo metóda sort() pre svoju prácu potrebuje a tým zistí, či je dátum väčšie, menšie alebo rovné.

Metódu budeme volať pred každým výpisom záznamov:

vypisZaznamy() {
    this.seradZaznamy();
    this.vypisElement.innerHTML = "";
    for (let i = 0; i < this.zaznamy.length; i++) {
        const zaznam = this.zaznamy[i];
        this.vypisElement.innerHTML += `<h3>${zaznam.nazev}</h3>kdy: ${zaznam.datum}<br>splněno: ${zaznam.splneno}`;
    }
}

Zoradenie by sme mohli tiež volať po pridaní záznamu a po ich načítaní, aby sa nemuselo volať pri každom výpise. Nevýhodou tohto riešenia by však bolo, že by sme na neho mohli zabudnú pri inej manipulácii so záznamami.

Ak teraz diár spustíme a máme v localStorage už nejaké dáta, vypíšu sa nám už zoradené podľa dátumu.

Zoskupovanie

Teraz výpis záznamov dokončíme. Budeme teda vypisovať dátum ak tomuto dátumu vždy všetky záznamy v daný deň. Náš cyklus ľahko upravíme:

vypisZaznamy() {
    this.seradZaznamy();
    this.vypisElement.innerHTML = "";
    let posledniDatum = null;
    for (const zaznam of this.zaznamy) {
        if (zaznam.datum !== posledniDatum) {
            this.vypisElement.innerHTML += `<h3>${zaznam.datum}</h3>`
        }
        posledniDatum = zaznam.datum;

        this.vypisElement.innerHTML += `<strong>${zaznam.nazev}</strong><br>splněno: ${zaznam.splneno}<hr>`;
    }
}

Do premennej posledniDatum priradíme vlastnosť datum z predchádzajúceho záznamu. Pretože pri prvom priebehu cyklu posledný záznam ešte nie je, nastavíme premennú prvýkrát na null. Dátum súčasného záznamu potom vypíšeme len ak sa líši od predchádzajúceho. Tak sa záznamy v rovnaký deň budú zoskupovať. Teraz máme vypísané pekne úlohy s rovnakým dátumom pod sebou a zoradené:

Tvoja stránka
localhost

Formátovanie dáta a splněnosti

Keďže formát dátumu a splněnost úlohy tiež nie je ideálne, je potrebné tieto výpisy upraviť do "ľudskejší" podoby :) Pamätáte na vlastnosť jazyk, ktorú môžeme ovplyvniť v konstruktoru? Teraz jej využijeme k lepšiemu výpisu dáta a zároveň si vylepšíme výpis splněnosti úloh:

vypisZaznamy() {
    this.seradZaznamy();
    this.vypisElement.innerHTML = "";
    let posledniDatum = null;
    for (const zaznam of this.zaznamy) {
        if (zaznam.datum !== posledniDatum) {
            const datum = new Date(zaznam.datum).toLocaleDateString(this.jazyk, {
                weekday: "long",
                day: "numeric",
                month: "short",
                year: "numeric"
            });
            this.vypisElement.innerHTML += `<h3>${datum}</h3>`
        }
        posledniDatum = zaznam.datum;

        this.vypisElement.innerHTML += `<strong>${zaznam.nazev}</strong><br>úkol ${!zaznam.splneno ? "ne" : ""}splněn<hr>`;
    }
}

Vytvoríme inštanciu objektu Date z nášho dátumu a použijeme jej metódu toLocaleString(), kam odovzdáme ako prvý parameter vlastnosť jazyk našej triedy a ako druhý parameter formátovacie objekt, ktorého vlastnosti udávajú ako presne sa má dátum vypísať.

U splněnosti úlohy sme použili jednoduchý ternárne operátor, podľa nesplněnosti pridáme "ne" alebo prázdny string.

Výsledok teraz vyzerá takto:

Tvoja stránka
localhost

Mazanie záznamov

Budeme pokračovať základné interakcií s našimi úlohami, budeme ich môcť mazať, alebo ich označiť ako splnené. Začneme mazaním.

Uloženie záznamov

Keďže po zmazaní bude potrebné záznamy znova uložiť, vyčlení si uloženie záznamov z metódy nastavUdalosti() do samostatnej metódy ulozZaznamy():

ulozZaznamy() {
    localStorage.setItem("zaznamy", JSON.stringify(this.zaznamy));
}

V metóde nastavUdalosti() teraz metódu ulozZaznamy() zavoláme:

nastavUdalosti() {
    this.potvrditButton.onclick = () => { // this zůstane nyní stále this
        const zaznam = new Zaznam(this.nazevInput.value, this.datumInput.value);
        this.zaznamy.push(zaznam);
        this.ulozZaznamy();
        this.vypisZaznamy();
    };
}

Tlačidlo

Ku každému záznamu vygenerujeme tlačidlo na jeho odstránenie. To vytvoríme ako nový element <button> pomocou metódy document.createElement() a do <div> us výpisom záznamov ho vložíme pomocou appendChild(). Tlačidlu takisto pridáme udalosť reakcie na kliknutie, kedy daný záznam odstránime z poľa, záznamy takto přeuložíme do localStorage a znova vypíšeme. Metóda vypisZaznamy() bude po pridaní mazacieho tlačidla vyzerať takto:

vypisZaznamy() {
    this.seradZaznamy();
    this.vypisElement.innerHTML = "";
    let posledniDatum = null;
    for (const zaznam of this.zaznamy) {
        if (zaznam.datum !== posledniDatum) {
            const datum = new Date(zaznam.datum).toLocaleDateString(this.jazyk, {
                weekday: "long",
                day: "numeric",
                month: "short",
                year: "numeric"
            });
            this.vypisElement.innerHTML += `<h3>${datum}</h3>`
        }
        posledniDatum = zaznam.datum;

        this.vypisElement.innerHTML += `<strong>${zaznam.nazev}</strong>
        <br>úkol ${!zaznam.splneno ? "ne" : ""}splněn`;
        const smazatButton = document.createElement("button");
        smazatButton.onclick = () => {
            if (confirm("Opravdu si přejete odstranit úkol?")) {
                this.zaznamy = this.zaznamy.filter(z => z !== zaznam); // Ponechá vše co není rovné proměnné zaznam
                this.ulozZaznamy();
                this.vypisZaznamy();
            }
        };
        smazatButton.innerText = "Smazat záznam";
        this.vypisElement.appendChild(smazatButton);
        this.vypisElement.innerHtml += "<br>";
    }
}

Všimnite si použitie potvrdzujúceho dialógu confirm(), odstránenie záznamu je určite akcia, ktorú nechceme urobiť omylom :)

Možno by vás napadlo vložiť tlačidlo rovno do HTML kódu ako text a priradiť mu do dátumu atribútu index záznamu v poli, ktorý má zmazať. Takáto tlačidla by sa potom niekde všetky vybrala a obslúžila tak, aby z poľa zmazala prvok pod daným indexom. Problém by však nastal, keby sme diár otvorili vo viacerých záložkách naraz. Keď by sme v jednej záložke zmazali nejakú položku a druhú záložku neobnovili, táto položka by tu stále bola, ale v localStorage by pod týmto indexom už bola položka iná. Mohli by sme tak na prvotne záložke nechtiac zmazať inú úlohu. Preto budeme všetku manipuláciu s položkami vždy robiť priamo pomocou anonymných funkcií, kam túto jednu konkrétnu položku odovzdáme.

Ak krútite hlavou nad kódom odstraňujúcim položku:

this.zaznamy = this.zaznamy.filter(z => z !== zaznam);

Je to v súčasnej dobe žiaľ najjednoduchší spôsob, ako v JavaScripte zmazať prvok v poli, ktorého index nepoznáme a nechceme ho zbytočne zisťovať. Kód prefiltrujú dané pole tak, že v ňom zostanú len záznamy, ktoré sa nerovnajú záznamu, ktorý chceme odstrániť.

Pokračovať budeme zas nabudúce, v lekcii Kvíz - Dátové typy a dátové úložiská v JavaScripte , kedy pridáme tlačidlo na splnenie úlohy, validáciu dáta a diár dokončíme pridaním jednoduchých CSS štýlov :)

V nasledujúcom kvíze, Kvíz - Dátové typy a dátové úložiská v JavaScripte, si vyskúšame nadobudnuté skúsenosti z predchádzajúcich lekcií.


 

Predchádzajúci článok
Objekty, JSON a vylepšenia diáre v JavaScripte
Všetky články v sekcii
Objektovo orientované programovanie v JavaScriptu
Preskočiť článok
(neodporúčame)
Kvíz - Dátové typy a dátové úložiská v JavaScripte
Článok pre vás napísal Šimon Raichl
Avatar
Užívateľské hodnotenie:
2 hlasov
Autor se věnuje hlavně tvorbě všemožných věcí v JS
Aktivity