Javascript - Momentum project

한윤서·2021년 11월 5일
0

Web

목록 보기
1/6

1. Objective

To clone code the Momentum page in able to learn the basic concepts of javasciprt

2. Structure

The following page is composed of mainly 6 sections :

  • Greetings section : Input the username and store it in storage. Then show the greetings comment : Hello "username"
  • Clock section : Show the current time in the main page. Important to keep the format (ex : show 9:05 not 9:5 for numbers less than 10)
  • Quotes section : Show a motivational quote on the bottom of the screen. Quote must change for every refresh of page
  • Background section : Show background image. Must also change for every refresh of page
  • To do section : Input daily goal for user. Page shows the list of goals down the page.
  • Weather section : Show the current weather of position in page

3. HTML structure

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Momentum</title>
    <link rel="stylesheet" href="css/style.css">
    <script defer src="js/greetings.js"></script>
    <script defer src="js/clock.js"></script>
    <script defer src="js/quotes.js"></script>
    <script defer src="js/background.js"></script>
    <script defer src="js/todo.js"></script>
    <script defer src="js/weather.js"></script>
</head>
<body>
    <div class="cover">
        <div id="weather">
            <span></span>
            <span></span>
        </div>
        <h2 id="clock">00:00:00</h2>
        <form class="login-form hidden">
            <input 
            required
            maxlength = "15"
            type="text" 
            placeholder="What is your name?">
            <button>Log In</button>
        </form>
        <h1 id="greeting" class="hidden"></h1>

        <form action="" id="todo-form">
            <input type="text" placeholder="Write a To do and Press Enter" required>
        </form>
        <ul id="todo-list"></ul>

        <a href="https://www.google.com"> Go to Homepage</a>
        <div id="quote">
            <span></span> <br>
            <span></span>
        </div>
        
    </div>
</body>
</html>

4. Greetings section

Variables defined

const loginForm = document.querySelector(".login-form");
const loginInput = loginForm.querySelector("input");
const loginButton = loginForm.querySelector("button");

const link = document.querySelector("a");

const greeting = document.querySelector("#greeting");

//HIDDEN_CLASSNAME variable is used as a class name that is used in the CSS styling of display : none;
const HIDDEN_CLASSNAME = "hidden";
const USERNAME_KEY = "username";

document.querySelector allows to select the html tags using the selectors

Initially, the page would want to input the username so that the greeting quote will be shown. After the user inputs the name, the page should store the name into the local storage(temporary storage on web) to show the name everytime the user opens the webpage again, without needing to type their username again

//Want to make the program to remember username once username is typed
//If there is no username stored, show the input form
const savedUsername = localStorage.getItem(USERNAME_KEY);

if(savedUsername == null) {
    //No saved username : show input form
    loginForm.classList.remove(HIDDEN_CLASSNAME);
    loginForm.addEventListener("submit", onLoginSubmit);
} else{
    //Saved username exist : show greeting
    paintGreetings();
}
  • Use const savedUsername = localStorage.getItem(USERNAME_KEY); to be able to find a variable in the local storage with name "username"
  • If there is nothing on the savedUsername, You would have to show the input form on the page
  • The html tag for the form initially had a class name of "hidden"
  • This "hidden" class has css styling of display : none;, Therefore form is not shown on webpage by default
  • However the loginForm.classList.remove(HIDDEN_CLASSNAME); removes the class name of the input value from the selected loginForm object
  • The loginForm.addEventListener("submit", onLoginSubmit); allows the onLoginSubmit() function to activate once the user submits the input on the form to deal with the information
  • Else when ther is a username stored in the local storage, the page would just have to paint the greetings string using paintGreetings();

onLoginSubmit() function :

//Have to stop refresh when submit happens(refresh is default behavior of HTML)
function onLoginSubmit(event) {
    //Prevent the default value(page refresh) of browser by using function 
    //event argument is normally automatically passed by JS. 
    //IT represents the current events that the brwoser executes autoamtically
    event.preventDefault();
    const username = loginInput.value;
    //Hide login form after input is submitted
    loginForm.classList.add(HIDDEN_CLASSNAME);
    //Use web API to store values in local storage
    //The first argument represents the name of the variable, 
    //and second argument is the value of variable
    localStorage.setItem(USERNAME_KEY, username);
    paintGreetings();
}
  • There are some default behaviors that the web page does due to the properties.
  • This is due to when function being passed, JS will automatically input an argument of the function that explains the information of current event that helps to activate function
  • Ex) For example events such as when user submits information, or when clicks using a mouse : Info related to the following events are also passed
  • Therefore during the following code loginForm.addEventListener("submit", onLoginSubmit); will pass the default behavior of submit event and cause the webpage to automatically refresh
  • Therefore the event.preventDefault() would be able to prevent the default value(page refresh) of browser to activate
  • The login form is disapeared by inserting the class name "hidden" to login form tag again using loginForm.classList.add(HIDDEN_CLASSNAME);
  • Store variables in the local storage using localStorage.setItem(USERNAME_KEY, username);
    First argument : Name of variable,
    Second arguemtn : Value of variable

