Momentum

2022. 4. 25. 18:09Study/JavaScript

바닐라 JS로 브라우저 크롬의 확장 프로그램인 Momentum을 구현하는 프로젝트

https://aluvy.github.io/www/momentum/

 

Momentum

Momentum 00:00:00

aluvy.github.io

 

local storage를 활용한 로그인, to do list 구현과

Math.random()을 활용한 랜덤 background 및 명언 출력

setInterval을 활용한 시계, openweathermap 을 활용한 날씨 API 등

 

 

index.html

헤더에 아이콘 사용을 위해서 폰트어썸 코드를 입력했다.

<!DOCTYPE html>
<html lang="ko">
<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>
    <script src="https://kit.fontawesome.com/cdd59ed73b.js" crossorigin="anonymous"></script>
    <link rel="stylesheet" href="./css/style.css">
</head>
<body>
    <div class="wrap">
        <h1 class="hidden">Momentum</h1>
        <article class="container">
            <div class="clock">00:00:00</div>
            
            <div class="greeting_wrap">
                <form class="form-wrap hidden">
                    <input type="text" placeholder="What is your name?" required maxlength="15">
                    <button type="submit"><i class="fa-solid fa-unlock-keyhole"></i></button>
                </form>
                <h1 class="greeting hidden"></h1>
            </div>

            <div class="todo_wrap">
                <form class="todo-form">
                    <input type="text" placeholder="Write a To Do and Press Enter" required>
                </form>
                <ul class="todo-list"></ul>
            </div>

        </article>
        
        <div class="quote">
            <span></span>
            <span></span>
        </div>
        
        <div class="weather">
            <i class="fa-solid"></i>
            <span></span>
            <span></span>
            <p></p>
        </div>
    </div>

    <script src="./js/greeting.js"></script>
    <script src="./js/clocks.js"></script>
    <script src="./js/quote.js"></script>
    <script src="./js/background.js"></script>
    <script src="./js/todo.js"></script>
    <script src="./js/weather.js"></script>

</body>
</html>

 

js/greeting.js

로그인 전을 위한 .form-wrap 영역과

로그인 후를 위한 .greeting 영역으로 분리되어 있다.

username은 local storage에 저장되어, 페이지 새로고침 시에도 로그인 정보가 유지된다.

const formWrap = document.querySelector(".form-wrap");
const formWrapInput = formWrap.querySelector("input");
const formWrapButton = formWrap.querySelector("button");

const greeting = document.querySelector(".greeting");
const USERNAME = localStorage.getItem("username");

if(USERNAME == null){   // username이 비어있으면
    formWrap.classList.remove("hidden");
    formWrap.addEventListener("submit", HandlerFormSubmit);
    formWrapInput.value = "";
} else {    // username이 있으면
    PrintGreeting(USERNAME);
}

function HandlerFormSubmit(event){
    event.preventDefault();

    const username = formWrapInput.value;
    localStorage.setItem("username", username);
    formWrap.classList.add("hidden");

    PrintGreeting(username);
}

function PrintGreeting(username){
    greeting.classList.remove("hidden");
    greeting.innerHTML = `Hello <i class="fa-solid fa-face-smile"></i> ${username}!`;
}

 

js/clock.js

setInterval을 활용하여, 1초 단위로 흘러가는 디지털 시계를 구현했다.

padStart() 함수를 이용해 시계 숫자의 자리수를 맞춰줬다.

padStart()를 사용하기 위해 시,분,초를 문자처리 해줬다. String()

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

function setClock(){
    const date = new Date();
    const Hours = String(date.getHours()).padStart(2, "0");
    const Menutes = String(date.getMinutes()).padStart(2, "0");
    const seconds = String(date.getSeconds()).padStart(2, "0");

    clock.innerHTML=`${Hours}:${Menutes}:${seconds}`;
}

setClock();
setInterval(setClock, 1000);

 

js/quotes.js

Math.Floor()와 Math.random(), array.length를 이용해 원하는 범위 내의 랜덤 숫자를 얻고, 이를 활용해 랜덤으로 글귀를 노출한다.

const quotes = [
    {
    quote: 'I never dreamed about success, I worked for it',
    author: 'Estee Lauder'
    },
    {
    quote: 'Do not try to be original, just try to be good.',
    author: 'Paul Rand'
    },
    {
    quote: 'Do not be afraid to give up the good to go for the great',
    author: 'John D. Rockefeller'
    },
    {
    quote: 'If you cannot fly then run. If you cannot run, then walk. And if you cannot walk, then crawl, but whatever you do, you have to keep moving forward.',
    author: 'Martin Luther King Jr.'
    },
    {
    quote: 'Our greatest weakness lies in giving up. The most certain way to succeed is always to try just one more time.',
    author: 'Thomas Edison'
    },
    {
    quote: 'The fastest way to change yourself is to hang out with people who are already the way you want to be',
    author: 'REid Hoffman'
    },
    {
    quote: 'Money is like gasoline during a road trip. You do not want to run out of gas on your trip, but you are not doing a tour of gas stations',
    author: 'Tim O Reilly'
    },
    {
    quote: 'Some people dream of success, while other people get up every morning and make it happen',
    author: 'Wayne Huizenga'
    },
    {
    quote: 'The only thing worse than starting something and falling.. is not starting something',
    author: 'SEth Godin'
    },
    {
    quote: 'If you really want to do something, you will find a way. If you do not, you will find an excuse.',
    author: 'Jim Rohn'
    },
];

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

