---
tags: mstu5003, tinker, js
---
# TINKER - Javascript Part II
<!--
- See repository: https://github.com/jmk2142/TodoMSTU5003
-->
- See demonstration: https://codepen.io/jmk2142/pen/oGxwPQ
- Tinker Markdown: https://hackmd.io/zJmA8GKJR5-Oe2Zy4r1wqw?both
* Group Members: Yi Chen Manru Li Linmiao Feng Haeram Jang
<!--
For this week, the actual Markdown file is not available via Github Gists. I have included it within this week's Tinker repository along with the rest of the code. It is called `README.md`. You might want to `IMPORT` the markdown into hackmd.io to use that tool (recommended.)
To get access to this code, and the actual Markdown to play with, you can use Github to CLONE the repository using the Github GUI Client. You can get the idea of what repositories are in my Youtube Video:
## Github: How to clone my repository
You'll want to start with the video overview:
https://youtu.be/QOXhN90d9Mk?list=PLn93-yl6k7zUkSFNI8MQqmIVn017z8vKO
Since you want to copy MY repository, once you have the Github GUI Client installed - you can do so with one click of a button. Just click on the Clone or download option, then **Open in Desktop** and that will automatically open it up in the Git GUI. (See Below)

Keep in mind that since you are cloning my repository, you will only be able to commit changes to your local computer. You will not be able to _sync_ or _push_ changes to my Github repository - for obvious security reasons. (You wouldn't want just anyone to change YOUR code.)
If you would like to use Github for your work in progress, what you can do is **_FORK_** my repository first. (See _FORK_ button under account picture.) This will create a copy of this repository under your account name in Github. You can clone YOUR version of this to your local computer, then commit and push to your account to your heart's content. :smiley_cat:
---
-->
## Devtools
You will also want to watch this video on the `console` as we will be using it extensively to Tinker this week.
General Video on Console: https://youtu.be/GAqOggzH_GE?list=PLn93-yl6k7zUkSFNI8MQqmIVn017z8vKO
One of the most important tools we'll use is the `DEBUGGER`.
:::success
**Debugger Demonstration and Youtube Video**
<!--
REPO: https://github.com/jmk2142/Debugger
DEMO: https://jmk2142.github.io/Debugger
-->
CODE: https://codepen.io/jmk2142/pen/RwZErre
DEMO: https://cdpn.io/jmk2142/debug/RwZErre
YOUTUBE: https://youtu.be/RdF7j4no0Ts
:::
I recommend that at some point, you watch these demonstrations and use these tools to explore the Tinker.
:::info
In order to use `console.dir(object)` and see the object property/values, make sure your console setting is set to DEFAULT.

:::
## Tinker GIST: TODOS
> Good bye, "Hello World!"
`Hello World` is probably the most common introductory program around as it's so simple.
```javascript=
alert("Hello World!");
// Or alternatively...
console.log("Hello World!");
```
Unfortunately, it's not very useful. It doesn't really show the range of different programming concepts and to be quite frank, it's boring. Many beginners like us are interested in creating interactive applications and this requires a range of programming concepts.
1. HTML Elements
2. CSS
3. Variables
4. Operators
5. Functions
6. Control Statements
7. Events
8. Data Structures + Data (e.g. Arrays, Objects, Booleans, Numbers, Strings)
And you really cant get a sense of how these things work together with a 1 line program like `Hello World!`.
### Enter TODOS
Some clever programmer realized this and probably thought:
> What's the simplest, _real_ program I can build that will incorporate all the important aspects of a basic interactive program?
And the **TODOS** or **TODO LIST** program was born.
The beauty of TODOS is that it has everything in a pretty simple package. It can be solved using a variety of different strategies and can be created to be _simpler_ or _more sophsiticated_ depending on ones needs. It tends to now be the defacto standard for demonstrating a full interactive application.
Beginners AND advanced students alike build TODO apps as they learn new things. For example, our TODOS Tinker is designed to demonstrate the base JS concepts with a few _stretch_ challenges embedded in it. In my regular practice, when I have to learn a new library or framework, I will probably start by viewing an existing TODO app built with that specific library to see how that library works. Sort of like how you might compare a basic HTML page with a Bootstrap page (of the same content) to be able to compare and contrast the two. If you're interested, you can briefly look at [this page](http://todomvc.com/) which is an archive of the TODO application built in various different frameworks.
And this is where I am hoping to take this class, the culmination of all the things we've been working towards - to understanding this first, real, interactive program and hopefully - you can apply some of these concepts in your own works.
## Tinker Tasks
In this tinker, were going to:
1. Review prior concepts in this new context:
- Variables, functions, events, and arrays
2. Observe, analyze, and study new concepts:
- Control statements (E.g. `if`, `for`)
- Logical operators (E.g. `===`,`&&`, `||`,`<`,`<=`,`>`,`>=`, etc.)
- Objects (and `array` of `objects`)
3. Learn how to use more developer tools to study JS code
- Source (i.e. debugger)
- Console (i.e. `console.log`, `console.dir`)
We will continue to observe, analyze and think about this program in terms of:
> What is the STATE?
> What is the SEQUENCE?
> What is the CAUSALITY?
### Part 0: Conceptual Program Overview
Play with the program and observe how it reacts to user interactions.
- _Without_ talking about it in _programming terms_ explain the user observable steps/process of the following three interactions and how the program responds.
- Adding a todo
>We can add a to-do item by typing it in the text area and then clicking the Add button or pressing the Enter key on the keyboard.
- Completing a todo
>We can click the circle and it will be marked as done. The number in front of the Remove button will be increased by 1.
- Removing a todo(s)
>We can click remove button and completed todo(s) will disappear. Then, the number of the remove button will disapper and the remove button will be disable.
Be specific but imagine you are talking to a _non-programmer_. Think about this in terms of observable actions and reactions.
> User puts toast in the toaster. Sets the length of the timer. Pushes the lever to start the toaster. The toast pops out the toaster after the time is completed and goes "DING".
- For each of the interactions above write in _pseudocode_ the steps of how the program for that interaction unfold and results. Pseudocode is semi-formal structure to write out the gist of how your program would work. It uses some keywords but is largely language agnostic. There isn't a single correct way to do it but the following are some rules that can help.
- RULES:
- One statement per line
- CAPITALIZE initial _keywords_
- READ, WRITE, IF, ELSE, REPEAT, UNTIL, AND, OR
- Indent to show hierarchy and groups of operation
- Keep statements language independent
```markdown=
# Making toast for a big family
READ loaf of bread
READ slice of loaf
Put slice in toaster
WRITE time to toast
Start the toaster
Cook the toast
READ time
WRITE time by one second less
REPEAT UNTIL time is zero
Remove toast
REPEAT for all slices in loaf
# Serving toast
WRITE number of slices total
READ number of family members
READ toastiness
IF toast is burnt AND (total slices >= number of family members)
throw away toast
decrement slices total
ELSE
serve toast to family member
```
- Using your pseudocode, identify the function(s) in the actual JS code that relate to your pseudocode.
- Compare and contrast your pseudocode with the actual code.
>Here is my pseudocode.
```
# Add a to-do list
Enter a to-do list in the text area
Click the add button
Write a new to-do list
# Delete all completed to-do items
Click the remove button
Completed to-do items disappea
then
Remove button disabled
The number of remove disappears
# mark completed to-do items
Select a to-do list item
Clcik the circle
This item will be marked as completed
If there is no completed to-do item before we click the circl
Remove button works
The number 1 appears before the remove button
else
The number in front of the Remove button is increased by 1.
```
- Explain what similarities and differences you noticed about the instructions / steps / processes in the code vs. your psuedocode.
>* similatieties:
* the rationale
* the results
* they present the same results.
>* differences:
* the steps
* js has to define functions before we call them.
* psuedocode does not require us to define functions.
* the processes
>* js has to read the data first.
- Manipulate different parts of the code as you see fit. Why did you decide to manipulate that part? What happened? (More structured tinkering to follow.)
>We want our pseudocode to have similar rationle like the real codes, epseically the functions.
### Part 1: Variables, Functions, Arrays, and Events
- Explain the `data` variable.
- What does this data (and the data inside) represent conceptually?
>This data represents the existing to-do list.
- If I wanted to access the second object, how would I do that in code?
>data.[1]
- If I wanted to access the `done` property of the first object, how would I do that?
>data.[0].done
- Look through the rest of the code where this `data` array is used. When the user does things, am I manipulating the visual display and updating the data to reflect those changes? Or am I manipulating the data and updating the visual display to reflect those changes?
- Is this what you would have thought of?
>Yes. We agree that we are manipulating the data and updating the visual display to reflect these changes.
- What might be the significance of this program design decision?
>When we refresh our code, we always have these to-do items. It can prompt users to try this to-do list. Also, it will create different IDsd for different to-do items. It can help other functions to refer to these to-do items.
- What do these lines in my code do?
```javascript=
var todosEl = document.querySelector('#todos');
var inputEl = document.querySelector('input');
var completedEl = document.querySelector('#counter');
```
>The first line declares the variable `todosEl`and assigns it the DOM value of the element with the id `#todos`.
inputEl: it assigns the value of the `input` element with id `#input`.
completedEl: it assigns the value of the `completed` element with id `#counter` to completedEl,
- Why declare these (see above) variables at the Global scope instead of in the functions?
- Or not at all... (E.g. `document.querySelector('#todos');`)
>We can use these variables into multiple functions.It will help people easily understand these varibales and their meanings.
- The `toggleComplete` function has an event parameter. Inside the function I access `event.currentTarget`. What is the difference between `event.currentTarget` and `event.target` which we used previously?
- Hint 1: You can add a `console.log(event)` etc. inside that function to test the value of `event.target` and `event.currentTarget`.
- Hint 2: When testing, click on a todo to "complete" it. Click on two areas: the `li` as well as the `i` (font icon) element to see the differences.
- Hint 3: You can pass multiple arguments to `console.log()`. I often pass two: first a string label, second the thing I want to log. This will basically make the logs easier to identify if you use `console.log()` a lot.
```javascript=
console.log("SOME LABEL: ", dataToLog);
```
>Console.log(event.target) means a to-do list that has not been completed.When we mark a to-do list completed, it will trigger console.log(event.currentTarget). Also, it will have a id to refer a specific to-do list.It will update the list of to-do.
- In the `toggleComplete` function, there is a `event.currentTarget.id`. Is that `id` the same thing as the id property in my todo objects in the `data` array?
- Explain.
>It is different. They use the string of task plus the id property in my todo objects in the `data` array to replace this id for current target. It represents uncompleted to-do items.
```
var todoID = parseInt(event.currentTarget.id.replace('task-',''));
```
- What does `!something` mean? (The exclamation mark) and how is it used in this code when we `toggleComplete`?
>`!something` means not equal to something. It will check whether the current completed to-do list data is equal to previous completed to-do list data. If it is not equal, it means we make a previously incomplete to-do into a completed state.
- Try calling some of the functions directly from the console. Some will work. Some won't.
>It will show how we define the js code for this function.
- Look at the function declarations in the JS panel.
- _Where_ is each function being called?
>The end of the js part
- Look at the function declarations in the JS panel.
- _Where_ is each function being called?
>After we define each function, we will have the function name() to call each function.
- _When_ is each function, actually called?
>When we navigate the to-do list, each function is actually called.
- What parameter(s) does that function have?
>The names listed in the function definition, such as event,id,empty values.
- What is the argument that is passed into the function when it is called?
>It's what's in the brackets.
- Use the console (in Chrome devtools) to `console.log()` and `console.dir()` the following. What is the difference between `console.log` and `console.dir` and why is `console.dir` kind of more useful for looking at some kinds of data?
javascript=
console.log(data);
console.log(todosEl);
console.dir(data);
console.dir(todosEl);
>console.log(data);
(4) [{…}, {…}, {…}, {…}]
We get the value of the data object.
```console.log(todosEl);```
We get the list of to-dos.
```console.dir(data);```
We get all properties of the data.
```console.dir(todosEl);```
We get all properties of `todosEl`.
</span>
### Part 2: Objects and Arrays of Objects
- Manipulate the different _properties_ of the _objects_ inside the `data` array.
- Change all todo objects' `done` property to `true`.
- Change some of the task values.
- Run your code and explain how this changes what you see and why.
>After we change all of the `done` property to true, there is strikethrough for all items on the todo list. The text of the task changes when we change the `task` value as well. These changes occur because we changed the original data, which is reflected through the visual change.
- `console.dir()` the `data` array. Goto the console and _OPEN_ the `> Array(3)` text by clicking on it. Go deeper by opening up the nested objects. Analyze what you see. Then add a new todo through the user interface. `console.dir()` the `data` array again and investigate the insides.
- What is the difference between `data` before and after adding a new todo?
> A new object is added to the orginal array, with its corresponding `id`, `task`, and `done` properties in the data array.
- Run the following code:
```javascript=
data.push({
done: true,
task: "Goto Aikido Lessons",
id: getTimeStamp()
});
console.dir(data);
```
- What did the code above do?
>It added a task directly into the data array.
- Does our page reflect the changes made? Why or why not? Prove it.
>These changes are initially shown only in the code, but when we click on an item in the to-do list, the function associated with the data variable is triggered and the data array is updated.
- Does order matter in `Objects`?
>Yes.
- What is the difference between `Object` keys (E.g. `done`, `task`, `id`) and `Array` indices (E.g. `0`, `1`, `2`)?
>Array indices: refer to data stored using subscripts.
Object key: refer to data stored using property.
- How are they similar?
>They are both used to extract data in objects.
```javascript=
var myAry = [123, "Code", true];
var myObj = {
id: 123,
task: "Code",
done: true
}
console.log(myAry[1]);
console.log(myObj["task"]);
console.log(myObj.task);
```
- Compare the following in the console:
```javascript=
var element = document.querySelector('ul');
var author = { first: "Mark", last: "Twain" }
var example = {
theAnswer: 42,
student: true,
hobby: "Fishing",
sayHello: function(){
alert("Hello");
},
favNums: [1,2,3],
favAuthor: author
};
console.dir(example);
console.dir(element);
```
- What is an `element` really?
>In this code, an element is a variable defined by selecting the values in the unordered list in HTML.
- How does our `element` relate in terms of similarities and differences to `example`?
>Both elements come from innerHTML. `‘Input’` and `‘ul’` are tags, and `#todos` and `#counter` are `id`from innerHTML.
- If I wanted to call the function in the `example` object, how would I do that? Prove it.
>The code is: `console.dir(example.sayHello)`;
- Try the following code in the console. How does dot notation and bracket notation differ and why would you want to use one or the other?
```javascript=
var x = "username";
var user = {
username: "happyCat"
}
console.log(user.username);
console.log(user["username"]);
console.log(user[x]);
console.log(user.x);
```
>Bracket notation is more expressive than dot notation as it converts all property name into strings to retrieve corresponding property.
- Identify various areas where the `.` object notation is used and explain the thing on the left side of the `.` and the thing on the right side of the `.`
- E.g. `document.querySelector()` `document` is... `querySelector` is...
- HINT: There are MANY choices here.
>`if (todo.done) {` the code on the left side of the `.` is `todo`, which is a defined variable, while the thing on the right side of `.` is `done`, which is the property specified in the `data` array.
- In two areas of my code, I use what is called a `filter` function. It's a function that arrays can use like `list.pop()`, `list.push()`.
- How does a filter function work?
>The `Filter` will create a new array with all of the elements that match the conditions and pass the test set in the function.
- What is the significance of the function argument that is passed INTO the filter parameters?
>The filter creates an array filled with all array elements that pass a test that is determined in the function.
- With regard to the function that is passed into the filter as an argument, that function must `return` a boolean or evaluate to a boolean. What is the purpose of this?
>Because the filter function takes out only the elements that match the conditions and uses them when creating a new array.
- What does the _filter function_ return?
E.g. `var x = list.filter(...); // What was returned to x?`
- CAUTION: NOT the function argument that goes into the filter.
- HINT: If you don't know, can you use console to "test" an idea out?
>It returns a new array based on the `filter` function that selects elements that are true.
- Does filtering an array _change_ the original array?
>No,it will not affect the original array.
### Part 3 Control Structures
- I use the `if` statement in several places in this code. Explain why a conditional is necessary in:
- `updateTodoItems`
>To set the condition to execute`onclick="toggleComplete(event)`. If 'todo' is 'done' is true, the code in `{}` works, but if it's false, it doesn't.
- `updateRemoveButton`
>`updateRemoveButton`should be executed under the condition of 'completedTodos'.
- `onEnterKey`
>Under the condition that the user press 'Enter' key, the events codes are done.
- `validateTask`
>Only when two operants are not equal, returning a Bulean result.
- `addTodoItem`
>In the condition of `inputEl` got value of !validateTask, the code is executed.
- `getTodoData`
>In this code, the program gets a number of data. Only in the condition of `(data[i].id === id)`.
- HINT: You might want to `console.log` the boolean condition where you see the `if` statements to understand what condition we are evaluating.
```javascript=
if (booleanCondition) {
...
}
console.log(booleanCondition);
```
- Comment on how the boolean condition works as there are many different examples.
- In this code, there are two kinds of `for` loops. The more traditional that looks like:
```javascript=
for (var i=0; i < list.length; i++) {
// CODE
}
```
and a `for of` loop that looks like:
```javascript=
for (item of list) {
// CODE
}
```
- How does a `for of` loop work?
- What does the `item` represent? (It can be named anything: `x`, `item`, `thing` etc.)
>`todo`
- Why are `for of` loops convenient compared to the traditional `for`?
>The 'for' statement iterates over the enumerable string properties of an object, while the 'for of' statement iterates over values that the iterable object defines to be iterated over.
- For what purpose(s) do I employ a `for` or `for of` loop in this program?
>`for`: If the condition is false, the for loop is terminated, and if the condition is true, the block of code inside the for loop is executed.
`for of`: is for iterable objects which are in this program, todo lists.
- On Facebook or Pinterest, or Twitter, how does a loop through data relate to the display of content?
>Loop helps us to display all elements of an array by using index.
### Part 3 Specific Routines
- Take a look at the `updateTodoItems`. Comment it out and replace it with this alternate, but functionally identical version. How does this function work and how do they relate / differ?
>If the codes are replaced with the codes below, the new lists are added without bullets. Also, when we add new lists in the textbox of the origianl version of the program, the list added disappears in the textbox. However, in the replaced version, the list added still remains in the textbox.
```javscript=
function updateTodoItems() {
todosEl.innerHTML = "";
if (!data.length) {
var liElement = document.createElement('li');
liElement.innerText = "Nothing todo...";
todosEl.appendChild(liElement);
} else {
for (todo of data) {
var liElement = document.createElement('li');
var iElement = document.createElement('i');
liElement.id = todo.id;
liElement.onclick = toggleComplete;
if (todo.done) {
liElement.className = "complete";
iElement.className = "fa fa-check-circle-o";
} else {
iElement.className = "fa fa-circle-o";
}
liElement.appendChild(iElement);
liElement.innerText = todo.task;
todosEl.appendChild(liElement);
}
}
updateRemoveBtn();
}
```
- Take a look at the helper function `getTimeStamp`. This function will return a number, in milliseconds, the current time stamp since January 1, 1970.
- I call this when I create new todo items, what are some ideas as to why I might be using a timestamp for todo `ids`?
>It can be used to whenever the new todo items are created, users can be able to measure their todos with the time codes executed.
- Take a look at the incomplete functions `markAllComplete` and `updateItemsLeft`.
- Can you complete these and add the functionality to this app?
```HTML=
<button onclick="markAllComplet()">All Complete
</button>
<p>You have <span id= "conter-Item"></span> tasks left.
```
```Javascript=
function markAllComplete(event){
for (todo of data) {
todo.done = true;
updateTodoItems();
}
}
var uncompletedEL = document.querySelelctor('#counter-Item');
function updateItemsLeft() {
var uncompletedTodos = data.filter(function(todo){
return todo.done === false;
});
uncompletedEl.textContent = uncompletedTodos.length;
if (uncompletedEl.length) {
uncompletedEl.parentElement.disabled = false;
} else {
uncompletedEl.parentElement.disabled = true;
}
}
function updateTodoItems() {
...
updateItemsLeft();
}
### Part 4 Debugging, Tools
Using the Chrome debugger (source) tool create breakpoints and watch the program execute line by line, part by part. Experience how this tool can give you insight into your program's _STATE_, _SEQUENCE_, _CAUSALITY_.
#### Chrome Debugger
- Set breakpoints at the following locations of your program
- `function initializeTodos`
- `function onEnterKey`
- `function addTodoItem`
- `function toggleComplete`
- Use the `Step over the next function call` feature to watch how the program pauses during the _SEQUENCE_ of its routines.
- Use the `Step into the next function call` feature to watch how the program pauses during the _SEQUENCE_ of its routines.
- What is the difference between `Step over` and `Step into` and how does this help you understand programs?
**'Step Into' is used to debug and fix test steps line by line at a time. And 'Step Over'works if the debugger run the whole function at continuously and stop after the function call on the next executable line.**
- Use `Step into` until you've reached the line `var inputEl = document.querySelector('input');`. Should be highlighted in blue.
- Highlight the variable `todosEl` on the line before it and `right click` on it. Select _Evaluate in console_.
- What does the console print?
**It prints the unordered HTML codes and the codes with specific ID.**
- Highlight the variable `inputEl` on this highlighted blue line.
- Why does the console say `inputEl` is undefined?
**Because the value of the InputEl variable has not been set or the variable has not been declared at all.**
- When you step through your code, does the blue line represent code that is about to be executed or code that has already executed? How do you know?
**It means that the code up to that line has already been run except for that line.**
- What do you predict would be the console value of the variable `completedEl` on the next line if you _Evaluate to console_ at this point?
**Since we do not have the input values for the completed to-do items, we will get undefined as a result.**
- Watch how debugger annotates your source code with the updated _state_ of different variables as your program progresses.
- How does the debugger behave when you enter a loop in your program?
**It keeps running in a loop until it checks all of the code and moves on to the next line.**
- How does the debugger behave when you reach the a `filter` function call?
**It shows filtered data and jump to the next function.**
- What does filter do and how does it work?
**Filter creates a new array containing all array elements that match the filter criteria**
### Part X: Putting all together
**Explain the program line by line with sufficient details, part by part.**
:::success
- Line by line
- Part by part
- Be sure to copy blocks of code into this markdown using code formatting/fences as references to your explanations.
- For repetitive code, you can explain how a line works then summarize how it would work for the rest.
:::
>**Head(HTML)**
```
<head>
<title>Todo List</title>
<link rel="stylesheet" href="css/styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css">
</head>
```
>The title of this project is Todo List.
>Then, let's move to the **body** part.
```
<h1>TODO List</h1>
<ul id="todos">
<!-- ITEMS HERE -->
</ul>
```
>It creates a title for this to-do list and creates an unordered to-do list.
>**controls part(HTML)**
>For the controls part, we have an text area and two buttons.
```
<div class="controls">
<input type="text" onkeypress="onEnterKey(event)">
<!--When the user enter the text, it will trigger an event. -->
<button onclick="addTodoItem()">Add</button>
<!--When this add button is clicked, it will call the function addTodoItem(). A new to do item is added.-->
<button onclick="removeTodoItem()"><span id="counter"></span> Remove</button>
<!--When the remove button is clicked, it will call the function removeTodoItem.Complted to-do items will be removed.-->
</div>
```
>At the end of the to-do list, it provides a link to an alternative version of the to-do list.
```
<a href="https://codepen.io/jmk2142/pen/oGxwPQ" target="_blank">Alternative Version</a>
```
>**CSS PART**
```
html, body {
font-family: Helvetica;
padding: 50px;
font-size: 32px;
}
<! --It assigns styling values to the html and body sections. -->
li {
cursor: pointer;
}
<!--When the user is on this circle of the cursor, the mouse turns into a pointer. -->
.complete {
text-decoration: line-through;
font-style: italic;
color: grey;
}
<!--It assigns styling values for completed to-do items. It will apply a line through the middle of text.Also, the font-style is italic and the whole part of the completed to-do items will be grey.-->
input, button {
font-size: 1rem;
}
<!--It assigns styling values to the input text area and two buttons. -->
a {
font-size: 50%;
}
<!--It is used to apply styles to the links, such as colors, font sizes, and font styles.-->
i {
padding-right: 15px;
}
The i selector is used to apply styles to these inline elements.
```
>**Javascript part**
```
// The core TRUTH of this program
var data = [
{
id: 1497141891479,
task: "Wake up",
done: false
},
{
id: 1497141913701,
task: "Eat breakfast",
done: false
},
{
id: 1497141937545,
task: "Learn code",
done: true
},
{
id: 1233048902189,
task: "Buy bitcoin",
done: true
}
];
// var data = [];
```
>It creates an object and an arrat named data. There are some several nested arrays of data. There are some ids to identify the different existing to-do items.If we don't add or delete any to-do items, when we refresh this page we still get the same list of to-do items.
```
// Important Elements - Cached as variables
var todosEl = document.querySelector('#todos');
var inputEl = document.querySelector('input');
var completedEl = document.querySelector('#counter');
```
>`todosEl` is declared and its value is the id of the element called todos. In this case, it represents all the to-do items.
`inputEl` is declared and its value is the id of the element called input. In this case, it represents the new to-do item we entered in the text area.
`completedEl` is declared and its value is the id of the element called counter.In this case, it represents all the completed to-do items.
```
function initializeTodos() {
updateTodoItems();
}
```
>When the use opens this website, it will will show the current to-do lists. It will call the updateTodoItems function.
```
function updateTodoItems() {
//At first, todosHTML is empty.
var todosHTML = "";
for (todo of data) {
if (todo.done) {
todosHTML += `<li id="task-${ todo.id }" class="complete" onclick="toggleComplete(event)">`;
todosHTML += `<i class="fa fa-check-circle-o"></i>`; // Font-awesome
}
//if a to-do item is marked as completed, todosHTML will increase one completed to-do item and the circle is marked.
else {
todosHTML += `<li id="task-${ todo.id }" onclick="toggleComplete(event)">`;
todosHTML += `<i class="fa fa-circle-o"></i>`; // Font-awesome
}
todosHTML += `${ todo.task }`;
todosHTML += `</li>`;
}
// If no new to-do items are completed, todosHTML will remain unchanged. It will show all previous to-do items.
if (todosHTML === "") {
todosHTML = "<li>Nothing todo...</li>";
}
// //if all the to-do items are completed, todosHTML will show Nothing todo...
todosEl.innerHTML = todosHTML;
updateRemoveBtn();
}
//If todosHTML is empty, then the innerHTML property of that todosEL is set to the string todosHTML, which contains the HTML content that should be added to the element.
//Then, the remove button will be updated.
```
```
function updateRemoveBtn() {
var completedTodos = data.filter(function(todo){
return todo.done === true;
});
//it uses data.fliter to select complted to-do items, then it will make todo.done true.
completedEl.textContent = completedTodos.length;
//Then it sets the text content of the completedEl element to the number of completed to-dos.
if (completedTodos.length)
{
completedEl.parentElement.disabled = false;
}
// If there are completed to-dos, enable the "Remove completed items" button
else {
completedEl.parentElement.disabled = true;
}
// Otherwise, if there are no completed to-dos, disable the button
}
```
```
function onEnterKey(event) {
if (event.code === "Enter") {
addTodoItem();
}
}
```
//If the user enters the new to-do items, it will trigger the addTodoItem function.
```
function validateTask(task) {
if (task !== "") {
return true;
} else {
return false;
}
}
//If task is not equal to empty, it iwll return true.If task is empty, it will return false.
function addTodoItem() {
// Check if the user has entered a valid task
if (!validateTask(inputEl.value)) {
return;
// If not, return without adding the task to the list
}
// Otherwise, add the task to the list...
```
```
var newTodo = {
id: getTimeStamp()
};
//create a new id for a newTodo
newTodo.task = inputEl.value;
//the value of newTodo is equal to the value of inputEL.
newTodo.done = false;
//the value of newTodo will not be marked as completed.
data.push(newTodo);
//it will add new add to newTodo.
updateTodoItems();
//it will update to-do items.
resetInput();
//it will reset inpt.
}
```
```
function toggleComplete(event) {
var todoID = parseInt(event.currentTarget.id.replace('task-',''));
var todoData = getTodoData(todoID);
todoData.done = !todoData.done;
updateTodoItems();
}
```
>The function takes an event object as its input, which is an event triggered by a user interaction with the to-do item.
>The function begins by extracting the ID of the to-do item from the id property of the `event.currentTarget `object. It does this by using the replace method to remove the string "task-" from the id and then using the parseInt function to convert the resulting string to an integer.
>Next, the function retrieves the data for the to-do item with the specified ID using the `getTodoData` function. This data is stored in an array.
>The function then uses the done property of the to-do item's data to toggle its completed status. This is done by using the logical NOT (!) operator to negate the current value of the done property. For example, if the done property is true, then !todoData.done would be false.
>Finally, the function calls the updateTodoItems function to update the to-do list display with the new completed status of the to-do item.
```
function removeTodoItem(event) {
var incompleteTodos = data.filter(function(todo){
return todo.done === false;
});
data = incompleteTodos;
updateTodoItems();
}
```
It defines `removeTodoItem()` function. It select incomplted Todos from the to-do list and create a new array. It only contains to-do items that have not been completed by selecting the property of todo.done is false.
Next, the function assigns the `incompleteTodos` array to the data variable, effectively replacing the original data array with a new array that only contains incomplete to-do items.
Then, it uses `updateTodoItems` to update items.
```
function resetInput() {
inputEl.value = "";
}
```
The function called `resetInput` will set the value of `inputEl` empty.
```
function getTodoData(id) {
var todoFound;
for (var i=0; i < data.length; i++) {
if (data[i].id === id) {
todoFound = data[i];
break;
}
}
if (todoFound) {
return todoFound;
} else {
return null;
}
}
```
>The function called `getTodoData()` uses id as its. element. It creats a loop for `todoFound`. This function will check if the element's id property is equal to the id argument passed to the function. If a match is found, the function assigns the matching element(data[i]) to the todoFound variable and uses the break keyword to exit the for loop.
If there is no matching item, it will return null. Otherwise, it will return `todoFound`.
```
// HELPER FUNCTION
function getTimeStamp() {
return Date.now(); // this returns a timestamp in milliseconds since 1970.
}
//getTimeStamp() is used to create id for new-to do items.
```
>// PARTIAL FUNCTIONS
```
function markAllComplete(event){
for (todo of data) {
todo.done = true;
updateTodoItems();
}
}
```
>When the user click this all remove button, it will make all the value of to-do items completed. Then, it will call `updateTodoItems` function.
function updateItemsLeft() {
// Add an area where the app can give feedback to the user, how many items are left todo.
// E.g. (3 items, all unchecked) "You have 3 tasks left"
// E.g. (3 items, 1 checked) "You have 2 tasks left"
// Modify this incomplete function so that it:
// 1) Calculates how many todo items are incomplete
// 2) Updates the visual display by printing the feedback
// 3) Call this function in the appropriate place(s) (somwhere else in this code)
}
```
// START THE APPLICATION
initializeTodos();
console.log('a');
console.log('b');
```
>It will call the initializeTodos when the use opens this project.
**Make it yours (group's)**
:::success
- Try to extend this program to do something cool, as a group, your own original idea(s).
- What is something that a Todo list or todo list user might benefit from?
Users will not forget their tasks when they are busy. It can help them to manage their time.
:::
>**Ideas**
>* For each to-do item, we can have priority labels from low to high.
* We can create a priority property for each item in the list and assign it a value that indicates the item's priority.
>* We can add the deadline for each to-do item.
* We can create a deadline property for each item in the list and assign it a value that indicates the deadline for the task.