paintGreetings() function :

function paintGreetings() {
    const username = localStorage.getItem("username");
    greeting.innerText = `Hello ${username}`;
    greeting.classList.remove(HIDDEN_CLASSNAME);
}
  • Get the value stored in the local storage and print the value
  • Backticks allow the combination of strings and variables : 'string ${variable}' format

5. Clock section

Objective : To show current time in correct format

Code :

const clock = document.querySelector("h2#clock");

function getClock() {
    const date = new Date();
    //.padStart() converts the string object to fit the number of letters to the 1st number input with the string in 2nd argument, infront of the string
    //Only applies to string therefore has to convert string to integer
    const hours = String(date.getHours()).padStart(2,"0");
    const minutes = String(date.getMinutes()).padStart(2,"0");
    const seconds = String(date.getSeconds()).padStart(2,"0");
    clock.innerText = `${hours}:${minutes}`;
}

getClock();
setInterval(getClock, 1000);
  • setInterval(getClock, 1000); : Function that repeats the function in first argument for a certain amount of interval, specified in the 2nd interval
  • The getClock(); is immediately called vefore the setInterval function to directly show the timde when page is refreshed (without delay)
  • Date() gives the functions that is related to current time : Can bet using functions such as .getHours()
  • const hours = String(date.getHours()).padStart(2,"0"); : .padStart() converts string object to fit the number of letters to the 1st argument, and fills the left blank space ith the 2nd argument input
  • String() converts a int variable to string

6. Quotes section

Objective : Store several quotes in array in form of object. Then show a different quote whenever page is refreshed

Code :

//Aray of objects. Each object has 2 string variables, (1 storing quotes, 1 stroing author)
const quotes = [
    {
        quote : "Your time is limited, so don't waste it living someone else's life. ",
        author : "Steve Jobs"
    },
    {
        quote : "Life is what happens when you're busy making other plans.",
        author : "John Lenon"
    },
    {
        quote : "Stay hungry, stary foolish",
        author : "Steve Jobs"
    },
    {
        quote : "Just do it",
        author : "Nike"
    }
];

const quote = document.querySelector("#quote span:first-child");
const author = document.querySelector("#quote span:last-child");

//To generate a random number between 0~3 : Math.floor((Math.random()*10)%quotes.length())

const todaysQuote = quotes[Math.floor((Math.random()*10)%quotes.length)];

quote.textContent = todaysQuote.quote;
author.textContent = todaysQuote.author;
  • Array stores objects and each object consists of the quote text and author info (both string variable)
  • Math.floor() : Truncates a decimal to its lower integer
  • Math.random() : Generates a random number between 0~1
  • Math.floor((Math.random()*10)%quotes.length) : Generates a random number between 0~(# of objects in array)
  • The random number generated is the input number of array index. The selected quote is stored in todaysQuote and it is shown in the screen

(!) 7. Background section

const images = ["background.jpeg", "hkust.jpg", "stanford_ms.jpg"];

const chosenImage = images[Math.floor(Math.random() * images.length)];

//Inset html img tag using JS

//create tag using createElement function
const bgImage = document.createElement("img");
bgImage.src = `img/${chosenImage}`;

//Add the made tag into html page
document.body.appendChild(bgImage);
  • The images array stores several images.
  • chosenImage randomly selects an image and stores
  • document.createElement() creates a HTML tag and gives the tag name following of the input
  • The source of the <img> tag is added
  • Finally to add the tag into the html page, use document.body.appendChild(bgImage);
  • However the following is only adding a image to the page but not setting it as the background image therefore might be inappropriate therefore require another way

8. To Do's section

Objective : To input the things to do from user and show it in a list form. Also enable to delete the to do list when clicking the X button

Variables defined :

const toDoForm = document.getElementById("todo-form");
const toDoInput = document.querySelector("#todo-form input");
const toDoList = document.getElementById("todo-list");

let toDos =[];
let idNum=0;

const TODOS_KEY = "todos";
  • The form, content of input, list is selected
  • The array to store list of to do's is defined in form of "let": Must update array when there is input -> save values in array to keep original elements when new element is pushed
  • TODOS_KEY is used to store a string that is used several times("todos") : This is for easy debugging

General flow of to do's section :

toDoForm.addEventListener("submit", handleToDoSubmit); 

const savedToDos = localStorage.getItem(TODOS_KEY);

//To keep show the typed to dos on screen
if(savedToDos) {
    const parsedToDos = JSON.parse(savedToDos);
    //Update the to dos array so that the original values are stored
    //When web detects more submit, it pushes elements to the updated array
    toDos = parsedToDos;
    //For simple functions, we can use arrow function to simplify code
    //Use the paintToDo function already made to paint the to do list on screen
    parsedToDos.forEach(paintToDo);
}
  • When there is an input and the user submits the input, move to function handleToDoSubmit; : To add the input to the storing array
  • Check the local storage to see if there is any to do list stored using localStorage.getItem(TODOS_KEY); and store it in variable
  • Note that local storage can only save strings and therefore the input array is stored in a string type : ex) "[a,b,c]" is stored
  • If there is stored todos, we transfer the stored string back to array again using parse() in JSON
  • toDos array is updated every time the user submits another to dos in the page. It is updated by the to dos saved in the local storage
  • JS allows you to execute function for each element in array using the function .forEach -> It passes the info of the element of array to the function and prints the stored to dos
