Zarábaj až 6 000 € mesačne! Akreditované rekvalifikačné kurzy od 0 €. Viac informácií.

Diskusia – 8. diel - Dokončenie objektového diáre v JavaScripte

Späť

Upozorňujeme, že diskusie pod našimi online kurzami sú nemoderované a primárne slúžia na získavanie spätnej väzby pre budúce vylepšenie kurzov. Pre študentov našich rekvalifikačných kurzov ponúkame možnosť priameho kontaktu s lektormi a študijným referentom pre osobné konzultácie a podporu v rámci ich štúdia. Toto je exkluzívna služba, ktorá zaisťuje kvalitnú a cielenú pomoc v prípade akýchkoľvek otázok alebo projektov.

Komentáre
Avatar
x.listo
Tvůrce
Avatar
x.listo:23.1.2019 20:06

Ukázková aplikace hezká, jen úplně nefunguje, včetně staženého zdrojového kódu.

Chyba je, že nefunguje kliknutí na tlačítka Smaž a Označit jako. Pokud je uložených více úkolů, kliknutí funguje jen na poslední zobrazený úkol.

Chyba je v řádcích kde se slučuje this.vypisEle­ment.innerHTML.

this.vypisElement.innerHTML += `<h3>${datum}</h3>`;

Tento řádek jsem nahradil tímto:

this.dt = document.createElement("div");
this.dt.innerHTML = `<h3>${datum}</h3>`;
this.dt.className = "datum";
this.vypisElement.appendChild(this.dt);

Původní:

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

Nový:

const ukol = document.createElement("div");
ukol.innerHTML = `<br><strong>${zaznam.nazev}</strong><br>kdy: ${zaznam.datum}<br>splněno: ${!zaznam.splneno ? "ne" : ""}splněn`;
ukol.className = "ukol";
this.dt.appendChild(ukol);
Editované 23.1.2019 20:09
 
Odpovedať
23.1.2019 20:06
Avatar
Martin Ko
Člen
Avatar
Odpovedá na x.listo
Martin Ko:16.3.2019 9:05

mě nepomohlo ani opravit podle tebe . button smazat záznam nereaguje ikdyž jsem zkoušel localStorage.re­moveItem()

 
Odpovedať
16.3.2019 9:05
Avatar
Tadeáš
Člen
Avatar
Odpovedá na x.listo
Tadeáš:3.4.2019 19:08

Mohl by jsi říct proč je to potřeba a nefunguje to dle tutoriálu? :)

 
Odpovedať
3.4.2019 19:08
Avatar
x.listo
Tvůrce
Avatar
x.listo:3.4.2019 20:59

Přesně důvod popsat nedokáži. Předpokládám, že to bude souviset s přepisováním proměnných. Každému tlačítku se přiřazuje funkce. S každým cyklem se přiřadí jen k poslednímu. Možná pro pochopení může pomoci tento krátký skript.

for (var i=0; i<5; i++) {
    var btn = document.createElement('button');
    btn.innerHTML = i;
    btn.onclick = function() {alert(i)}

    document.body.appendChild(btn);
}

var br = document.createElement("br");
document.body.appendChild(br);

for (var i=0; i<5; i++) {
    var btn = document.createElement('button');
    btn.innerHTML = i;
    const j = i;
    btn.onclick = function() {alert(j)}

    document.body.appendChild(btn);
}

První cyklus vypíše 5 tlačítek a po stisknutí se objeví varovné okno s indexem i. V tomto případě u každého tlačítka je hodnota 5. V druhém cyklu je index i převeden na konstantu j, která je neměnná a nelze ji dále přepisovat jinými hodnotami. V tomto případě každé tlačítko vrátí svůj příslušný index. Tak jak se očekává.

 
Odpovedať
3.4.2019 20:59
Avatar
x.listo
Tvůrce
Avatar
Odpovedá na Martin Ko
x.listo:3.4.2019 21:01

Chyba může být kdekoliv, možná i jen v překlepu. Můžu ti pomoci jedině tak, že si svůj kód porovnáš s mým.

class Diar {

    constructor(jazyk = "cs-CZ") {
        const zaznamyZeStorage = localStorage.getItem("zaznamy");
        this.zaznamy = zaznamyZeStorage ? JSON.parse(zaznamyZeStorage) : [];
        this.jazyk = jazyk;
        this.dt = null;

        this.nazevInput = document.getElementById("nazev");
        this.datumInput = document.getElementById("datum");
        this.potvrditButton = document.getElementById("potvrdit");
        this.vypisElement = document.getElementById("seznam-ukolu");

        this._nastavUdalosti();
    }

    _nastavUdalosti() {
        this.potvrditButton.onclick = () => { // this zůstane nyní stále this
                        if (this.datumInput.value !== "") {
                                const zaznam = new Zaznam(this.nazevInput.value, this.datumInput.value);
                                this.zaznamy.push(zaznam);
                                this.ulozZaznamy();
                                this.vypisZaznamy();
                        } else
                                alert("Musíte vyplnit datum!");
            };
    }

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

    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>";
                            this.dt = document.createElement("div");
                            this.dt.innerHTML = `<h3>${datum}</h3>`;
                            this.dt.className = "datum";
                            this.vypisElement.appendChild(this.dt);

                    }
                    posledniDatum = zaznam.datum;

                    const ukol = document.createElement("div");
                    ukol.innerHTML = `<br><strong>${zaznam.nazev}</strong><br>kdy: ${zaznam.datum}<br>splněno: ${!zaznam.splneno ? "ne" : ""}splněn`;
                    ukol.className = "ukol";
                    this.dt.appendChild(ukol);

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

                    this._pridejTlacitko("Smazat", () => {
                            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();
                            }
                    });
                    this._pridejTlacitko("Označit jako " + (zaznam.splneno ? "nesplněný" : "splněný"), () => {
                            zaznam.splneno = !zaznam.splneno;
                            this.ulozZaznamy();
                            this.vypisZaznamy();
                    });
                    //this.vypisElement.innerHtml = `<div class="ukol">` + this.vypisElement.innerHtml  + `</div>`;
            }
    }

    _pridejTlacitko(titulek, callback) {
            const button = document.createElement("button");
            button.onclick = callback;
            button.innerText = titulek;
            this.vypisElement.appendChild(button);
    }

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

}
Editované 3.4.2019 21:02
 
