paint-brush
You Can Make Your Own Task Manager in 10 minutes: Practicum Coding Bootcampby@evgeniy-lebedev
5,415 reads
5,415 reads

You Can Make Your Own Task Manager in 10 minutes: Practicum Coding Bootcamp

by Evgeniy LebedevJanuary 30th, 2020
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

There are many task managing apps out there, but it’s always exciting to make an app of your own. In this walkthrough, I’ll show you how to write a simple task-managing app that will work in your browser. In later episodes, I’ll show you how to upgrade this task manager to include more features. This is a very basic walkthrough, aimed at beginners. If you are experienced in HTML and JavaScript, don’t expect much from it. But hey, one step at a time is the best way to learn.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - You Can Make Your Own Task Manager in 10 minutes: Practicum Coding Bootcamp
Evgeniy Lebedev HackerNoon profile picture

There are many task managing apps out there, but it’s always exciting to make an app of your own. In this walkthrough, I’ll show you how to write a simple task-managing app that will work in your browser. In later episodes, I’ll show you how to upgrade this task manager to include more features.

This is a very basic walkthrough, aimed at beginners. If you are experienced in HTML and JavaScript, don’t expect much from it. But hey, one step at a time is the best way to learn.

Tools

For this to work, I’ll need a basic text editor and a browser. There are browsers on literally every machine now; I’ll use Chrome. As for our text editor, I prefer Sublime Text for simple tasks like these.

The main idea

In the text editor, I’ll create a web page that has a script. This script will be responsible for managing my tasks.

The task manager itself will be a simple list of bits of text. Those bits will be my tasks. Underneath this list, (or above it, whichever you decide), I’ll put an input box for new tasks. 

The data about my tasks will be stored in Localstorage—that’s an area of memory that lives in your browser and helps store the data related to specific webpages. If I reload the page or restart my computer, my Localstorage will hold on to my tasks, and so the next time I open up the page, my tasks will be there.

Basic page layout 

I’ll begin with the bare minimum for the page. This code below tells the browser that this is an HTML document. The tags

HEAD
and
BODY
are required for the page to work, but at the moment, this page does nothing—it just exists.  

<!DOCTYPE html> 

<html> 

    <head> 

    </head> 

    <body> 

    </body> 

</html> 

I’ll save this as a file—for example, task-manager.html. We need to include “HTML” in the name of the file so that the browser can recognize the page and open it correctly. This page can sit anywhere on my computer.  

Populating the Head 

In an HTML document, the Head contains service information about the page: what its language is, how the page works with other browsers etc. Frankly, we don’t need to go too deep into this: I just copied the code from a verified source.  

So, here’s what needs to go between the

<head>
and
</head>
tags:

<title>My Task Manager</title> 

<meta charset="utf-8"> 

<meta http-equiv="X-UA-Compatible" content="IE=edge"> 

<meta name="viewport" content="width=device-width, initial-scale=1"> 

Populating the Body

Now let’s add something legible to the Body section of the page. The Body section holds the actual contents of the document. So whatever I put here will be rendered. 

At the moment, I want to create a header and an input box. Inside the code, I’ll put the

<!--
signs. When I write things in between the 
<!--
 and 
-->
 signs, these are my comments on my code; they are not rendered by the browser. Read these comments to understand what each line of code stands for: 

<div class="container" style="width: 400px; margin: auto;"> 

<!-- Invisible boundaries for our app. The width is 440 pixels. Our app should sit in the center of the screen. --> 

   <h2 class="todo__caption">My Tasks</h2> 

   <!-- That was the header. --> 

   <!-- Next will come the input field where we can type our tasks. --> 

   <div id="tdlApp"> 

     <input type="text" class="form-control" placeholder="Add a task here"> 

     <!—Now lets create a list of tasks, a list thats currently empty. --> 

    <div class="tdlDiv"> 

       <ul class="tdList list-unstyled"> 

         <!-- Our tasks will appear here later. -->d 

       </ul> 

     </div> 

   </div> 

</div> 

If you saved the page now and then opened it in your browser, you’d see a header and an input box. Nothing would work just yet, but we’ve made a great start. 

Making it beautiful 

I prefer to make an app look good first, then create the code that makes it work. This is because once I’ve written that code, the app starts working, and I no longer have the patience to make it beautiful.

So I’ll spend some time making our new app look nice now, and I’ll create the working code later. 

This app will run as a webpage in my browser. To make a page look good, developers use something called CSS—that’s a kind of markup language that tells the browser everything about the appearance and design of a page. Hence the name—Cascading Style Sheets. It’s all about the style. 

We can apply different styles to the things on a page. We can make a style describe a certain HTML tag—for example, we can make a style for all Inputs. Since I’ve only created one input, this style will only affect one object on my page. But if I had many inputs, this style would affect them all.  

CSS also supports something called ‘classes.’ A class is a kind of a label for a style. For example, we can create a class called ‘

.importantTask
’ and apply it to specific tasks in our list.

And we can specify that ‘

.importantTask
’ has to be red. That way, all tasks that are tagged ‘
.importantTask
’ will appear in red.