const quoteSelect = quotes[Math.floor(Math.random() * quotes.length)];

quote.innerHTML = quoteSelect.quote;
author.innerHTML = quoteSelect.author;

 

js/background.js

랜덤으로 배경화면 주소를 얻어온다.

const BackgroundImages = [
    "0.jpg",
    "1.jpg",
    "2.jpg",
    "3.jpg",
    "4.jpg",
    "5.jpg",
    "6.jpg",
    "7.jpg"
];

const wrap = document.querySelector(".wrap");

const SelectImage = BackgroundImages[Math.floor(Math.random()*BackgroundImages.length)];
wrap.style.backgroundImage = `url(./img/${SelectImage})`;

 

js/todo.js

local storage와 배열을 활용한 to do list

Date.now()함수를 이용해 겹치지 않는 id값과 함께 to do list text를 로컬스토리지에 저장한다.

로컬스토리지에 컨텐츠가 배열 형태로 저장되지 않아 JSON.stringify(toDos) 를 활용해 '배열 모양으로' 저장한다.

로컬스토리지에 배열'모양'의 string 형태로 저장된 컨텐츠를 JSON.parse(savedToDos)를 이용해 실제 배열로 불러와 프린트해준다.

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

const TODOS_KEY = "todos";

let toDos = [];

function saveToDos(){
    localStorage.setItem(TODOS_KEY, JSON.stringify(toDos));
    // JSON.stringify()를 이용해 배열 문자 형태로 localStorage에 저장
}

function deleteToDo(event){
    const li = event.target.parentElement;
    li.remove();
    toDos = toDos.filter(toDo => toDo.id !== parseInt(li.id));
    saveToDos();
}

function paintToDo(newTodo){
    const li = document.createElement("li");
    li.id = newTodo.id;
    const span = document.createElement("span");
    li.appendChild(span);
    span.innerText = newTodo.text;

    const button = document.createElement("button");
    button.type ="button";
    button.innerText = "❎";
    li.appendChild(button);
    button.addEventListener("click", deleteToDo);

    toDoList.appendChild(li); 
}

function handleToDoSubmit(event){
    event.preventDefault();
    const newTodo = toDoInput.value;
    toDoInput.value = "";

    const newTodoObj = {
        id : Date.now(),
        text : newTodo,
    };

    console.log(toDos.length);
    if(toDos.length < 7){
        toDos.push(newTodoObj);    // toDos Array에 Push
        paintToDo(newTodoObj);
        saveToDos();
    } else {
        alert("You can only enter up to 7.");
    }
}

toDoForm.addEventListener("submit", handleToDoSubmit);


const savedToDos = localStorage.getItem(TODOS_KEY);

if(savedToDos){ // savedToDos가 없으면 null이 반환된다.(false) 있으면 true
    const parsedToDos = JSON.parse(savedToDos); // 문자형태인 savedToDos를 array 형태로 반환
    toDos = parsedToDos;
    parsedToDos.forEach((item) => paintToDo(item));
    // parsedToDos.forEach(paintTodo);
}

 

js/weather.js

https://api.openweathermap.org/

API를 사용하여 간단하게 날씨 정보를 출력할 수 있다.

const weatherIcon = {
    "01": "fa-sun",    // clear sky
    "02": "fa-cloud-sun",  // few clouds
    "03": "fa-cloud",  // scattered clouds
    "04": "fa-cloud-meatball", // broken clouds
    "09": "fa-cloud-rain", // shower rain
    "10": "fa-cloud-showers-heavy", // rain
    "11": "fa-cloud-bolt", // thunderstorm
    "13": "fa-snowflake", // snow
    "50": "fa-water", // mist
};

const API_KEY = "ab25b9205ac4992cdb13d1409a98f3d6";

function onGeoOk(position){
    const lat = position.coords.latitude;
    const lon = position.coords.longitude;

    const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${API_KEY}&units=metric`;
    // console.log(url);
    fetch(url).then(response => response.json()).then(data =>{
        // const weatherWrap = document.querySelector(".weather");
        const icon = document.querySelector(".weather i");
        const temp = document.querySelector(".weather span:nth-of-type(1)");
        const weather = document.querySelector(".weather span:nth-of-type(2)");
        const city = document.querySelector(".weather p");

        const iconNum = (data.weather[0].icon).substr(0,2); // icon번호
        const iconEmoji = weatherIcon[iconNum]; // 배열에서 fontawsome class 받아오기
        icon.classList.add(iconEmoji)   // 해당 클래스 +

        temp.innerText = `${Math.floor(data.main.temp)}℃`;
        weather.innerText = `${data.weather[0].main}`;
        city.innerText = data.name;
    });

    // http://openweathermap.org/img/w/10d.png
}

function onGeoError(){
    alert("Can't find you. No weather for you.");
}

navigator.geolocation.getCurrentPosition(onGeoOk, onGeoError);
 

 

momentum.zip
10.21MB

 

 

'Study > JavaScript' 카테고리의 다른 글

Timer 타이머  (0) 2022.05.18
ES6 배열 내장 함수  (0) 2022.04.26
React JS  (0) 2022.04.15
Vue JS  (1) 2022.04.08
Angular JS  (0) 2022.04.06