Codecademy Practice

To Do List

Challenge: Build a to-do list app that reveals parts of an image as you mark tasks as done. To mark a task as done, you click it. To remove a task from the task list, you click it again.

To practice: Testing a user interface.

Video showing how to use the To Do list.

Step by step instructions

SVG

SVG is a graphics format based on XML, as HTML once was. It basically means that you have specific tags to create specific elements, and they can have attributes and be applied styles or be targeted with JavaScript. Image formats based on XML are sometimes called “vector” images (SVG, EPS, PDF), since you create the images using geometrical figures. Instead, “raster” images (JPG, PNG, GIF) are made of a collection of pixels. You can read more about the differences between raster images and vector images in this article.

You can open an SVG file in your browser, and when you do that, you can see it’s elements in the inspector, and you can access them from the console too.

SVG images are rarely created by hand. Instead, people use software to create vector images, like Inkscape in Linux (open-source, free), Adobe Illustrator (Mac & Windows, paid) or Sketch (Mac only, paid). However, is a good idea to familiarize with the syntax so that you can manipulate the SVG DOM.

MDN has a full SVG elements reference and a SVG attributes reference. Another good resource about SVG is the blog of the SVG expert Sara Soueidan and any of her talks. There is also a visual explanation of SVG paths in this CSS tricks post.

SVG examples:

<svg width="200" height= "200">
  <circle cx="100" cy="100" r="70" stroke="#ff004a" stroke-width="15" fill="#ffa200" />
  Sorry but this browser does not support inline SVG.
</svg>

produces:

Sorry but this browser does not support inline SVG.

You can give it a class, from inside the SVG or from the page’s CSS file:

<svg width="200" height="200">
  <style>
    .square {
      fill: #27aaff;
      stroke: #222e55;
      stroke-width: 2em;
    }
  </style>
  <rect class="square" x="15" y="15" width="165" height="165" />
  Sorry, your browser does not support inline SVG.  
</svg>

Sorry, your browser does not support inline SVG.

or target it with js:

<svg id="star" height="200" width="200">
  <style>
    polygon {
      fill: lime;
      stroke: purple;
      stroke-width: 5;
      fill-rule: nonzero;
    }
    text {
      cursor: pointer;
    }
  </style>
  <polygon points="100,10 40,198 190,78 10,78 160,198" />
  <text x="75" y="120">Click me!</text>
  Sorry, your browser does not support inline SVG.
</svg>

<script>
  document.getElementById('star').addEventListener('click', () => {
    alert('clicked!');
  });
</script>

Click me! Sorry, your browser does not support inline SVG.

Download the sample SVG image. Load the image in your browser and inspect it. What SVG tags can you see in it? Do they all have an id? Which tags do have an id? Does any of them have a class?

HTML

Create a pair label / text input and a div to hold all the to-dos. Each to-do is a div as well, and will be created when the user types a new to-do and hits Enter.

Use the image as an inline SVG, i.e., copy paste the actual contents of the file in the right place in your layout (it’s a lot of code to paste, but later on we’ll learn a better way to do this, for now this is good enough).

CSS

JS

This app is very UI intensive so all the code is doing DOM manipulation. Features:

Testing

Use TDD to build this logic one test at a time. Considering all your app needs to do, sit and think of all the things you have to implement. Make a list of features. Then translate each into a test, one by one.

Example list of things to test, based on the features mentioned above:

Remember to simulate user journey in your tests. The user types something, then presses enter, then something happens. Setup the DOM before the tests and then reset the DOM after the tests. It is recommended that when you reset the DOM you remove all the elements you created when you setup the DOM, or you will be adding more in every test.

You can simulate a user clicking Enter like this (check the docs at MDN):

let event = new Event('keydown');
event.code = 'Enter';
input.dispatchEvent(event);

Don’t call any methods directly, unless you are going to call them directly explicitly in the HTML (for example, you would probably want to call an initialize() method explicitly in your HTML, in which case you would also have to call it in your tests.)

If the DOM is complex to setup (for example, many elements), you can just add minimal HTML as a string using innerHTML. The backticks allow you to type multiline strings. Don’t overwrite the body contents because Jasmine adds stuff to the body. Better add your stuff in a div.

let container = document.createElement('div');
container.innerHTML = `<anElement>
  Hello
</anElement>
<anotherElement>
  Hi
</anotherElement>`;
document.body.appendChild(container);

Production code: Put every class in its own file. If there is extra code to run (like creating the UI and calling initialize on it) that goes in your HTML page.