Then we could change our mind and make ‘.importantTask’ not red, but blinking and bold instead. Then all tasks with the class ‘

.importantTask
’ would become bold and start blinking.

It’s a good idea to write all our styles in the Head section of the page, so we give the browser all the design instructions before it draws anything on the screen. However, it’s technically possible to place styles anywhere in the document—today’s browsers are so fast, they can handle it just fine. But I’d keep it old school and place my styles in the

<head>
...
</head>
. Observe this code and the comments. (Note: in CSS, we write comments in between 
/*
and
*/
.) 

<style type="text/css"> 

   /* These next instructions will apply to BODY—that is, to the whole page. These instructions should be self-explanatory: how the text is aligned, what the page margins are, what the font is, etc. In CSS, most things turn out to be exactly what they say on the box.* / 

   body{ 

     text-align: center; 

     margin: 10; 

     font-family: Verdana, Arial, sans-serif; 

     font-size: 16px; 

   } 

    /* This next set of instructions relates to the INPUT tag, which is where we input text when using the app. */ 

   input{ 

     display: inline-block; 

     margin: 20px auto; 

     border: 2px solid #eee; 

     padding: 10px 20px; 

     font-family: Verdana, Arial, sans-serif; 

     font-size: 16px; 

   } 

   /* The next set of styles will apply to a class. We’ll call this class ‘.task’ and use it for all our tasks. */ 

   .task{ 

     text-align: left; 

     padding: 10px; 

     cursor: default; 

     border-radius: 7px; 

   } 

   /* What happens if we hover the mouse over a task? */ 

   .task:hover{ 

     background-color: lightblue; 

   } 

 </style> 

Preparing the script 

I now need some application code that will take care of accepting new tasks, storing them, retrieving them from memory, and deleting them if necessary. I’ll do this in JavaScript—a simple scripting language that any modern browser can support.  

To run scripts in JavaScript (JS), I need to add the tag

 <script>
...
</script>
 to the page. By the time it executes a JS script, the browser should have already loaded everything on the page. So, it’s a good idea to place the script at the very end of the Body section, not at the beginning. If I place my JS script at the beginning and tell the script to manipulate some part of the page that hasn’t loaded yet, my script won’t work.

I’ll also use a pre-made JavaScript library called jQuery. I’ll use JQuery’s capabilities to manipulate things on the page. jQuery isn’t necessary for this task: I can manipulate things with JS just fine. But the jQuery code makes things a little easier, and I’m sure I’ll be using it more in the future when I upgrade this project. 

To include jQuery, I’ll use this code in

Head
or
Body
:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> 

I’ll need to make sure that jQuery is loaded before I write my script, so I can use things from jQuery. If I write my script before jQuery loads, I’ll be referencing parts of jQuery that haven’t been loaded yet, and that will throw and error. 

A few words about Localstorage 

Every browser has 

Localstorage
. As we mentioned earlier, that’s a bit of memory that allows your browser to store data related to specific pages. With JavaScript, I can read from and write to Localstorage. So, I can use this area to store my tasks.

Localstorage works well for our project because Localstorage is immune to us reloading the page, rebooting the browser, resetting the internet router, and whatnot. Even if the page freezes, we close the browser, and our internet connection goes dead, the tasks will still be stored properly. 

The downside is that Localstorage doesn’t sync across multiple devices, pages, or browsers. My page can’t read from another page’s Localstorage; it’s restricted to its own Localstorage. So, if I open my task manager on a different computer or even on my own phone, I won’t see my tasks. 

If I wanted to sync my tasks across many devices, I’d need a whole lot of infrastructure: a server, a login-pass routine, a password recovery system, and much, much more. So, I’ll keep it simple for now.

Showing all available tasks 

Once the page has loaded, I want my script to look into Localstorage and see if there are any tasks already stored. Here is the code with my comments. (In JavaScript, comments come after 

//
).

function showTasks(){ 

     // Find out if there is anything lying around in Localstorage and waiting for us: 

     var Storage_size = localStorage.length; 

     // If there is something... 

     if (Storage_size > 0){ 

       // then add it into the task list 

       for (var i = 0; i < Storage_size; i++){ 

         var key = localStorage.key(i); 

         if(key.indexOf(Mask) == 0){ 

           // and make it part of the task list. We’ll use a jQuery command for that:  

           $('<li></li>').addClass('task') 

             .attr('data-itemid', key) 

             .text(localStorage.getItem(key)) 

             .appendTo(List); 

         } 

       } 

     } 

   } 

// At this point, we’ve defined the function, but we haven’t run it yet. Let’s run it now: 

showTasks(); 

If we save our code and reload the page in our browser now, nothing will change visually, but the script already works: it’s going into Localstorage and checking for new tasks. But since Localstorage is empty, there is nothing to display. Good, let’s keep going.  

Adding new tasks 

Our program will add new tasks whenever the user inputs something into the input field and presses Enter. We can use JS to make this happen:

/ We’ll use a jQuery command that gets read like this: Start by looking at an input called ‘tdlApp’. When a key is pressed inside of that input, do the following things. 