Odpovedať
3.4.2019 21:01
Avatar
pavlicekr
Člen
Avatar
pavlicekr:5.4.2019 18:42

cau, chyba je v samotnem pridani obsahu pomocí innerHTML do elementu, který už má obsah s eventem. Takže když se použije takto: element.innerHTML += obsah; každou další iterací se bohužel přemaže původní event.

Jinak jsem rád, že tu někdo rozvíji dál JS :)

Editované 5.4.2019 18:43
 
Odpovedať
5.4.2019 18:42
Avatar
Patrik Pastor:14.4.2019 9:28

cau, napadlo me pridat jeste tlacitko pro vymazani celeho diar (v pripade, ze byste meli spoustu poloezek, nebo proste chteli smaznout historii), tak jsem v html vytvoril button element navazal ho v kontruktoru a do metody nastavUdalosti, pripsal tuto metodu:

this.vycistit­Button.onclick = () =>{
if (alert("Opravdu si prejete vycistit Diar?")){
localStorage.cle­ar();
this.ulozZaznamy();
this.vypisZaz­namy();
}
}

Ovsem po kliknuti nic. Alert vyskoci, ale po "ok" jsou zaznamy porad k nalezeni, nenapada nekoho proc to nefunguje? (na netu jsem hledat funkci localStorage.cle­ar() a nemela by mit zadny parametr, takze myslim ze tam chyba neni, potom me ale nenapada proc to nefunguje.

 
Odpovedať
14.4.2019 9:28
Avatar
Odpovedá na x.listo
Patrik Pastor:14.4.2019 9:46

zkusil jsem a lze to mazat z prostredka, nicmene to rozbilo tim DIVem cele css. Jde o to ze ted, pokud mas k jednomu datu vice zaznamu, pak tlacitka jednotlivych zaznamu jsou NAKONCI tohoto divu. Jinymi slovy tlacitka uz nejsou u kazde polozky jednotlive, ale nevzhledne rozhazeny v dusledku pridani divu. Jak jsi to teda vyresil s tlacitky, aby zustaly u kazde polozky?

 
Odpovedať
14.4.2019 9:46
Avatar
x.listo
Tvůrce
Avatar
Odpovedá na Patrik Pastor
x.listo:14.4.2019 14:03

Výborně.
To jsem přehlédl. Řešení může být přidání dalšího parametru do _pridejTlacitko, který bude reprezentovat konkrétní úkol.

_pridejTlacitko(titulek, callback, ukol) {
            const button = document.createElement("button");
            button.onclick = callback;
            button.innerText = titulek;
            ukol.appendChild(button);
    }

Potom už stačí jen doplnit požadovaný element jako parametr do obou volání.

this._pridejTlacitko("Smazat", () => {
                            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();
                            }
                    }, ukol);

this._pridejTlacitko("Označit jako " + (zaznam.splneno ? "nesplněný" : "splněný"), () => {
                            zaznam.splneno = !zaznam.splneno;
                            this.ulozZaznamy();
                            this.vypisZaznamy();
                    }, ukol);
 
Odpovedať
14.4.2019 14:03
Avatar
Odpovedá na x.listo
Patrik Pastor:14.4.2019 17:43

Diky, ted uz je vsechno vporadku (skoda ze sem na to sam neprisel, ale tak delam to poprve), proto jsem si chtel pridat prave tlacitko pro odstraneni celeho zaznamu (pri vytvareni jsem omylem naklikal jeden zaznam hodnekrat, a kdyz to konecne najelo, mel jsem tam ukoly uplne vsechny). Metoda pro tlacitko byla "localStorage­.clear()" - jak jsem na sel na stackoverflow, ale stejne mi nejede, nevis proc?

_nastavUdalosti(){
// => znaci zmenu klicoveho slova this na puvodni kontext (tedy "this" plati pro klasu "Diar")
this.potvrdit­Button.onclick = () => {
if (this.datumIn­put.value !== ''){
const zaznam = new Zaznam(this.na­zevInput.valu­e, this.datumInput­.value);
this.zaznamy.push(zaz­nam);
this.ulozZaznamy();
this.vypisZaz­namy();
} else {
alert('Musite vyplnit datum');
}
};
// TATO METODA MA VYCISTIT CELY DIAR

this.vycistit­Button.onclick = () =>{
if (alert("Opravdu si prejete vycistit Diar?")){
window.localSto­rage.clear();
this.ulozZaznamy();
this.vypisZaz­namy();
}
}
}

vycistitButton je navazane tacitko, ktere jsem v html napsal pod potvrdit:
<div>
<button id='potvrdit'>U­ložit úkol</button>
<button id='vycistit'>Vy­cistit diar</button>
</div>

 
Odpovedať
14.4.2019 17:43
Robíme čo je v našich silách, aby bola tunajšia diskusia čo najkvalitnejšia. Preto do nej tiež môžu prispievať len registrovaní členovia. Pre zapojenie sa do diskusie sa zaloguj. Ak ešte nemáš účet, zaregistruj sa, je to zadarmo.

Zatiaľ nikto nevložil komentár - buď prvý!