Goals:
First, download the starter-folder from here.
In that folder, you'll see three files:
First, let's take a look at index.html:
<!DOCTYPE html>
<html>
<head>
<title>TODO List</title>
<link href="styles.css" rel="stylesheet" type="text/css">
</head>
<body>
<!-- Your code here! -->
<script src="index.js"></script>
</body>
</html>
In the header, we set a title and link to styles.css. At the bottom of the body, we link to index.js. That's it -- pretty simple!
If you look at the image at the top of this page, you'll see a sticky note at the center of the page with a button below it. That's actually a form with two inputs (one with type="text" and the other with type="submit"), as shown below:
<form id="form1">
<input type="text" id="todo-input"><br>
<input type="submit" value="Just do it!">
</form>
Here, we have a form with
id="form1"
and a
text input with id="todo-input"
.
These IDs will give us the ability to work with these DOM elements
in javascript. We'll see exactly what I mean in step 2.
We also have a submission input with value="Just Do It!"
.
The value attribute allows us to specify what text we want on our submission button.
Add this form to the body of your html file!
Not too pretty, right? To make it prettier, try adding this to the css code:
body {
margin:0;
background-image: url("https://images.unsplash.com/photo-1510148199876-8a856ee41d42?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&w=1000&q=80")
}
#form1 {
width:100%;
padding: 20px;
text-align: center;
}
#form1 input[type=text] {
font-family: 'Permanent Marker', cursive;
font-size: 20px;
width: 200px;
height: 160px;
padding: 6px 6px;
box-sizing: border-box;
border-top: 40px solid #FFFF88;
background-color: #FFFFA8;
text-align: top;
}
#form1 input[type=text]:focus{
outline: none;
}
In that css code, we're using a font-family named "Permanent Marker." This isn't a built-in font, so we need to import it from Google's Font library. To do so, include this line in the header of your HTML file, above the css-link:
<link href="https://fonts.googleapis.com/css?family=Permanent+Marker&display=swap" rel="stylesheet">
To see other Google Fonts, visit their website at: fonts.google.com
Now, we have a pretty site, but when we try to use it, nothing happens. Let's fix that!!!
To add the on-submit handler, we'll be using a tool called JQuery. JQuery is an extremely popular and powerful tool that makes certain things in Javascript extremely easy. You won't need to know much about how javascript works, but in order to use it, we'll need to import it. To do so, add the following script tag to the bottom of your body tag, but above the link to "index.js":
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
Now, let's add the following code to index.js:
$("#form1").submit(function(e) {
// Your code here!
});
This code is basically saying "When the form with id 'form1' is submitted, run this function." So, when you submit the form, whatever code you have inside of those curly-brackets should run. To prove this to ourselves, let's add a console.log in there, like so:
$("#form1").submit(function(e) {
console.log("form submitted!")
});
Now, every time you submit the form, form submitted!
should be logged to the console. If you try it, though, you'll
notice that those words appear only briefly, then they disappear!
That's because by default, when a form is submitted, the entire
page refreshes. But don't worry -- we can fix this by adding
the following line of code:
$("#form1").submit(function(e) {
e.preventDefault();
console.log("form submitted!")
});
Now it works -- we have code that runs every single time our form
is submitted. Woooo
Our website is still kind of boring, though. Let's actually do something
with the text that's being input. For now, add the following code
to simply log whatever the user inputs:
$("#form1").submit(function(e) {
e.preventDefault();
var todo_input = document.getElementById("todo-input");
var todo_text = todo_input.value;
console.log(todo_text)
});
We added two lines of code. In the first one, we have a statement saying,
document.getElementById("todo-input")
,
which basically asks the HTML document, "Hey -- Could you give
me the element that has the id "todo-input." Then, it stores
that element in a variable called todo_input
.
To get the value that the user typed, we store todo_input.value
in a variable called todo_text
, and to
prove that it all worked, we log that text to the console! Run that code now, and you'll see
that every time you submit the form, whatever you type is logged.
You'll also probably notice something annoying: every time you want to resubmit the form, you
have to delete whatever is in the input. Wouldn't it be nice if we
could just do that in code??? You can! To empty, or reset, the
text input, add the following line of code to the script:
todo_input.value="";
Now, we have a form that runs javascript code upon submission -- great! I'll be the first to admit, however, that this javascript code, although works, doesn't do much -- let's change that now!
Right now, the javascript code simply logs whatever text the
user types. However, we want to add that text to the page on
a sticky-note. To start, let's replace that console.log
with a call to a function:
$("#form1").submit(function(e) {
e.preventDefault();
var todo_input = document.getElementById("todo-input");
var todo_text = todo_input.value;
addNewItem(todo_text);
todo_input.value="";
});
function addNewItem(todo_text){
// Your code here!
}
Now the code will store the text that the user types inside of
todo_text
and then pass that
value to a function to add a new item -- great.
Adding elements to the DOM is a two-step process:
Whenever I construct a DOM element in Javascript, I find it easier if I design it in HTML first, so I also did that for this to-do list application. Each sticky-note, if built in HTML would look like this:
<div class="todo_card">
<p>todo-list Item!</p>
</div>
That DOM element is composed of a <div>
element with
class="todo_card"
and
a child <p>
node. The text
will be inside of the <p>
node.
Great -- now we know what our element would look like IF we were writing
HTML, but we want to use Javascript so we can dynamically create
new elements. So, let's write that Javascript now.
Let's start with the construction of the <div>
element:
// Create new todo div to store all todo content
var todo_card = document.createElement("div");
todo_card.classList.add("todo_card");
On the first line, we ask the document to create a new div element and we
store it in a variable named todo_card
.
Then, we add a class, called todo_card to that element.
Next, let's create the <p>
element:
// Put the todo item in a p
var todo_text_elem = document.createElement("p");
todo_text_elem.innerHTML = todo_text;
This code, similar to the last code-block, creates a new p element
and stores it in a variable named todo_text_elem
.
On the next line, it sets the innerHTML
, or the text
inside of the <p>
element, to be the user's input.
Now, we have the <div>
and
<p>
elements. Next, let's
put them together to create one element that we can append
to the document! Let's do it:
todo_card.appendChild(todo_text_elem);
Here, we're appending the <p>
element that we just created, stored in todo_text_elem
,
to the <div>
element, stored in
todo_card
, creating one element that
we can add to the HTML document.
Before we write more javascript code, we have to have a place in HTML where we can add these elements to. Add the following code to index.html to give us a place to append all of our our sticky-notes:
<div id="container"></div>
Lastly, add the following line of code to index.js to append your element to the DOM:
document.getElementById("container").appendChild(todo_card);
When you run the code, you can see that it works! Woo!
Add the following code to styles.css to make it all look better:
#container {
margin: 20px;
}
.todo_card {
font-family: 'Permanent Marker', cursive;
font-size: 20px;
width: 200px;
height: 160px;
padding: 10px;
border-top: 40px solid #FFFF88;
background-color: #FFFFA8;
display: inline-block;
margin: 20px 20px 0px 0px;
}
The best part of having a To-do list is finishing items and removing them, right? We'll show you how to do that next, and learn about Adding On-Click events along the way.
It would be really annoying if you couldn't remove items from your todo list, right? Let's add a feature to make it such that when a user clicks on a sticky-note, it is removed. To do so, let's head over to javascript and add whats called an event listener.
todo_card.addEventListener("click", function(){
// Your code here!
});
This piece of code adds an event listener to the todo_card
element. In english, that piece of code is saying "Hey Javascript, every time the todo_card
element is clicked, call this function."
So, if we said we wanted to remove a sticky-note every time the element is clicked, we
have to replace // Your code here!
with
code to remove the todo_card element. This is trickier than you may think, though.
The code in that function isn't running now -- it runs when something is clicked,
but we don't know when that will be. As such, we need a way to
identify the sticky-note whenever that happens.
As such, we'll have to give the todo_card
element an id, like so:
var todo_card_id = String(Math.random())
todo_card.id = todo_card_id
We start by creating a new variable that stores a random number.
We're using a random number because we want our IDs to be unique
and we can assume that these random numbers won't repeat.
DISCLAIMER: You should NOT always use this, because random numbers DO repeat.
We're just using this for this example, but it is generally
not great practice.
the next line sets the id of the todo_card
element to the value we just produced.
Now that we have a unique ID in each of our sticky-notes, we can
simply replace // Your code here!
in our javascript file with the following line of code:
document.getElementById(todo_card_id).remove()
This line asks the document "Can I have the element that
has an ID equal to todo_card_id
?"
which is the value we just calculated!
You did it! You made a todo-list application using DOM manipulation.
You'll notice that if you refresh, nothing is saved. That's
because there's no back-end (hint hint, we'll learn
that next).