function handleToDoSubmit(event) {
    event.preventDefault(); 
    const newToDo = toDoInput.value;
    toDoInput.value = ""; 
    //Push the input to do to the storing array
    //Also push the id of the to do input
    //Array stores objects!!
    const newToDoObj = {
        text: newToDo,
        id: idNum++,
    };
    toDos.push(newToDoObj);
    paintToDo(newToDoObj);
    saveToDos();
}
  • The following function handles the input data of the form when user submits it
  • First prevent the default behaviour (:refresh page) by using preventDefault()
  • Then make an object and store 2 strings regarding the quote : quote content and author
  • Push the object to the storing array
  • Create a list of the following newly added to do using paintToDo() function
  • Save the new to do list on local storage using saveToDos()
//Create a list of todos
function paintToDo(newToDo) {
    //Create li , span and button tag 
    const li = document.createElement("li");
    //Add ID to the li tag on HTML (give id of the element array's id)
    li.id = newToDo.id;
    const span = document.createElement("span");
    const button = document.createElement("button");
    //Add content of button and span
    span.innerText = newToDo.text;
    button.innerText = "❌";
    //Check if button is clicked
    button.addEventListener("click", deleteToDo);
    //Put span tag inside of li tag
    li.appendChild(span);
    li.appendChild(button);
    //Put the whole list tag inside todo-list
    toDoList.appendChild(li);
}
  • The following function normally makes a HTML tag regarding the list. Therefore the list of to dos will be shown in the web page
  • Create a list and assign an id by using the id variable defined.
  • li is consisted of a span for text and delete button
  • If button is clicked, the event listener listens to the act and activates the deleteToDo() function
function deleteToDo(event) {
    //Now each button is linked to its parent element : list, and therefore differentiated with other buttons
    const li = event.target.parentElement;
    //filter() function passes each element of the array to the function inside filter()
    toDos = toDos.filter((element)=> element.id!==parseInt(li.id));
    //Call saveToDos once more to update the local storage
    saveToDos();
    li.remove();
}
  • Function enables the list connected to certain button disapear when the button is clicked
  • The event argument fives info about the click : ex) which button was clicked
  • event.target.parentElement links the button to its parent element : <li> tag that covers the clicked button
  • For array, we do not delete elements directly in the array : We create a new array and add the elements except the element that has to be deleted, and then update the toDos array to the temporary array
  • .filter() function passes each element of the array to the function inside filter
  • The function toDos = toDos.filter((element)=> element.id!==parseInt(li.id)); is an arrow function : The passed element of the array returns the element only if the id of the element is not equal to the selected buttons id
  • Call the saveToDos() to update the to do list on local storage
function saveToDos() {
    localStorage.setItem(TODOS_KEY, JSON.stringify(toDos));
}
  • Local storage can only save strings therefore without stringify, the input automatically is converted to individual strings : ex) a,b,c stored individually
  • With stringify, the whold array, including [] will turn into a whole string: ex) [a,b,c] stored in storage
  • Therefore will store the following array as a string in storage -> ex) ["a","b","c"]

9. Weather section

Objective : Use the weather API to get the current location and weather and show it in screen

const API_KEY = "93b01e7d4f2378f6c818a5dc686539c9";

function onGeoSuccess(position) {
    const lat = position.coords.latitude;
    const long = position.coords.longitude;
    const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${long}&appid=${API_KEY}&units=metric`;
    //Using fetch, you do not have to go to url, but js will call url
    fetch(url)
        .then(response => response.json())
        .then(data => {
            const weatherContainer = document.querySelector("#weather span:first-child");
            const cityContainer = document.querySelector("#weather span:last-child");      
            cityContainer.textContent = data.name;
            weatherContainer.textContent =  `${data.weather[0].main} / ${data.main.temp}`;
        });
}

function onGeoError() {
    alert("Cant find position");
}

//First argument : function called when can get position, Second : function called when can't get current position
navigator.geolocation.getCurrentPosition(onGeoSuccess, onGeoError);
  • position.coords.latitude and position.coords.longitude each return the current location of the user using coordinates
  • The URL represents the API that can be used to get the info about current location : ex) city, weather etc.
  • Using the fetch(), the URL can be brought to the webpage without needing to access : Info can be brought

10. Result

profile
future eo

0개의 댓글