Project: todo app

In deze toepassing ontwerp je een todo app voor je smartphone.

Alle taken worden gebundeld in een array en bij elke wijziging lokaal bewaard. Hiervoor gebruiken we HTML5 local storage (is een onderdeel van Web Storage).

  1. Maak in de map LesCordova een nieuw project aan:
    $ cordova create todo be.uwnaam.todo Todo
    $ cd todo
    $ cordova platform add browser android

Wat is local storage?

Local storage is een onderdeel van Web storage.
Local storage bewaart een key/value combinatie op de client. De value is altijd een string. In de value kan je elk type data opslaan (een string, een getal, een array, een JSON-object, ...), zolang je het maar kan omzetten naar een string.
De belangrijkste functies zijn:

  1. Waarde opslaan: localStorage.setItem('key', 'value')
  2. Waarde ophalen: localStorage.getItem('key')
  3. Waarde wissen: localStorage.removeItem('key')
  4. Local storage volledig wissen: localStorage.clear()

Wil je, zoals in deze toepassing, een array van JSON-objecten bewaren en lezen, dan kan dit enkel met een string!

  1. Converteer een JSON-array naar een JSON-string:
    localStorage.setItem('key', JSON.stringify(object))
  2. And vice versa:
    object = JSON.parse(localStorage.getItem('key'))

Inhoud van de website

  1. Wis de volledige inhoud van de www-folder en vervang deze door de bestanden uit dit zip-bestand.
  2. Bestudeer de bestanden.
index.html

De lay-out van de pagina wordt verzorgd door materializecss. De interactie gebeurt met jQuery. Alle CSS- en JavaScript-bibliotheken zijn reeds op de pagina geïntegreerd.


      
  1. Bovenaan de pagina staat een fixed navbar.
  2. Gevolgd door een collection (een ul-tag) met één dummy taak (een li-tag).
    • Op het wis-icoon dat bij de taak hoort, is een extra class .deleteTask toegevoegd. Via deze class kunnen we straks de taak wissen.
    • Zowel het icoon als de tekst krijgen een data-attribuut data-task="0". Dit nummer gebruiken we later om het juiste element binnen de array te benaderen. data-task="0" verwijst naar het array-element _dotos[0].
    • Het attribuut contenteditable op de div-tag maakt dat we de tekst rechtstreeks (inline) kunnen aanpassen.
  3. Op het einde komt nog een fixed action button. Met het id #addTask kunnen we een nieuwe taak toevoegen.
js/app.js

Dit is het basisscript voor onze toepassing.

Zodra het device actief is onDeviceReady() wordt de todo-lijst geïnitialiseerd.

Daarna volgen de verschillende acties die we kunnen uitvoeren. De verschillende classes en id's verwijzen naar de elementen op de html-pagina. Voorlopig schrijven we enkel wat commentaar naar de console. De functionaliteit gaan we dadelijk toevoegen.

Merk op dat we de twee laatste events via on() uitvoeren!
Alle methodes zoals click(), blur(), .., met uitzondering van on() werken UITSLUITEND op een selector die bij het openen van de pagina aanwezig is!
Omdat we straks de li-tags dynamisch toevoegen, kunnen we $('.title').click(function(){}) niet gebruiken en zijn we genoodzaakt via on() te werken.
De code wordt dan: $('ul').on('click', '.title', function(){}). De selector is nu de ul-tag (deze bestaat wel tijdens het laden van de pagina) en het click-event wordt gedelegeerd naar de class .title.


      
js/todo.js