$('#tdlApp input').on('keydown',function(e){ 

// If the Enter (code 13) key wasn’t pressed, never mind; just await the next keystroke. 

     if(e.keyCode != 13) return; 

// This next line of code will only run if Enter was pressed. 

// Next line: put whatever was in the input field into temporary memory, under the name ‘str’. Str now holds our task. 

     var str = e.target.value; 

// Then we’ll make the input field blank. The task will stay stored inside the memory, although user can’t see that task in the task list yet. 

     e.target.value = ""; 

     // If the user has indeed written something in the input field, we’ll first count up the current tasks before we add the new one to the task list. That way, we can put our new task on the list in the proper order.  

     if(str.length > 0){ 

       var number_Id = 0; 

       List.children().each(function(index, el){ 

         var element_Id = $(el).attr('data-itemid').slice(4); 

         if(element_Id > number_Id) 

           number_Id = element_Id; 

       }) 

       number_Id++; 

        // Now we’ll send the task into Localstorage... 

       localStorage.setItem(Mask+number_Id,str); 

       // and inject the task into the task list: 

       $('<li></li>').addClass('task') 

         .attr('data-itemid', Mask+number_Id) 

         .text(str).appendTo(List); 

     } 

   }); 

Removing tasks by clicking 

I’ll now add a small snippet of code that removes a task from memory and from the list if you click on it:

// The next line of code adds an event: let something happen when someone clicks on an object with a .task class.  

$(document).on('click','.task', function(e){ 

     // Which task was clicked? 

     var jet = $(e.target); 

     // Remove that item from Localstorage… 

     localStorage.removeItem(jet.attr('data-itemid')); 

     // and from the list, too. 

     jet.remove(); 

   }) 

The final product 

Once we’ve saved the code and reloaded the page in our browser, our brand new Task Manager will look like this: 

Note that this code has a few limitations:

  1. You can’t add more than nine tasks. If you want to add more, then you’ll need a routine that corrects for double-digit and triple-digit numbers. That will complicate the code a little, so I’ve omitted that for now 
  2. No reordering yet. There are libraries that allow reordering of units inside a list though, so it wouldn’t be a very hard thing to implement. 
  3. No synchronization across devices. As we mentioned earlier, syncing your tasks across different machines would require substantially more complex coding. So let’s hold off on that for now. 


And now, without further ado, here is the final code: 

<!DOCTYPE html> 

<html> 

<head> 

  <title>My Task Manager</title> 

  <meta charset="utf-8"> 

  <meta http-equiv="X-UA-Compatible" content="IE=edge"> 

  <meta name="viewport" content="width=device-width, initial-scale=1"> 

  <style type="text/css"> 

    body{ 

      text-align: center; 

      margin: 10; 

      font-family: Verdana, Arial, sans-serif; 

      font-size: 16px; 

    } 

    input{ 

      display: inline-block; 

      margin: 20px auto; 

      border: 2px solid #eee; 

      padding: 10px 20px; 

      font-family: Verdana, Arial, sans-serif; 

      font-size: 16px; 

    } 

    .task{ 

      text-align: left; 

      padding: 10px; 

      cursor: default; 

      border-radius: 7px; 

    } 

    .task:hover{ 

      background-color: lightblue; 

    } 

  </style> 

</head> 

<body> 

  <div class="container"  style="width: 400px; margin: auto;"> 

    <h2 class="todo__caption">My Task Manager</h2> 

    <div id="tdlApp"> 

      <input type="text" class="form-control" placeholder="Add task"> 

      <div class="tdlDiv"> 

        <ul class="List list-unstyled"> 

        </ul> 

      </div> 

    </div> 

  </div> 

  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"> 

  </script> 

  <script> 

    var List = $('#tdlpp ul'); 

    var Mask = 'tdl_'; 

    function showTasks(){ 

      var Storage_size = localStorage.length; 

      if (Storage_size > 0){ 

        for (var i = 0; i < Storage_size; i++){ 

          var key = localStorage.key(i); 

          if(key.indexOf(Mask) == 0){ 

            $('<li></li>').addClass('task') 

              .attr('data-itemid', key) 

              .text(localStorage.getItem(key)) 

              .appendTo(List); 

          } 

        } 

      } 

    } 

    showTasks(); 

    $('#tdlApp input').on('keydown',function(e){ 

      if(e.keyCode != 13) return; 

      var str = e.target.value; 

      e.target.value = ""; 

      if(str.length > 0){ 

        var number_Id = 0; 

        List.children().each(function(index, el){ 

          var element_Id = $(el).attr('data-itemid').slice(4); 

          if(element_Id > number_Id) 

            number_Id = element_Id; 

        }) 

        number_Id++; 

        localStorage.setItem(Mask+number_Id,str); 

        $('<li></li>').addClass('task') 

          .attr('data-itemid', Mask+number_Id) 

          .text(str).appendTo(List); 

      } 

    }); 

    $(document).on('click','.task', function(e){ 

      var jet = $(e.target); 

      localStorage.removeItem(jet.attr('data-itemid')); 

      jet.remove(); 

    }) 

  </script> 

</body> 

</html> 

Found this walkthrough helpful? Explore Practicum. We make it simple to learn programming, data science, and more tech skills from expert mentors.