Javascript Fun: Build A Running Tracker App! | Chris Dixon | Skillshare

Playback Speed

  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

Javascript Fun: Build A Running Tracker App!

teacher avatar Chris Dixon, Web Developer & Online Teacher

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.

      Welcome To The Class!


    • 2.

      Share Your Work On Skillshare!


    • 3.

      Creating The User Interface


    • 4.

      Fonts & Styling


    • 5.

      Adding New Entries


    • 6.

      Calculating Total & Average


    • 7.

      Weekly High & Goals


    • 8.

      Progress Circle


    • 9.

      Follow Me On Skillshare!


  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.





About This Class

Welcome to the Javascript fun series! 

You can find all of the code and project stages here:

For web design or development, there are 3 must-know technologies, HTML, CSS, and Javascript.

The main aim of the Javascript fun series is to take your knowledge of these 3 (only a little is required!), and put them into practice by building a series of educational, yet fun projects that show you exactly how they work perfectly together. Working on projects and solving problems is a great way to learn.

The project we will build in this class will be a Javascript Running Tracker App.

All the required tools are free to download, I will be using the following:

Visual Studio Code Text Editor:​

Chrome Web Browser:

We begin by creating the user interface with HTML. We then apply styling using CSS. 

Then we add Javascript, this is where the real magic happens! 

You will learn things such as:

  • Creating HTML interfaces
  • Styling with CSS
  • Incorporating Javascript and linking external files
  • Variables / Constants
  • Functions
  • Event handlers
  • Manipulating the DOM
  • Arrays & Array Methods
  • Conditionals
  • Converting values to a number
  • Submitting & Re-setting Forms
  • Creating Progress Circles Using Javascript & CSS
  • Template Strings
  • Javascript Math
  • Reducers
  • And much more!

So if you are looking to move on and put your skills into practice by building real projects, I hope to see you in class!

Meet Your Teacher

Teacher Profile Image

Chris Dixon

Web Developer & Online Teacher

Top Teacher

Hello, My name is Chris and I am a Web Developer from the UK. I am an experienced trainer leading web development bootcamps and also teaching online courses.

My main areas of interest are Vue.js, WordPress, Shopify, Javascript, eCommerce, and business. I am passionate about what I do and about teaching others. 

Whatever your reason for learning to build websites you have made an excellent career choice.

My personal motivation was to become my own boss and have more freedom and flexibility in my life. I also enjoy the technical challenge it provides and the way it constantly evolves. I built my first website back in 1999 and I have watched the web evolve into what it is today.

I try to make my courses enjoyable and try to remember what it was like wh... See full profile

Level: Beginner

Class Ratings

Expectations Met?
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.


