CS Study/Projects

Project 13 : My Chrome

Ryannn 2022. 4. 15. 13:40

#기능

1. 실시간 시간 표시

2. Log-In을 수행하면 username을 로컬 스토리지에 저장하고 Hello (username) 표시

3. To-do list 표시

4. 현재 위치의 날씨 안내

5. 랜덤 명언 하단에 출력

6. 랜덤 배경화면 출력

#구현

<!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>Document</title>
    <style>
        @import url(style.css);
        @import url('https://fonts.googleapis.com/css2?family=Lora:ital@1&display=swap');
        @import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300&display=swap');
    </style>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100&family=Roboto:wght@400;700&display=swap" rel="stylesheet">
</head>
<body>
    <h2 id = "clock"></h2>
    <form class = "hidden" id = "login-form">
        <input required maxlength = "15" placeholder="What is your name?">
    </form>
    <h1 id = "greeting" class = "hidden"></h1>
    <form id = "todo-form">
        <input type = "text" required placeholder="Write a To do">
    </form>
    <ul id = "todo-list"></ul>
    <div id = "quotes">
        <span id = "quote"></span>
        <span id = "author"></span>
    </div>
    <div id = "weather">
        <span></span>
        <span></span>
    </div>
    <script src = "greeting.js"></script>
    <script src = "clock.js"></script>
    <script src = "quote.js"></script>
    <script src = "background.js"></script>
    <script src = "todo.js"></script>
    <script src = "weather.js"></script>
</body>
</html>
.hidden{
    display : none;
}

body{
    display : block;
    height: 100%;
    margin : 0;
    padding : 0;
}
#greeting,#clock{
    font-family: 'Open Sans', sans-serif;
}
input{
    background-color: transparent;
    border-color : transparent;
    border-bottom-color : white;
    height : 30px;
    width : 30%;
}
input:focus{
    outline : none;
    color : white;
    text-align: center;
    font-size: 24px;
}
input::placeholder{
    color : white;
    text-align: center;
    font-size: 24px;
}

#clock{
    display : flex;
    margin: 0;
    align-items: center;
    justify-content: center;
    height : 100vh;
    font-size: 96px;
    color : white;
}
#login-form{
    position : absolute;
    text-align : center;
    margin : 0;
    top : 55%;
    left : 20%;
    right : 20%;
    font-size : 48px;
    color : white;
    font-family: 'Roboto', sans-serif;
}
#greeting{
    position : absolute;
    text-align : center;
    margin : 0;
    top : 55%;
    left : 20%;
    right : 20%;
    font-size : 48px;
    color : white;
}
#todo-form{
    position : absolute;
    text-align: center;
    top : 62%;
    left : 20%;
    right : 20%;
    font-size : 48px;
    color : white;
    font-family: 'Roboto', sans-serif;
}
#todo-list{
    position : absolute;
    text-align: center;
    top : 70%;
    left : 20%;
    right : 20%;
    font-size : 24px;
    color : white;
}
#weather{
    position : absolute;
    top : 10px;
    right : 10px;
    text-align: center;
    font-family: 'Roboto', sans-serif;
    color : white;
}
#quotes{
    position : absolute;
    width : 100%;
    bottom : 20px;
    text-align: center;
    z-index: 10;
    color : white;
    font-family: 'Lora', serif;
}
#author{
    display : block;
}
button{
    background-color: transparent;
    border : none;
}
//로그인 후 사용자 환영 메시지 출력 기능

const loginForm = document.querySelector("#login-form");
const loginName = loginForm.querySelector("input");
const greeting = document.querySelector("#greeting");

const HIDDEN_CLASSNAME = "hidden";
const USERNAME_KEY = "username";

function onLoginSubmit(event){
    event.preventDefault();
    loginForm.classList.add(HIDDEN_CLASSNAME);
    const username = loginName.value;
    localStorage.setItem(USERNAME_KEY, username);
    paintGreeting(username);    
}

function paintGreeting(username){
    greeting.innerText = "Hello " + username;
    greeting.classList.remove(HIDDEN_CLASSNAME);
}
const savedUsername = localStorage.getItem(USERNAME_KEY);

if(savedUsername == null){
    loginForm.classList.remove(HIDDEN_CLASSNAME);
    loginForm.addEventListener("submit", onLoginSubmit);
}
else {
    paintGreeting(savedUsername);
}
//To-do list 입력 및 출력 기능

const todoForm = document.getElementById("todo-form");
const todoInput = todoForm.querySelector("input");
const todoList = document.getElementById("todo-list");

let todos = []; //todo 저장하는 배열

function todoSave(){ //todo localstorage에 저장(string)
    localStorage.setItem("todos",JSON.stringify(todos));
}