De publieke methodes van deze module zijn:

  1. init(): initialiseer de array _todos[] met alle taken die in local storage zijn opgeslagen.
  2. addTask(): voeg een nieuwe taak aan de array _todos[] toe en bewaar deze in local storage.
  3. deleteTask(id): verwijder de geselecteerde taak uit de array _todos[id] en bewaar de aangepaste lijst in local storage.
    id is de waarde van data-task="x".
  4. editTask = function(id, task): pas de tekst van de taak aan.
    id is de waarde van data-task="x".
    task is de tekst die erbij hoort.
    
            
  5. Start de applicatie in de browser.
    $ phonegap serve
  6. Open de app in Chrome (http://localhost:3000) en test de functionaliteit.
  7. Open de Chrome DevTools (F12) en klik op het console tabblad.
    Bij het opstarten van de app verschijnen er twee meldingen in de console. De eerste melding is afkomstig van app.js, de tweede van todo.js.
  8. Klik op de verschillende icoontjes op de pagina. Voorlopig wordt enkel een tekst in de console getoond. Dadelijk gaan we acties toevoegen.

Een taak aanpassen.

Een taak aanpassen doe je door op de tekst te klikken. Hiervoor hoef je verder geen code te schrijven. Het attribuut contenteditable zorgt ervoor dat de tekst aanpasbaar is.

Klik je buiten het tekstveld, dan activeer je het blur-event. Hier worden twee waardes opgehaald (id en task). Elke aanpassing verwijst naar het juiste element in de array _todos[]. Voorlopig bevat de array nog maar één element: _todos[0]. In de console zie je de aangepaste tekst.

  1. Pas de code op js/app.js aan:
    
    $('ul').on('blur', '.title', function(){
        console.log('taak is aangepast');
        let id = $(this).data('task');   // id = waarde x uit data-task="x"
        let task = $(this).html();       // task = de HTML-code in het teksveld
        ToDo.editTask(id, task);
    });
    				
  2. Pas de code op js/todo.js aan:
    
    let editTask = function(id, task){
        console.log(`taak bewerken: _dotos[${id}] = ${task}`);
        _todos[id] = task;
        _setLocalStorage();
    };
    				

Een taak toevoegen.

Zodra je op het toevoeg-icoon klikt, wordt aan het einde van de array een nieuwe taak toegevoegd. In de tekst verwerk je tevens de lengte van de array. De nieuwe taak verschijnt nog niet op het scherm, maar wel in de console.
Klik enkele malen op het toevoeg-icoon en controleer in de console hoe de array groeit.

  1. Pas de code op js/app.js aan:
    
    $('#addTask').click(function(){
        console.log('nieuwe taak toevoegen');
        ToDo.addTask();
    });
    				
  2. Pas de code op js/todo.js aan:
    
    let addTask = function(){
        console.log('nieuwe taak toevoegen');
        _todos.push(`Taak ${_todos.length}`);  // / Voeg achteraan (push) of vooraan (unshift) de array de tekst "Taak x" toe
        _setLocalStorage();
    };
    				

Een taak wissen.

Zodra je op het wis-icoon klikt, wordt het juiste element uit de array verwijderd. Omdat de taak nog hard-gecodeerd op de pagina staat, ga je bij elke klik steeds het eerste element wissen (data-task="0"). De taak verdwijnt nog niet van het scherm omdat we deze functionaliteit nog moeten toevoegen.
Klik enkele malen op het toevoeg-icoon en vervolgens enkel malen op het wis-icoon. Controleer in de console wat er gebeurt met de array.

  1. Pas de code op js/app.js aan:
    
    $('ul').on('click', '.deleteTask', function(){
        console.log('taak wissen');
        let id = $(this).data('task');   // id = waarde x uit data-task="x"
        ToDo.deleteTask(id);
    });
    				
  2. Pas de code op js/todo.js aan:
    
    let deleteTask = function(id){
        console.log(`taak wissen: id = ${id}`);
        if(confirm('Deze taak wissen?')) {
            _todos.splice(id, 1);   // Verwijder het x-de element uit de array
            _setLocalStorage();
        }
    };
    				

Taken bewaren in local storage.

De drie methodes editTask(), addTask() en deleteTask() verwijzen op het einde tlekens naar de methode _setLocalStorage(). Het is in deze methode dat we de array lokaal gaan bewaren. Merk op dat we de array eerst met JSON.stringify(_todos) converteren naar een JSON string en dan pas bewaren. Zonder deze voorafgaande bewerking kan je de gegevens niet correct verwerken!

De laatste actie verwijst naar _taskList(). Hier wordt dadelijk de takenlijst op het scherm opnieuw opgebouwd.

  1. Pas de code op js/todo.js aan:
    
    let _setLocalStorage = function() {
        console.log('bewaar alle taken in "todo"');
        console.log(_todos);
        localStorage.setItem('todo', JSON.stringify(_todos));  // localStorage.setItem('key', 'value')
        _taskList();
    }				

Klik enkele malen op het toevoeg-icoon en controleer in de console hoe de gegevens lokaal worden bewaard. Je kan de local storage uitlezen onder het tabblad Application.
Local Storage

Takenlijst opnieuw opbouwen.

De laatste regel van de methode _setLocalStorage()verwijst naar de methode _taskList(). Hier wordt de takenlijst opgebouwd.

Eerst gaan we alle reeds aanwezige li-tags wissen. Vervolgens gaan we vanuit een for-lus alle li-tags opnieuw opbouwen. De structuur is identiek aan de structuur van de dummy li-tag die nu hard gecodeerd op de pagina staat. De tekst en het data-task nummer worden dynamisch gegenereerd.

Controleer de werking van de applicatie. Je kan nu taken toevoegen, wijzigen en wissen. Elke aanpassing zal ook zichtbaar zijn in local storage.

  1. Pas de code op js/todo.js aan:
    
            

Takenlijst ophalen bij het starten van de app.

Bij het initialiseren (het opstarten) van de app, ga je de gegevens uit local storage ophalen en de takenlijst op het scherm tonen.

Maak de array _todos[] eerst leeg. Haal vervolgens de waarde van todo uit de local storage op. Controleer of de string niet leeg is en converteer de string vervolgens met JSON.parse() naar een array. Daarna bouw je de takenlijst terug op.

  1. Pas de code op js/todo.js aan:
    
    let init = function(){
        console.log('de todo app start op...');
        let todos_str = localStorage.getItem('todo');
        if (todos_str !== null) {
        	_todos = [];   // Maak array leeg
            _todos = JSON.parse(todos_str);
        }
        _taskList();
    }				

Installeer de todo app

  1. Installeer de todo app op je smartphone en controleer de werking.
    $ cordova run android