├── tutorial ├── assets │ ├── jstodo.gif │ ├── addTasks.gif │ ├── eventTarget.gif │ └── insertAdjacentHTML.png ├── 1-start-here.html ├── 3-js-output.html ├── 4-todo-app.html └── 2-js-input.html ├── final ├── js │ └── scripts.js ├── index.html └── css │ └── styles.css ├── LICENSE └── README.md /tutorial/assets/jstodo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdbootstrap/JS-tutorial-To-Do-List-App-for-beginners/HEAD/tutorial/assets/jstodo.gif -------------------------------------------------------------------------------- /tutorial/assets/addTasks.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdbootstrap/JS-tutorial-To-Do-List-App-for-beginners/HEAD/tutorial/assets/addTasks.gif -------------------------------------------------------------------------------- /tutorial/assets/eventTarget.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdbootstrap/JS-tutorial-To-Do-List-App-for-beginners/HEAD/tutorial/assets/eventTarget.gif -------------------------------------------------------------------------------- /tutorial/assets/insertAdjacentHTML.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdbootstrap/JS-tutorial-To-Do-List-App-for-beginners/HEAD/tutorial/assets/insertAdjacentHTML.png -------------------------------------------------------------------------------- /final/js/scripts.js: -------------------------------------------------------------------------------- 1 | function addTask() { 2 | let task = document.getElementById('task').value; 3 | 4 | if (!task) 5 | return; 6 | 7 | const text = "
  • " + task + "
  • " 8 | document.getElementById('list').insertAdjacentHTML('beforeend', text) 9 | document.getElementById('task').value = ''; 10 | } 11 | 12 | document.getElementById('add').addEventListener('click', addTask); 13 | document.getElementById('list').addEventListener('click', function(event){ 14 | const element = event.target; 15 | element.classList.toggle("done"); 16 | }); 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /final/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | The JS tutorial 7 | 8 | 9 | 10 | 11 | 12 | 13 |
    14 |
    15 | 16 | 17 |
    18 | 19 |
    20 | 22 |
    23 |
    24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 MDBootstrap 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /final/css/styles.css: -------------------------------------------------------------------------------- 1 | html{ 2 | height: 100%; 3 | background-image: linear-gradient(#20a9d3,#0d5c9c); 4 | background-repeat: no-repeat; 5 | font-family: sans-serif; 6 | color: #0f222d; 7 | background-size: auto; 8 | } 9 | 10 | .app{ 11 | width: 400px; 12 | display: flex; 13 | justify-content: center; 14 | flex-direction: column; 15 | margin: 50px auto; 16 | } 17 | form{ 18 | background-color: #fff; 19 | padding: 15px; 20 | } 21 | input[type="text"]{ 22 | width: 310px; 23 | height: 30px; 24 | outline: 0; 25 | border: none; 26 | font-size: 1.5em; 27 | background: #fff; 28 | color: #2f4f4f; 29 | } 30 | input[type="submit"]{ 31 | font-size: 1.5em; 32 | color: #53BDFF; 33 | background-color: #fff; 34 | outline: 0; 35 | border: none; 36 | width: 50px; 37 | 38 | } 39 | .todos{ 40 | background-color: #fff; 41 | margin-top: 20px; 42 | padding-top: 10px; 43 | padding-bottom: 10px; 44 | padding-right: 40px; 45 | 46 | } 47 | ul{ 48 | list-style: none; 49 | } 50 | li{ 51 | border-bottom: 1px solid #53BDFF; 52 | padding-bottom: 15px; 53 | padding-top: 15px; 54 | font-size: 1.3em; 55 | color: #ffffff; 56 | cursor: pointer; 57 | } 58 | 59 | .done { 60 | text-decoration: line-through; 61 | color: #104123; 62 | cursor: pointer; 63 | } 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JS-tutorial-To-Do-List-App-for-beginners 2 | This tutorial will teach you basics of JavaScript on the real app example 3 | 4 | ## What will you learn? 5 | You will learn basics of JS as well as interaction with HTML an CSS (using JS) 6 | 7 | ## What will I build? 8 | 9 | ![Preview](https://raw.githubusercontent.com/mdbootstrap/JS-tutorial-To-Do-List-App-for-beginners/master/tutorial/assets/jstodo.gif) 10 | 11 | ## How to start? 12 | ### 1. Preapre the environment 13 | 14 | #### 1.1 Text editor 15 | Download and install [Visual Studio Code](https://code.visualstudio.com/download) 16 | 17 | #### 1.2 Browser 18 | Download and install one of the following browser: 19 | 20 | * [Google Chrome](https://www.google.com/chrome/) 21 | * [Firefox](https://www.mozilla.org/en-US/firefox/new/) 22 | * [Opera](https://www.opera.com/download) 23 | 24 | #### 1.3 Lesson files 25 | Download lesson files from [here](https://github.com/mdbootstrap/JS-tutorial-To-Do-List-App-for-beginners/archive/master.zip) and unzip on your computer. 26 | 27 | You will see the following files structre: 28 | 29 | tutorial/ 30 | 1-start-here.html 31 | 2-js-input.html 32 | 3-css.html 33 | 3-js-output.html 34 | 4-todo-app.html 35 | final 36 | index.html 37 | css/ 38 | styles.css 39 | js/ 40 | scripts.js 41 | 42 | 43 | ### 2. Start learning 44 | Navigate to tutorial folder and follow lesson files in given order: 45 | 46 | 1-start-here.html 47 | 2-js-input.html 48 | 3-css.html 49 | 3-js-output.html 50 | 4-todo-app.html 51 | -------------------------------------------------------------------------------- /tutorial/1-start-here.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

    This tutorial will guide you thorough basics of JavaScript by building real TODO application.

    6 | 7 |

    How to start?

    8 | 9 | 10 | 11 |

    1. Preapre the environment

    12 | 13 |

    1.1. Text editor

    14 | 15 |

    Download and install Visual Studio Code

    16 | 17 |

    1.2 Browser

    18 | 19 |

    Download and install one of the following browser: 20 |

    25 |

    26 | 27 |

    1.3 Lesson files

    28 |

    Download lesson files from here and unzip on your computer.

    29 |

    You will see the following files

    30 | 31 |
    32 |         tutorial/ 
    33 |             1-start-here.html
    34 |             2-js-input.html
    35 |             3-js-output.html
    36 |             4-todo-app.html
    37 |         final
    38 |             index.html
    39 |             css/
    40 |                 styles.css
    41 |             js/
    42 |                 scripts.js
    43 |     
    44 | 45 | 46 |

    2. Start learning

    47 | 48 | 49 |

    Navigate to tutorial folder and follow lesson files in given order: 50 |

      51 |
    1. 1-start-here.html (current file)
    2. 52 |
    3. 2-js-input.html
    4. 53 |
    5. 3-js-output.html
    6. 54 |
    7. 4-todo-app.html
    8. 55 |
    56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /tutorial/3-js-output.html: -------------------------------------------------------------------------------- 1 | 7 |

    How to get data from JS into HTML

    8 | 9 |

    Since we already know how to pass data from our visitors to our JS functions, let's learn how we can use JS to modify data on our page.

    10 | 11 | 12 |

    innerText

    13 | 14 | 15 |

    In the previous lesson we have learn how to get data from different HTML tags using innerHTML, now we will learn how to use the same function to set it.

    16 | 17 |

    Add some div:

    18 | 19 |
    
     20 |     <form onsubmit="addTask();return false" action="#">
            <label for="task">Task:</label>
            <input type="text" name="task" id="task">
            <input type="submit" id="add" value="Add">
        </form>
    
        <div id="todos">List of todos...</div>
     21 | 
    22 | 23 |

    And update our addTask function:

    24 | 25 | 26 |
    
     27 |     function addTask() {
     28 |         var task = document.getElementById('task').value;
     29 |     
     30 |         document.getElementById('todos').innerText = task;
     31 |     }
     32 | 
    33 | 34 |

    As you can see we can assign value/parameter to different html tags using simple assignment.

    35 | 36 |

    innerHTML

    37 | 38 |

    Similarly, we can also create and assign entire HTML structure:

    39 | 40 |
    
     41 |     document.getElementById('todos').innerHTML = "<ol><li>" + task + "</li></ol>
    
     42 | 
    43 | 44 | 45 |

    Do I have to always replace entire content?

    46 | 47 |

    No!

    48 | 49 |

    You probably noticed that currently we are replacing entire inner html of div. This means, that every time we add new task, the old one get erased.

    50 | 51 |

    In order to append new HTML to existing one we will use another JS function - insertAdjacentHTML()

    52 | 53 |

    The insertAdjacentHTML() method inserts a text as HTML, into a specified position.

    54 | 55 |

    Legal position values are:

    56 | 57 | 63 | 64 | 65 | 66 |

    Let's use unordered list (ul) inside our div:

    67 | 68 |
    
     69 |     <div id="todos">
            <ul id="list">
            </ul> 
        </div>
     70 | 
    71 | 72 |

    and add new tasks as a new line items (li):

    73 | 74 |
    
     75 |     document.getElementById('list').insertAdjacentHTML('beforeend', "<li>" + task + "</li>")
    
     76 | 
    77 | 78 | 79 | 80 |

    Not only the content

    81 | 82 |

    Now we know how to use JavaScript to manipulate content, but actually we can adjust almost any element of our webpage and it's properties.

    83 | 84 |

    We can adjust classes by adding them:

    85 | 86 |
    
     87 |     let element = document.getElementById("myDIV");
     88 |     element.classList.add("new-class");
     89 | 
    90 | 91 |

    removing:

    92 | 93 |
    
     94 |     var element = document.getElementById("myDIV");
     95 |     element.classList.remove("new-class");
     96 | 
    97 | 98 |

    or toggle (add if not present or remove if present)

    99 | 100 |
    
    101 |     var element = document.getElementById("myDIV");
    102 |     element.classList.toggle("new-class");  
    103 | 
    104 | 105 |

    Other options

    106 | 107 |

    As I said before - options are almost limitless. Using JS we can i.e. 108 |

    116 |

    117 | 118 |

    Let's create some app

    119 | 120 |

    Now when we know how to transfer data between HTML and JS and apply CSS on the fly, it's high time to build some real app!

    121 | 122 |

    Let's start!

    123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /tutorial/4-todo-app.html: -------------------------------------------------------------------------------- 1 | 7 |

    Todo App

    8 | 9 |

    Plan

    10 | 11 | 12 |

    In order to create our app we will need to execute following steps: 13 | 14 |

      15 |
    1. Cleanup code
    2. 16 |
    3. Add styles
    4. 17 |
    5. Add functionality to mark task as completed
    6. 18 |
    19 | 20 | 21 | 22 |

    23 | 24 |

    Cleanup:

    25 | 26 |

    In order to create our app we will: 27 | 28 |

      29 |
    1. wrap it with surrounding div
    2. 30 |
    3. replace <label> tag with placeholder="" attribute in input
    4. 31 |
    5. Clean JS code
    6. 32 |
    33 |

    34 | 35 |

    Update index.html code:

    36 | 37 |
    
     38 |     <div class="app">
            <form onsubmit="return false" action="#">
                <input type="text" name="task" id="task" placeholder="Add new task...">
                <input type="submit" id="add" value="Add">
            </form>
        
            <div id="todos">
              <ul id="list">
              </ul> 
            </div>
        </div>
     39 | 
    40 | 41 | 42 |

    Now let's do some small cleanup in JS, instead of concatenating our new list item inside the function:

    43 | 44 |
    
     45 |     document.getElementById('list').insertAdjacentHTML('beforeend', "<li class='task'>" + task + "</li>")
    
     46 | 
    47 | 48 |

    let's make it more readable and split it in 2 steps:

    49 | 50 |
    
     51 |     const text = "<li class='task'>" + task + "</li>"
        document.getElementById('list').insertAdjacentHTML('beforeend', text)
     52 | 
    53 | 54 |

    We want to make sure that we won't add tasks with empty name:

    55 | 56 | 57 |
    
     58 |     if (!task)
     59 |     return;
     60 | 
    61 | 62 |

    This condition, checks whether task, isn't an empty value. In case it is, it will return 0, therefore we are adding ! sign in front which revert logic: 63 | 64 |

    68 | 69 | So if someone tries to add empty task, our condition will be triggered and function will stop execution here. 70 |

    71 | 72 |

    Finally, once we add new item to the list, we want to clear our input area:

    73 | 74 |
    
     75 |     document.getElementById('task').value = '';
     76 | 
    77 | 78 |

    The final scripts.js code after cleanup:

    79 | 80 |
    
     81 |     function addTask() {
            let task = document.getElementById('task').value;
        
            if (!task)
            return;
        
            const text = "<li class='task'>" + task + "</li>"
            document.getElementById('list').insertAdjacentHTML('beforeend', text)
            document.getElementById('task').value = '';
        }
        
        document.getElementById('add').addEventListener('click', addTask);
     82 | 
    83 | 84 | 85 |

    Add styles:

    86 | 87 |
    
     88 |     html{
     89 |         height: 100%;
     90 |         background-image: linear-gradient(#20a9d3,#0d5c9c);
     91 |         background-repeat: no-repeat;
     92 |         font-family: sans-serif;
     93 |         color: #0f222d;
     94 |         background-size: auto;
     95 |       }
     96 |       
     97 |       .app{
     98 |         width: 400px;
     99 |         display: flex;
    100 |         justify-content: center;
    101 |         flex-direction: column;
    102 |         margin: auto;
    103 |       }
    104 |       h1{
    105 |         text-align: center;
    106 |         color: #fff;
    107 |       }
    108 |       form{
    109 |         background-color: #fff;
    110 |         padding: 15px;
    111 |       }
    112 |       input[type="text"]{
    113 |         width: 310px;
    114 |         height: 30px;
    115 |         outline: 0;
    116 |         border: none;
    117 |         font-size: 1.5em;
    118 |         background: #fff;
    119 |         color: #2f4f4f;
    120 |       }
    121 |       input[type="submit"]{
    122 |         font-size: 1.5em;
    123 |         color: #53BDFF;
    124 |         background-color: #fff;
    125 |         outline: 0;
    126 |         border: none;
    127 |         width: 50px;
    128 |       
    129 |       }
    130 |       .todos{
    131 |         background-color: #fff;
    132 |         margin-top: 20px;
    133 |         padding-top: 10px;
    134 |         padding-bottom: 10px;
    135 |         padding-right: 40px;
    136 |       
    137 |       }
    138 |       ul{
    139 |         list-style: none;
    140 |       }
    141 |       li{
    142 |         border-bottom: 1px solid #53BDFF;
    143 |         padding-bottom: 15px;
    144 |         padding-top: 15px;
    145 |         font-size: 1.3em;
    146 |         color: #ffffff;
    147 |         cursor: pointer;
    148 |       }
    149 |     
    150 |       .done {
    151 |         text-decoration: line-through; 
    152 |         color: #104123;
    153 |         cursor: pointer;
    154 |       }
    155 |      
    156 | 
    157 | 158 |

    Add option to mark task as done

    159 | 160 |

    Now we have to mark our tasks as done. In order to do that we will add or remove class done to the item when someone clicks on it.

    161 | 162 |

    Add new listener:

    163 | 164 |
    
    165 |     document.getElementById('list').addEventListener('click', function(event){
    166 |         const element = event.target;
    167 |         console.log(element);
    168 |     });
    169 | 
    170 | 171 |

    Now we can check console to verify if we are catching correct element.

    172 | 173 | 174 |

    As you can notice - we are passing a click event to our function, and assigning it's target (so element which was clicked) to constant variable called element

    175 | 176 | 177 |

    Since we have our element assign, the last thing we have to do is to toggle done class:

    178 | 179 | 180 |
    
    181 |     document.getElementById('list').addEventListener('click', function(event){
    182 |         const element = event.target;
    183 |         element.classList.toggle("done");
    184 |     });
    185 | 
    186 | 187 |

    Voila! Our code is ready.

    188 | 189 | 190 |

    There are few more enhancements which we could provide to our app like: 191 | 192 |

    196 |

    197 | 198 |

    Try to write this functionality yourself and if you want to see final solution, don't miss next tutorial!

    199 | -------------------------------------------------------------------------------- /tutorial/2-js-input.html: -------------------------------------------------------------------------------- 1 | 7 |

    How to get data from HTML into JS

    8 | 9 |

    In order to build website we use HTML, CSS and JS. As you already know: 10 | 11 |

    16 |

    17 | 18 |

    Let's learn how can we make communication between HTML and JS happen in both directions.

    19 | 20 |

    HTML > JS

    21 | 22 | 23 |

    JavaScript has multiple options to get values from HTML.

    24 | 25 |

    Let's create a paragraph with id

    26 | 27 |

    Paragraph 1

    28 | 29 |

    and try to access this using GetElementById function in JS:

    30 | 31 |
    
     32 |     let p = document.getElementById('p1');
     33 |     console.log(p);
     34 | 
    35 | 36 |

    When you check in console, you will note that we received entire tag. But what if we are interested only in what inside the paragraph?

    37 | 38 |

    Instead of printing out p, we will print it's innerText

    39 | 40 |
    console.log(p.innerText);
    41 | 42 |

    In case of nested structure:

    43 | 44 |
    
     45 |     <div id="d1">
            <p id="p1">Paragraph 1</p>
        </div>
     46 | 
    47 | 48 |

    we can get not only text but entire internal HTML:

    49 | 50 |
    
     51 |     let d = document.getElementById('d1');
     52 |     console.log(d.innerText);
     53 |     console.log(d.innerHTML);
     54 | 
    55 | 56 |

    We can also get values of it's atributes:

    57 | 58 |
    <div id="d1" class="a b c "></div>
    59 | 60 |
    console.log(d.className);
    61 | 62 |

    and many more like: 63 | 64 |

    70 | 71 |

    72 | 73 | 74 |

    Other access methods

    75 | 76 |

    Using ID is convenient when our element's have them. However we have to remember that id must be unique (2 elements can't have same id). This means that we can use them only for elements on the website which are unique.

    77 | 78 |

    Sometimes we have elements which don't have id, what to do then?

    79 | 80 |

    We can access them by tag

    81 | 82 |
    
     83 |     const x = document. getElementsByTagName("p");
     84 |     for (let e of x) { e.style.color = "green"; }
     85 | 
    86 | 87 | 88 |

    Note! When you use tag selector, you will get access to all paragraphs on the page!

    89 | 90 |

    Above code will get access to all paragraphs on the page, and change its' color to green.

    91 | 92 |

    You can also access elements by class name:

    93 | 94 |
    
     95 |     const x = document. getElementsByClassName("js");
     96 | 
    97 | 98 | 99 |

    Inputs

    100 | 101 |

    Now you know how to literally access any element on the page. However, users browsing your website are not allowed to change elements like paragraphs.

    102 | 103 |

    In order let your visitors interact with your page, we will use inputs. Inputs are used to build forms.

    104 | 105 |

    Let's imagine that we want to build a simple TODO app. We will start with basic input in the index.html file:

    106 | 107 |
     <input type="text">
    108 | 109 | 110 |

    Since it ain't self explenatory, let's add some label to it:

    111 | 112 |
    
    113 |     <label for="task">Task:</label>
        <input type="text" name="task" id="task">
        <input type="submit" id="add" value="Add">
    114 | 
    115 | 116 |

    As you noticed we added few things:

    117 | 122 | 123 |

    Keep in mind that HTML allows you to build very advanced and powerfull forms containing on or more following elements 124 |

    135 |

    136 | 137 |

    Check more examples of inputs and forms

    138 | 139 |

    Now when our minimalists form is ready, we have do last thing. Read data from our input when user click submit button/

    140 | 141 | 142 |

    Submitting inputs

    143 | 144 |

    As always in programming, there are multiple way to achieve same result.

    145 | 146 |

    onClick()

    147 | 148 |

    On of the easiest option is to use onClick event to our submit input:

    149 | 150 |
    
    151 |     <input type="submit" id="add" value="Add" onclick="addTask()">
    
    152 | 
    153 | 154 |

    which will addTask() function:

    155 | 156 |
    
    157 |     function addTask() {
    158 |         let task = document.getElementById('task').value;
    159 |         console.log(task)
    160 |     }    
    161 | 
    162 | 163 | 164 |

    onSubmit

    165 | 166 |

    Imagine that instead of simple input, we have entire form to create. I.e. tax form where we have provide 20 or 40 different answers - or - even better (worse?), that we are about to create multi step wizard with multiple subforms. I.e. regitration, order, invoice details.

    167 |

    In order to organize our inputs, HTML offers a

    <form></form>
    tag which works like a wrapper to all our inputs and allows us to submit them all at once.

    168 | 169 |

    Wrap our input with form:

    170 | 171 |
    
    172 |     <form onsubmit="addTask();return false" action="#">
            <label for="task">Task:</label>
            <input type="text" name="task" id="task">
            <input type="submit" id="add" value="Add">
        </form>
    173 | 
    174 | 175 |

    Note: We added return false to onsubmit="" in order to prevent website from reload. We will cover that in future lesson about forms.

    176 | 177 |

    Note:Although you can use inputs outside form tag - code will be still valid, if your intention is to submit data in any way, you should be using a form.

    178 | 179 |

    Why do we put

    <input>
    elements inside of
    <form></form>
    elements? For the same reason we put <li> tags inside of <ul> and <ol> elements - it's where they belong. It's semantically correct, and helps to define the markup. Parsers, screen readers, and various software can better understand your markup when it is semantically correct - when the markup has meaning, not just structure.

    180 | 181 | 182 |

    Using listener

    183 | 184 |

    Instead of explicitly specify which function to call in on HTML side, JavaScript allows us to define listeners. Event listeners can react on different events i.e.: 185 | 186 |

    195 | 196 |

    Example

    197 | 198 | 199 |
    
    200 |     document.getElementById('add').addEventListener('click', addTask);
    201 | 
    202 | 203 |

    Remember to remove call to addTask() function from onsubmit, but keep in mind to leave return false

    204 | 205 |
    
    206 |     <form onsubmit="return false" action="#">
    
    207 | 
    208 | 209 | 210 | 211 |

    As you already noticed, addEventListener accepts 2 arguments (actually - 3, but we will skip third for the moment since it's optional) 212 |

    216 |

    217 | 218 |

    Since we know how to pass data from HTML to JS, let's move to the next lesson and learn how to we can do it in opposite direction.

    219 | 220 | 221 | 222 | 223 | --------------------------------------------------------------------------------