function todoDelete(event){ //todo 삭제하기
    const deleteLi = event.target.parentElement;
    deleteLi.remove();
    todos = todos.filter((todo) => todo.id != parseInt(deleteLi.id));
    todoSave();
}

function todoPaint(newTodoObj){ //리스트에 todo 삽입하기
    const li = document.createElement("li");
    li.id = newTodoObj.id;
    const span = document.createElement("span");
    span.innerText = newTodoObj.text;
    const button = document.createElement("button");
    button.innerText = "❌";
    button.addEventListener("click",todoDelete);
    li.appendChild(span);
    li.appendChild(button);
    todoList.appendChild(li); 
}

function todoSubmit(event){ //input 폼에서 엔터 눌렀을 때 기능
    event.preventDefault();
    const newTodo = todoInput.value;
    todoInput.value = "";
    const newTodoObj = {
        text : newTodo,
        id : Date.now()
    }
    todos.push(newTodoObj);
    todoPaint(newTodoObj);
    todoSave();
}

todoForm.addEventListener("submit", todoSubmit);

const savedTodos = localStorage.getItem("todos");
if(savedTodos){
    const parsedTodos = JSON.parse(savedTodos);
    todos = parsedTodos;
    parsedTodos.forEach(todoPaint);
}
//날씨 표시 기능

const API_KEYS = "c4e0733ed08482258c4ac8ebf689b078";


function geoOk(position){
    let lat = position.coords.latitude;
    let lon = position.coords.longitude;
    const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${API_KEYS}&units=metric`;
    fetch(url).then(response => response.json()).then(data =>{
        const weatherTag = document.querySelector("#weather span:first-child");
        const cityTag = document.querySelector("#weather span:last-child");
        weatherTag.innerText = data.weather[0].main + "/" + Math.floor(data.main.temp);
        cityTag.innerText = data.name;
    });
}
function geoError(){
    alert("We cannot find you!")
}

navigator.geolocation.getCurrentPosition(geoOk, geoError);
//초 단위 현재 시각 표시 기능

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

function getClock(){
    const date = new Date();
    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 + ":" + seconds;
}
getClock();
setInterval(getClock, 1000);
//랜덤 명언 출력 기능

const quotes = [
    {
      quote: "The way to get started is to quit talking and begin doing.",
      author: "Walt Disney",
    },
    {
      quote: "Life is what happens when you're busy making other plans.",
      author: "John Lennon",
    },
    {
      quote:
        "The world is a book and those who do not travel read only one page.",
      author: "Saint Augustine",
    },
    {
      quote: "Life is either a daring adventure or nothing at all.",
      author: "Helen Keller",
    },
    {
      quote: "To Travel is to Live",
      author: "Hans Christian Andersen",
    },
    {
      quote: "Only a life lived for others is a life worthwhile.",
      author: "Albert Einstein",
    },
    {
      quote: "You only live once, but if you do it right, once is enough.",
      author: "Mae West",
    },
    {
      quote: "Never go on trips with anyone you do ntot love.",
      author: "Hemmingway",
    },
    {
      quote: "We wander for distraction, but we travel for fulfilment.",
      author: "Hilaire Belloc",
    },
    {
      quote: "Travel expands the mind and fills the gap.",
      author: "Sheda Savage",
    },
  ];

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

const showQuotes = quotes[Math.floor(Math.random()*quotes.length)];
quote.innerText = showQuotes.quote;
author.innerText = showQuotes.author;
//랜덤 배경화면 출력 기능

const images = ["0.jpg", "1.jpg", "2.jpg"];
const randomImage = images[Math.floor(Math.random()*images.length)];
const body = document.querySelector("body");


const bgImage = document.createElement("img");
bgImage.src = randomImage;
bgImage.id = "bgImg";
body.appendChild(bgImage);
//bgImage 제어
bgImage.style.position = "absolute";
bgImage.style.width = "100%";
bgImage.style.height = "100%";
bgImage.style.top = "0";
bgImage.style.left = "0";
bgImage.style.zIndex = "-1";

 

이전 소규모 개인프로젝트를 진행할 때는 HTML, CSS, Javascript 파일 딱 3개만 만들어서 Javascript 파일에 모든 기능을 쑤셔넣으면서 코드 작성을 했었는데 그렇게 하니 제 머리 속으로 정리도 잘 안되고 복잡하더라구요..

그래서 제가 구현할 기능을 최대한 구분해본 뒤 그 기능에 따른 Javascript 파일을 각각 만들었습니다.

0.jpg
0.29MB
1.jpg
0.40MB
2.jpg
0.63MB