1. Welcome To The Class!: Hey, welcome to this class. If you are a web development beginner, come on, so just jump in, and build some fun projects. You've came to the right place. The idea behind this series is to show you what you can do with regular HTML, CSS, and JavaScript. When it comes to using any frameworks, any boilerplate, any libraries, or any templates, instead, we're going to be building everything completely from scratch, step-by-step to show you how these free technologies all work together. The project for this class is a running [inaudible] application, where the user can log how many miles they have run each day. We have an input field at the very top, where we can log the number of miles and these will be recorded as the last seven days values. If you add a second one, this will then be added over on the right and it stores the last seven values which we enter. All these values are then stored just below. We can see the total number of miles. This total is then divided up by the number of entries, to give us a average too, along what's on the highest entry which the user has entered for this week too. In addition to this just below, we'll also add a progress circle too, where we can add in a weekly target, and then this progress circle will be updated for each value which the user adds. This will give us a nice visual feedback of how the week is going too. This project is created completely from scratch. We'll use HTML for the user interface, we'll add custom font, we'll add styling, we'll learn all about the JavaScript fundamentals such as functions, creating variables and constants, we'll work with arrays, we'll create calculations, we'll work with the DOM, we'll work with events, conditional statements, and all the fundamentals which you will need in JavaScript. Your progress circle will also be fully custom too. We'll make use of JavaScript, and also CSS to keep this updated. Well, thanks for checking out this class and I'll see you in the first lesson. 2. Share Your Work On Skillshare!: When taking any course, it's really important to not get in the habit of following along just for the sake of ticking off another lecture. Take the time to process each lesson. Review the code which you write, and think about how you might approach these solutions yourself. With this in mind, this class is project-based and this gives you the opportunity to really make something personal and unique. You don't need to get too lost and divert away from the class and you can even take a step back after you've finished the class, come back and make some project changes afterwards. This will really give you a good chance to practice what you've learned a way from the class. Also, remember to share your project too here on Skillshare, and not only will I check it out, but it will also inspire fellow students too. More information on the class project head into the project and resources tab where you can not only upload your project, but you can also see other class projects too. With this in mind I look forward to seeing what you create, and upload here on Skillshare. 3. Creating The User Interface: This is a look of what we are going to build in this upcoming set of videos. We're going to build a running track application where the user can log each day, how many miles they've ran. For example, we could add a value for today such as 1.9, and this is then added to the end of this array. Each day we can add a value, and we'll record the values for the last seven days. Each time I add value, we will replace any of these placeholders, let's add the new one inside of here, and these all pushed off the edge here, so we got the latest seven days. Scrolling down, we have an area where we can check out all of our stats. So just the total, which will run in this particular week, the average distance, and also the highest recorded value for this particular week. Right at the very bottom, we can also add a target inside the code where we can say how many miles we want to run for that particular week. This is then updated each time I add a new value, and then we see this nice progress circle down at the bottom. Let's add the new value, and this is then added to our total and also updating the progress circle. We're going to start in this video by creating the user interface with HTML, and to do this we can also use this image up at the top, which is in SVG. You can of course find your own, but if you want to use the same one, which I'm using in the course, head over to this link on GitHub, which is chrisdixon161/ In this repository, you'll find all of the finished code for each one of these projects. If you head into the Running Tracker, you'll also see a runner.svg. To use this inside of our project, we need to click on the code icon, and this is the code which we need just here. We're going to now begin by creating our project and we'll come back to this very soon. Let's go over to the desktop. I'm going to create a new folder. I am going to name this the running-tracker. Open up Visual Studio code and then we can drag over our projects. The first thing we need is to create an index.html page, this is going to be for our user interface. Let's create a new file inside of our folder, this is the index.html. If you're using visual studio code, you can make use of the shortcut, which is html:5, and hit Enter. This will then give us our starting points for our HTML page. I can also open this up in the browser by clicking on the tab, copy the path, and then paste this inside of the browser. As always, you can double-click on the index.html file, which is also contained inside of our project folder. Working from the very top we're going to include this SVG right at the very start. To do this I'm going to create a div section, which is going to have the class of logo. Inside of this section we can now make use of our SVG. I'll copy the code from GitHub, paste this in. Moving down; the next thing we need for our project is the input section. We're going to create this with a label and then a number input, and then a button to submit this form. Just below our logo section, or the wrapper div, create our form. We also don't need the action, we're going to begin with a label. This label is going to be for a input with the Id of entry, and then the text is going to be number of miles today. You can also change this to be kilometers, or any other value which you want to use, that's completely fine too and it won't affect this application. A break tag, put this onto a new line. Then our input, which is going to have the type of number, the id of entry which is going to match our label, and then a step attribute of 0.1, which means our values inside of the number inputs will increase by the value of 0.1. After this, a new break tag, so we can then add our submit button. The button needs the type of submit which will allow this to submit our form. At the moment, we don't have any JavaScript in place to take advantage of the numbers which the user inputs, but for now we can add these dashes as placeholder values. We're going to do this by creating a wrapper for the section, creating an unordered list, and each one of these values is going to be a list item. Below our form, a horizontal rule just to divide the section. The section elements on the class, so we can use this inside of the CSS is going to be the entriesWrapper. The title of the last seven days. As we just mentioned, and unordered lists to store all of these values, which can also have an id, so we can target this inside of JavaScript. For now our placeholder value is simply going to be a dash. Since we work in with the previous seven days, I'm going to duplicate this to grade seven list items, and let's check this out. Next we have a data section which is going to be all of the stats for our application. We're going to create a section and three separate divs, and each one of these divs is going to have a title and also a value. We can also write this in a new section in our HTML. A section can have a class of data, and then our first div for our total section. But each one of these titles on the left I'm going to to wrap this in a p elements, and then a span over on the right. The first p is for the text of total and then a colon. The first span, you can even live is empty, or put in a placeholder value, this will also need an id, so we're going to update this in JavaScript. After this div, we can then concentrate on our average distance section. New div, the p elements, and the text for this one is average distance. The span for this one is also going to have a unique id, which is going to be the average. Again, you can also add a placeholder number, but this is completely optional. The third section is for the weekly high-value. Our p elements, we headed this weeks high. Our span with the id, which is going to be high, and then a default value. Let's take a look at this. Most of the user interface is now in place, but we just need to take a look at the bottom and then add our progress circle. All of this progress circle is going to be dependent on the JavaScript and also the CSS, which we'll add in future videos, but for now we can create a label and also a div section, so we can use this later on in the course. The final section down at the very bottom, you can add a class of progress. Then our level three heading up at the top which is weekly target. This weekly target section is going to have also two separate values. We'll have the total number of miles for this particular week, and then also a slash followed by the target. To do this, I'm going to add two separate span elements. The first one, this is going to have an id of progress total, a placeholder value of zero after the span, add a forward slash. Then a second span element, let's add a default value of 25, and also an id which is going to be equal to target. After both of these spans, we also need to add the text of miles right at the very end after our last span. Let's add this onto their own line so it's more readable, there we go. Also make sure that all of this is contained inside of the level three heading, save, and reload the browser. We have a heading, and the very last thing to do below the level three heading is to add a new div, which is going to be for our progress circle. We can add this just with a class of progress circle wrapper. As we mentioned earlier, we don't need to do anything else with this section, this is simply going to be a placeholder div, we'll deal with this later on using CSS and also JavaScript. For now we'll call this video done, our user interface is now in place, and in the next video we'll make it look a lot nicer using CSS. 4. Fonts & Styling: Let's now make this application a little prettier by using some CSS and also by adding a Google font. The first thing if we open up the sidebar and go into our project, let's create the styles.css and then link this in the head of our index.html. I've already chosen a font from Google Fonts, but you can choose any different one which you prefer. This is the one I'm going to use, which is on the homepage, but you can choose or search for a different value up at the top. To include this, just like the earlier project, let's click on this and then we can select any of the font weights. I'm going to go for the 300, the 500 and a bold 700 version. Embed, and then let's copy this link which you can place in our index page, just above our style sheet, and then our font family is placed in our styles.css. We can add this in the root under the HTML element. Paste this in and we can also select a root font-size. I'm going to go for 10 pixels. You can also set a background color. This is going to be for the section behind our content. If we stretch the browser on the final version, this is the color which we see outside of the body section. The volume I'm going to use is 2d3740. Let's check this is working and our style sheet has linked correctly. Reload this and we see the background color, we see a different font and also the font size has taken effect. The reason we see all of this background rather than it just on the outsides, is because we haven't yet set a color for our body section. Let's do this now. First of all, some padding which is going to give you some spacing around our edges of 1rem, which is 10 pixels, then a background for the section. The volume I'm going to use is 1c262f. The font is a little hard to read with this dark background, so we can also change the font color. We can again use a hex value, just like we've used above, or we can also use a RGB color, just select any of our values. An RGB color is a way to combine red, green, and blue values to make a particular color. I'm going to go for a red value of 230, 225 for the green and 225 for the blue. This is going to give us this light white color, which will take effect for all of our body section. To find out more about these particular color values, we can do a search for HTML color picker. There is various color pickers which you can see online, or this default one which comes with the search engine. We can see for any shade which we select, have a red, green, and blue value, and also the equivalent hex value which we've looked at just above, along with some different values here too. This is just a couple of different ways you can use to select color values. Next back over in the body section, the width of 90 percent just to restrict the overall width of the project, and also center this with margin zero auto. Remember, if we didn't have this auto value, this will be pushed over. Let's just check this. This will be pushed over on the left of the project. But now with the auto value on the left and right, this has now divided up equally on both sides. After the body, lets go for the logo section, which is at the very top. We can sensor this with text-align center. The current fill color for our image at the top doesn't currently stand out too well on this darker background. Just like we see in the final version, we can also change this too. We can also target this in the CSS, or we can do this over in our index.html. The way to do this inside of our SVG element, is to take a look at the path section. Each one of these sections has a fill attribute which we can change. I want to change this to be a value of gray, refresh, and now the head section is gray, and we can also do the same for the body section. Back over to our style sheet, we're going to now move down to the form section, which is going to be the wrapper for our label, the form inputs and also the submit button. All we need to do for this wrapper is to set the text line into the center. We need to make the label a little larger, so let's target this. The font size, I want to go for 1.8rems, which is equivalent of 18 pixels down to the number input. First target all of the form inputs, then inside the square brackets, we can select our particular type of number. Not any type of number is not particularly important for this project since we don't have multiple inputs, but this way we are covered four a project was to grow at a later stage. By default, the form input won't inherit the rest of the font family. We can see this is a completely different font than the rest of the project. Font family, we can set this to be inherit. Lets now inherit the font style from the rest of the project. The background, to keep things consistent. Let's also grab the same RGB color, which we used for the lighter text. The width of 80 percent. Some spacing on the top and bottom, 1rem and then a value of zero on the left and right. To make the actual form input larger too, we can add some padding inside. 0.8rems on the top and bottom, and then zero on the left and right. Remove the default border with border none, a font-size to make this a little larger when you use inputs or value. Let's go for our 1.2rems and also set the text-align to be centered. Moving down, the next thing we have is this form submit button. To make this just like the finished version, we're going to add a background color. We're going to add a 50 percent border-radius to make this fully rounded, along with setting the width and height. Let's target our bottom element. Again, we also need to inherit the font family. The font size a little larger and also the font weight is going to be bolder too. To make this a rounded bottom, we're also going to set a width and also an equal height. I'm going to go for eight pixels and also a matching value for the height too. Let's see how this is looking inside the browser. This is equal width and height, but we also need to round the corners with the border-radius, and also remove any default borders. Let's start with border none, and then the border-radius, which has a value of 50 percent. To give this the blue color we see in the final version, we need to set the background color. I want to go for a hex value which is equal to 0ad9ff, followed by some margin values. On the very top, 0.5rems on the top, zero on the right, 1rem on the bottom, and then zero on the left. Moving down to our last seven days values, this is inside of another list. Remove the default padding with the value of zero, and we also need to remove the list item bullets, and then we can set this to go across the page by setting the display type to be flex. Remove the bullets with the list-style to be none leaving us with the dashes which we have for each list item. Taking a look at the finished version, we also have some equal spacing between each one of these items, and we can do this by setting justify content to have space between. On the list is a step in the right direction for styling the section. The next thing we need to do is to target each one of our list items. Starting with the borders, each one of these items stands out more. Let's go for a value of one pixel, a solid line, and then some padding inside of these list items to add some spacing. One rem on the top and bottom and 1.5 on the left and right. Within this section, let's target the level three heading, increase the font size and also add some padding to give it some spacing just like on the final version. To do this often in the index.html, we have a section with the class of entries wrapper. Let's target this. Some can work with our a level three heading and also add some spacing to our sections. This is a class so we need the dots. First of all, we can add some padding to give this some spacing on the top and bottom of 1rem, zero on the left and right, and then also set the default font size to be 1.6rems. Next up the level three heading which is for the title of last seven days. We can remove any default margin which the browser provides, and you can see this removes the default margin from the very top of our heading. We can push this into the center, with text-align. This is also pretty bold, so let's change the font weight to be lighter. Below this, we have all of the rest of the information for our app. We have the total, the distances and also the weekly height. This is all wrapped in a section with the class of data. Moving down, let's target this. First of all, we can set the default font size to be a little larger, so 1.4rems. Each one of our sections is surrounded inside of a div two, so we can and then div. Let's begin with the background color for each one of our sections. The value I'm going to use is going to be 141c22. The display type is going to be equal to flex. We can make use of the flexbox to center our label and also the value on the same line, along with also adding some space in between. We first place these onto their own line with a line item center, and now it's at the spacing in between, we can use justify content. This now pushes all of our values over to the right. The next thing to do is to add some padding. These are not up against the left and right edges and also some margin to the outside of our div, so all three sections have some space in between. First of all, the margin on the top and bottom, I'm going to use 0.5rems, zero on the left and right, and then some padding inside of our divs. We already have some spacing on the top and bottom so let's just add some spacing on the left and right. Zero and then 1rem. This is now the majority of the styling for our application. We just need to target the section at the bottom later on when we add the progress circle. But for now though, let's move on to the next video and add some JavaScript to our project, so we can update our entries. 5. Adding New Entries: The styling for our project is pretty much now in place, there's just a little to come back to later on. When we add this section down at the very bottom. Well, for now though, we're going to move on to add in our script file to introduce some JavaScript. In particular, in this video, we'll capture the user's input and then update our last seven days. The first thing we need to do inside of our project is to create a new file, which is going to be this script.js. The first thing to do is to link this down at the very bottom, just above our close and body section. We can link this with the script elements. This is also in the [inaudible] project alongside our index. We can just reference this with script.js. Let's take a quick moment to think about exactly what we want to do here. We have a form input just here where the user will add the value. We want to listen out for any form submissions. Once this happens, we don't want to run a function. Let us start with this of in this script.js. The first thing to do is to grab a reference to our form. For this form section, we now need to listen out for the submit event. The submit event will be called each time the user hits enter inside this input or clicks on our submit button. In the script, let's create a reference to this form. Const form. All form reference is always going to stay the same. This can be used as a constant within a target, the full document. Then we can use the query selector. Query selector is a way to capture HTML elements, and we can capture any of the elements in our HTML. The way we do this is exactly the same as our style sheets. If we target any elements, we reference the elements by the name. If it's a class, we use the dot followed by the class name. If it was a ID, we would use the hash prefix. Since our form, is just simply a form element. We can target this. Then we want to add an event listener. The events in which you want to listen for is the submit event. Then we want to run a function. We add the name of our function as the second value separated by a comma. The function name is going to be a handle submit. We haven't created this handle submit function just yet. Just above our event listener, we can create this now. Handlesubmit is going to take in the event information which is passed to the function each time form has been submit. The first thing we want to do is to grab this event information and then call prevent default. Prevent defaults will prevent the default behavior of the form submission which is to reload the browser. For this use case, we don't want to refresh the browser since all of our information will be lost. Instead what we want to do is to actually capture the user inputs from this field here. Again, let's use querySelector. This is going to grab our form input. We could either grab this using the input name or also buy the ID of entry. So document.querySelector. Just like with CSS, we target this with the hash and then the ID name. We can then grab the value and also store this inside of a variable or a constant. If you remember from early when we created the Tip calculator, one of the problems which we had when we grabbed the information submitted by the user was the value came in the form of string. Since we work with numbers, we want to convert this to be a number type. That could be this, I'm going to convert this string value to be number, bypassing this into the JavaScript number function. Before moving on, let's do a console log with the value of entry and check everything is working fine. Right-click Inspect and we can go into the console. Click the console tab. Let's add some random numbers inside here. So 1.2, 6.4, meaning we now successfully listening for a submit event and also capturing the user's input. There's also a couple of ways we can improve on this if we go over to our input and type the value of zero, we still see that the value of zero is still logged. This could cause a problem if the user was hit enter by accident before inputting their value. Also each time a value is added, we also want to clear this form so it's available for the next entry. Back over to our function, we can use an if statement to check if no entry has been made. Use the exclamation mark. This means if no entry is present or the value is false. Then we can use the return keyword to break out of our function since no value has been entered. The next thing to do is to clear the form input each time a value has been submit. First of all, let's grab all form. So document.querySelector. We can grab our form. Then we can call the reset method, which is going to clear all of our form inputs. Enter the value. Now when we enter a value and hit Enter, I will form input is cleared. With this taken care of, the next thing we want to do is to actually store all of the user values inside of an array. I'm going to initialize our array called entries and set this equal to an empty array. Notice here we use the let keyword rather than const because we want to update the values of entries. If this was said to be const, we won't be able to obtain this array by pushing new values. Now the way to actually add a new value inside of our empty array is to first target this by the variable name of entries. Then an array has a push method which allows us to push a new value to the end of our array. The value which you want to push is our entry, which has been captured from our user input. Let's test this out with a console log. We can now output the value of entries which is our array. Reload. Insert a couple of values inside here, let's see what happens. This will now update our array with the user inputs. With this all now working, let's remove our console log and we could carry on adding more code to this handleSubmit method. But to keep this more clean, I'm going to create a new function which is going to update our user interface. Each one of these array items is going to be pushed onto the end of our unordered list. Let's create a new function about the very top, and I'm going to call this addNewEntry. I'm also going to call this function each time the user enters a new input, also, parsing in the value of entry. This entry value will then be received inside of our function, and I'm going to call this newEntry, but the value will be exactly the same. First of all, let's do a console log with the value of the newEntry just to check we are receiving this correctly in our function. Add a value. Okay. Good. Now our function has access to each one of these user inputs. One of the great things about using JavaScript is we can also use it to create new elements in our DOM. If we go to our index.html, so far we've been creating all of these elements inside of our HTML page. But we can also use JavaScript to create these too. The way we're going to use this in this function is we're going to target this unordered list, and then for each new number which the user adds, we're then going to create a new list item. The way to do this is by using document.createElement. When creating a new HTML Element, we can use the same element name as the opening tag. We can create an unordered list, a list item, a level 3 heading, or even a section. We are going to be using a list item, so we can push this to the end of our list. Let's start this inside of a constant called listItem, and then, next, we also need a value to go in between our elements. At the moment, this is just going to create a list item, which is just like this. But we also need to create some text content inside. We do this in JavaScript with document.createTextNode. We can parse in anything, such as a string of text. But in our case, we want to parse in the new entry, then also store this in a constant too, and we're going to call this the list value. This now leaves us with the actual elements and the contents. But these are two separate nodes. We need to actually add our list value to our list item. The way we can do this is by grabbing our listItem, and then we use appendChild. This is going to add a newChild node. Under newChild node, one we want to add is the listValue. Here, what we're basically doing is creating a list item with this first line. Then with the second line, we're creating a value from our new entry. If the user enters 2.7, this will be stored in listValue. We then append in this listValue into our listItem. This is going to grab our value and place this inside of our elements. This now leaves us with a fully constructed list item. This list item now needs to push to our unordered list. The way we can do this is by first targeting our unordered list, find the ID of entries. Outside of our function I'm going to create a constant, which is called our entriesWrapper. This is going to be equal to document.querySelector, with the ID of entries. This is our unordered list, and now we need to push the listItem, which we have here. The way we can do this is very similar to this line just here. We're going to grab our unordered list. Again, using appendChild, adding on our full listItem. This will now take our list item add this until the very end of our unordered list creating a new value at the end. Go to the browser and reload, and add some values, 1.4, and these are all now added to the end of our list. This is all good. This now means our entries in our working are being pushed to our array, and we're also creating a new list item and updating the DOM. Just one little thing we need to do before we wrap this video up. These three new values which we just added will be added to the existing seven entries. We only want to keep a record of the last seven days. Each time we add a value to the end of the array, we also want to remove the first value too. The way we do this in JavaScript is pretty much the opposite of what we've just done here. Here we were grabbing the unordered list and appending a newChild element. Instead, though, we want to do the opposite, which is to remove a child. Let's do this at the start of our addNewEntry function. Grab the entriesWrapper, which is our unordered list, and then we can call removeChild. If we just simply call removeChild, JavaScript won't know exactly which child element we want to remove. By child element, we mean each one of these list items. But, fortunately, JavaScript provides us with an easy and simple way to target the very first child elements. This is a property called firstChildElement. If I go over to our script, we can target the entriesWrapper, which is all of our unordered list, and then select the firstElementChild. Let's now save this file and go back over to the browser and check if this is working. Let's add some values, 4, 5, 6, 7. Now, for each element which we add, we see that we still have seven days in total. Let's add number 8, and we see the value of one has now been removed from the start of our list. Let's try one more. The value of nine. This removes the value of two. All of this may look pretty complex if it's something which you've not done before, but all we're doing is adding a new list item to the end here and then removing the very first one. This is now a really important part of our running truck application now complete. Next, we'll move down to our start section where we'll add the total and also the average distance. 6. Calculating Total & Average: Let's get to work now on some of these stats down at the bottom. This video, we're going to focus on calculating the total and also the average distance. Now to do this, we are going to make use of a JavaScript array method called reduce. Let's take a quick look at how we can use this. If you've not used the reduced method before, it can look pretty complex, but it's really not too difficult to use. The main concept behind a reduce method, is it will take all of the elements, all of the values which is inside of an array, in our case, it's going to be all of our distances, and then we're going to reduce it into one single value. In our case, we're going to reduce down all of our values by adding them all together. This is going to give us our total which we need just here, and then we can also make use of this in the average distance by dividing this total by the number of entries. Back to the reducer, we're going to create a function just like this. The example we see here is pretty much exactly how we need to use it. We're going to add together all of the values in the array. We do this by calling a method which adds the current value to the previous total. For the first element inside of the array which is one, it will then call this method, but this first time we only have the current value, we don't have the total, so the reducer will be equal to one. For the second value which is two, the current value of two will be added to the total of one, resulting in a value of three. Continuing on, the value of three will then be added to the current total, making this six. The value of four then completes the reducer, resulting in a total value of 10. Back over to our script.js, we're going to begin by creating a function which is going to have the same behavior. I'm going to do mine just above our handleSubmit. The function which I'm going to call the reducer takes in our two values which is the total, and then the current value. I'll just call this a total rather than accumulator since it seems more clear. All this function is going to do is to return the new value, which is equivalent of the total which has been added to the current value. Just as a side note here, we are adding the current value to the total, but you could do other things such as take it away too. The whole idea is exactly the same. The reducer is intended to reduce our array values into one single value. The next thing to do is we're going to create a new function just below, and I'm going to call this calTotal. This function is going to grab all of our entries, use a reduce method, and then update our value just here. To do this, it also needs to take in all of our current entries, which is inside of our array. We can then grab our entries array, which is only values stored inside here. We can then call the reduced method, which we just looked at on the Mozilla website, and then we can pass in our reducer function. This will then give us our single total value, and we can also store this inside of a constant. Now I have this value, we're going to update the DOM. The two values which we want to update if we take a look at our project is the total section just here, and we also have a total which is updated for our weekly targets. Let's grab the documents, we can grab an element by the id. The first one which we want to grab is for the total just here, scroll down to the data section, and we have a span with the id of total. We can then set the innerText content to be equal to our total value. Let's duplicate this line, and we can also use this to update the weekly targets. Now the bottom of our index page, this is this progressTotal which currently has the value of zero, we could remove the placeholder, update our id. We now have our function which calculates the total. In fact, it should just be calcTotal. Now every time we handleSubmit down at the bottom, we now want to call this function. When we call this, we can also pass in the entries. The entries was the value from our array at the very top here, or we can leave this empty for this particular case, because this is a global variable. When we declare a variable outside of any of these functions, this means this is now in global scope, meaning that we can access the value of entries anywhere inside of our program. If our variable was declared inside of any particular function, we could only access it inside of that function. So since this is global, we can access this inside of this function and also this one just here too. With this in place, now let's save this and over to the browser. Let's add some new values. One and two, these two added up give us the total of three, and also down in our target too. Let's add one more, and our totals are now updated. With this working, now let's move on to the average distance. The average distance is going to be pretty simple because we already have our reducer function in place. All we need to do is to create a new function to take care of this. I'm going to call this calcAverage. The way we can calculate the average is to first, grab all of the total values which you've added together. We know how to do this from our function just above. Then we can divide it by how many entries we currently have giving us the average. Let's start this inside of a constant called average. This equal to our entries array, we can again, call our reduce method, passing in our reducer function. This will then give us the total, and the next thing we need to do is to divide this by the number of entries. We can do this by grabbing our entries array and then calling.length. The next step is to update the DOM with document.getElementById. The Id which you want to grab over in the index.html, is this average id just here. Just like above, we'll also set the innerText to be equal to our average variable from above. The last step is to actually call this function, calcAverage. This also doesn't need anything passed to it since it's only taking advantage of the entries array, which we have at the top. Save this file and off to the browser. Now if we add in it two different values, we see the total of four. The total of 4 divided by 2 gives us a average of 2. Let's try at one more, go for 10. Our average is now updated. Just one more finishing touch we can do to this project for these two values is to round these to one decimal place. At the moment, we get a rounded number of 14, but if we do something such as 2.7, but I want to keep this consistent and make sure all values are to one decimal place. Just like earlier, the way to do this is to use toFixed. I'm going to set this to be one decimal place so passing the value of one. This is going to be for our total, and we can do the same for our average too. We would need to wrap this inside of our brackets, and then call toFixed on the total. If we didn't wrap this in brackets, toFixed would be called on the entries.length rather than the total sum. Let's test this out. One and five giving us a total of six, which has a value of 6.0 now. The average, let's add some more values. We can now say our total and average is rounded to one decimal place. We can also do the same for our entries just here. We can do this up above where we created our new entries, and also here where we add the new entry as our text note. Just like before, we can also call toFixed passing in the value of one and now if we add some entries, we see these rounded to one decimal place. This is now our total and the average now taken care of, and in the next video, we'll take a look at the weekly goal, and also the weekly high. 7. Weekly High & Goals: We now have the total values and also the average distance. We now want to move on to calculating the highest value of that week, and also updating our goal down at the bottom too. So to do this, let's go back over to our script.js and we can create a function to calculate this. The name of this function will be weeklyHigh, and all we need to do is to calculate the highest value which has been added into our entries array. Store this in a constant called high. The way we can do this is by use of a malfunction JavaScript provides which is called Math. Inside here we can pass in different values such as four,12, and six. Now if we do a console log for the value of high, we should see that the value of 12 is output. Let's call this inside side our function handleSubmit, and we can check this is working in the console. We can add any value inside here. Hit Enter, and we see the value of 12. But instead we want to grab the highest value from our entries array. Let's find Yes, we can pass in our entries array and check this is working. So five, six, and one. This now gives us a problem inside the console. So the reason this is happening is because Math.max will expect a series of numbers. However, we are passing an entries array. So we effectively do in something like this. Instead, what we want is to extract the actual values from inside of our array, so it looks more like this. The way we can do this is by using the JavaScript spread operator, which is the three dots. This will then extract all of the values inside of our entries array and this should now work inside the console. Now will have the high-value, we can now update the DOM. So document.getElementById, the ID we want, if we go to the index page, is the value of high. Let's set the inner text, which is going to be equal to our variable. That's out, so the value of one, five, we see the weekly high is a value of five. Seven, this is being updated. If we add the lower values which is three, this still has the high value of seven. Next up, we can also make our weekly target more dynamic too, by controlling this from our scripts. We don't need to do this by a function, we can just do this as soon as our script loads. So let's create a variable at the top or a constant. I'm going to call this our goal. Set this to any value such as 25. We can then use a query selector or getElementById to update our target. The target Id and then we need to set the in a text to be equal to our goal. We can also remove the placeholder value of 25 and also check this is working in the browser. We don't have anything to obtain this goal from the user interface. I've just hard coded this as a value inside the script. But of course, if you do want a little challenge, you can go ahead and add this to the project so we can be updated by the user. Most of the functionality is now in place. The final part we're going to do, if we take a look at the final version, is to create this progress circle down at the bottom. 8. Progress Circle: Welcome back and to this final video of this project. This video is all about concentrating on our progressCircle, which we're going to create, just like in the final version, just here. Each time the user enters a value into the number field, such as this, the weekly target will then be updated and this will be converted into a percentage so we can update the progressCircle. Now, I am aware there's many different ways we can do this. We can use things such as the Canvas, and there's lots more complex options which we can use. However, I've tried to keep this as simple as possible for this project. The way we're going to do this is by making use of a CSS function called the conic-gradient. The way this works is to create a gradient of color which is transitioned around the center point. Here we can see we have the first section, which is red, and this is from 0-6 degrees, the orange section then carries on from 6-18 degrees, then we have the yellow section up to 45 degrees and this thing continues round. If we scroll down, we can see the difference between the conic-gradient and the radial-gradient. The conic type is more suited to our needs since we're going to make use of this rotation to create our progressElement. The radial-gradient, on the other hand, provides the transition outward from the center, creating these rings which are not really much use for our circle. Let's start over in the index.html. Early on we added a wrapper for this section and then created a to-do section. Inside here I'm going to create two new divs. This first one is going to be the actual div for our circle. So I'm going to give this an ID of progressCircle. Then next inside I going to add a second div. This will have the ID of progressCenter. The reason for this section will become more clear very soon. First of all, we're going to target all this section which is down at the bottom, starting with our text. This is contained inside of the progress section. Let's save this and go to our styles.css. Right at the very bottom, we can begin by targeting the progress section. We can align the text into the center and also add some padding onto the very bottom. Next the text is contained in the level 3 heading. Let's target the progress h3, font size of 1.6 rems, and also this font weight, we're going to set this to be lighter. Next we can begin to work on our progressCircle. So we have the outer wrapper, which is progressCircleWrapper. We're going to grab this, set the flexbox, and then justify the content to be in the center. Back to our style sheet. Add this in. They can use all of the flexbox, so we can then justify our content into the center. This is going to place the circle once we create it into the middle of our section. Next up we have the progressCircle itself, which is going to have the conic-gradient. Back to our style sheet. This was an ID. To make this equal we can set the width. I want to go for 250 pixels and also a matching height. The example we'd seen before on the Mozilla website used a square section, just like we see here. But instead I'm going to turn this into a circle by adding a border-radius. A value of 50 percent will make this circular. Now we can make use of our conic-gradient by setting this as a background property. We did see lots of different values entered on the example before. But all we need is two different values. We just need the green values, which is the total number of miles the user has run and then the gray section for the rest of the circle. These are just going to be placeholder values for now, and we'll update these with JavaScript very soon. The green color is 70db70. Add any first value of 50 percent, means that this will run from zero right through to 50 percent. The second value is going to be a hex value of 2d3740. For the second value, if we set this to be 50 percent, if we don't add a second value such as 70, this will run right through to 100 percent. Now let's save this and go over to our project. Reload. This now places our conic-gradient into the full size of our circle. But if we take a look at the final version, we have the center circle just here, given as the appearance of a ring. This is the section which you've added into the middle of progressCenter. Let's grab this. All we're going to do is effectively use this as a mask covering up the center of the circle. This is going to be similar to just above, but we're going to make it a little smaller by setting the width to be 220. The same for the height. This will also need a border radius, so it's a circle. To also give this a appearance of a ring we need to make the background color the same as the rest of the app. The current value was 1c262f. Onto our project and let's see how this looks. We have the center of the circle now in place, but we just need to make sure this is centered. We can do this inside of our progressCircleWrapper. Let's set this with the display type of flex. Remember this is for the wrapper. We can then justify the content across the page into the center and also set the vertical alignment using align-items. Good. This now looks exactly how we want it to. Now let's go on to our script.js and we can create a function which is going to update this. Let's call this calcGoal. The first thing we need to do inside this function is to access our total value. This is the value just here. Once we have this, we can then divide this by our goal. The way we can grab this, just like above, we will grab the total value. Let's copy this. Paste this in, and this makes use of our reducer function to grab all of the items inside of our array and add them all together. The next step we need to take is to calculate a percentage between zero and 100. We're then going to use these values inside of our CSS to update our two colors. To convert this into a percentage, let's first grab the total value and then to get this as a percentage, we need to divide this by our goal divided by 100. We can then store this inside of a constant. Let's call this completedPercent. We can also do a console.log before we go any further and check this is all working fine. Lets add this into our log. We can also call this function from handle submit. Let's save this. Open up the developer tools with right-click and inspect into the console. Let's add a value of 10. This divided by our goal is going to give us a value of 40 percent. If we do 2.5, 10 plus 2.5 is equal to half of our goal, resulting in 50 percent. Now I have this value, we can now use this to update the styling of our progressCircle. Let's grab this by the ID of in the script. Back to calcGoal. We can remove the console.log and then call document.querySelector. The selector was an ID, so we pass the hash value in of progressCircle. Obvious inside of a constant call progressCircle. Now rather than having the conic-radiant hard-coded into here, we can now comment this out and then add this inside of JavaScript. The way to do this is to access our progressCircle elements. We can set any style property such as our background. We can once again set this equal to our conic-gradient. Let's copy the section, just like it is inside the styling, paste this in as a string inside of the quotations. These are still just hard-coded values. Let's try this out. Any values which we add inside of here will still result in a 50-50 split. Meaning our next step is to now make these two values more dynamic. The way we can do this, if we remove the quotations, can replace these with the backticks. These backticks are going to allow us to create a template string, which is a way of inserting variables into our regular text. We can remove our 50 percent. The way we insert a variable is to use the dollar symbol and then the curly braces. The first value is going to be the equivalent of our variable completed percent. Let's add this in. We also need the percent symbol, and then we need to update our second value. Again, this is going to be our completedPercent all the way through to 100 percent. Since this is our first value, this will go from zero right through to our completedPercent. Say this is 50 percent, it will go from zero to 50. The second value will then go from 50 right through to the end of our circle, which is 100 percent. Just before we update our progressCircle, we can add a conditional statement just above. We can add an if statement to check if the completed percent is more than 100. If it is, then we're just going to reset this back to 100. So our progressCircle always goes from 0-100. We can check if the completedPercent is greater than 100. If it is, we'll then reset this back to 100 percent. Let's try this out. 12.5, which is exactly half, our progressCircle is now 50-50. Insert a new value. Let's get it round to 100 percent. 22.5, we just need to add a value of 2.5. This now completes our circle. If we try to add a new value, we see that the progressCircle doesn't go any further. Since we received 100 percent of our target for that week, this is now all of the functionality now complete for our running tracker. Just to finish this off, we're going to add a media query just to restrict the maximum width of some of these elements. Back to our styles. Let's add a media query which is going to target our screens, alongside the minimum screen width of 800 pixels. So far, 800 pixel devices and above will restrict the body width to be equal to 60 percent. We can also restrict the width of this number input too. Still within the media query, the input with the type of number, all we need to do again is set width and this time of 40 percent. Finally, we can also reduce the size of this svg on the larger screens. Let's target the svg, setting the maximum width to be 50 percent. [inaudible] will still see there's lots of spacing above the top and bottom of this svg. The way to fix this, if we go to our index.html, is to go to our svg opening tag. Inside of this type, we can see we still have the width and the height set. We can remove these, allowing the sizing to be controlled with our style sheet. Save this and now svg now takes up less space. Congratulations for now reaching the end of this project, and I'll see you in the next one. 9. Follow Me On Skillshare!: A huge congratulations from me for reaching the end of this class. I hope you really enjoyed it and gain some knowledge from it. If you've enjoyed this class, make sure you check out the rest of my classes here on Skillshare, and also follow me for any updates and also to be informed of any new classes as they become available. So thank you once again, good luck, and hopefully I'll see you again in a future class.