<!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>Sseul's_Momentum</title>
<link rel="stylesheet" href="./CSS/style.css" />
</head>
<body>
<form id="login-form" class="hidden">
<input
required
maxlength="15"
type="text"
placeholder="What is your name?"
/>
<input type="submit" value="Log In" />
</form>
<div class="main-box">
<div class="clockAndName">
<h2 id="clock">00:00</h2>
<h1 id="greeting" class="hidden"></h1>
</div>
<form id="todo-form">
<p>"What is your main focus for today??"</p>
<input type="text" required />
</form>
<ul id="todo-list"></ul>
</div>
<div id="quote"><span></span><br /><span></span></div>
<div id="weather"><span></span><span></span></div>
<script src="./JS/greetings.js"></script>
<script src="./JS/clock.js"></script>
<script src="./JS/quotes.js"></script>
<script src="./JS/background.js"></script>
<script src="./JS/todo.js"></script>
<script src="./JS/weather.js"></script>
</body>
</html>
* {
color: white;
}
/* 초기화 */
h1,
h2 {
margin: 0;
padding: 0;
}
ul,
li {
list-style: none;
}
button {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border: none;
background-color: transparent;
}
input {
width: 100%;
height: 100%;
text-align: center;
font-size: 20px;
outline: none;
border: none;
border-bottom: 1px solid white;
color: white;
background-color: transparent;
}
input::placeholder {
color: white;
}
/* 시작 */
.hidden {
display: none;
}
img {
size: 100%;
}
body {
height: 100vh;
background-repeat: no-repeat;
background-size: cover;
overflow: hidden;
text-align: center;
}
h2 {
font-size: 150px;
}
h1 {
font-size: 50px;
}
.main-box {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.clockAndName {
margin-bottom: 50px;
}
#todo-form p {
font-size: 30px;
}
#todo-list li span {
font-size: 20px;
}
#quote {
position: absolute;
bottom: 1%;
left: 50%;
transform: translate(-50%, -50%);
}
#weather {
text-align: right;
}
const bgImages = ["0.jpeg", "1.jpeg", "2.jpeg", "3.jpeg", "4.jpeg", "5.jpeg"];
const selectedImg = bgImages[Math.floor(Math.random() * bgImages.length)];
const bgImage = document.createElement("img");
const bgImageUrl = `Images/${selectedImg}`;
bgImage.classList.add("hidden");
bgImage.src = bgImageUrl;
document.body.style.backgroundImage = `url(${bgImageUrl})`;
document.body.appendChild(bgImage);
✍🏻 폴더 구조!
✍🏻 코드 설명
Images폴더 내 파일명과 const bgImages = ["0.jpeg", "1.jpeg", "2.jpeg", "3.jpeg", "4.jpeg", "5.jpeg"];
을 동일하게 배열을 만들어준다!
랜덤한 이미지를 불러오기에, selectedImg라는 변수를 생성해준다.
이미지가 html구조 내에 없기에 bgImage라는 변수를 생성하여 img태그를 createElement함!
Image들의 경로를 저장하는 bgImageUrl라는 변수 생성
bgImage.classList.add("hidden");
여기서 hidden 이라는 클래스를 생성해준 이유는 ?
document.body.style.backgroundImage =
url(${bgImageUrl});
js로 backgroundImage 스타일을 주었기에, 이미지가 2개이기에 원래 이미지는 hidden을 통해 가려줌
document.body.appendChild(bgImage);
를 통해 html에 생성!
✍🏻 이미지를 JS로 백그라운드 이미지 처리 하지 않았을 때 모습!
✍🏻 이미지를 JS로 백그라운드 이미지 처리 한 후!
const clock = document.querySelector("h2#clock");
function getClock() {
const date = new Date();
const hours = String(date.getHours()).padStart(2, "0");
const minutes = String(date.getMinutes()).padStart(2, "0");
clock.innerText = `${hours}:${minutes}`;
}
getClock();
setInterval(getClock, 1000);
✍🏻 코드 설명
setInterval(getClock, 1000)
은 1초에 한번씩 getClock함수를 호출하는 함수이다.const loginForm = document.querySelector("#login-form");
const loginInput = document.querySelector("#login-form 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 = loginInput.value;
localStorage.setItem(USERNAME_KEY, username);
paintGreetings(username);
}
loginForm.addEventListener("submit", onLoginSubmit);
function paintGreetings(username) {
greeting.innerText = `Hello ${username}`;
greeting.classList.remove(HIDDEN_CLASSNAME);
}
const savedUsername = localStorage.getItem(USERNAME_KEY);
if (savedUsername === null) {
//show the form
loginForm.classList.remove(HIDDEN_CLASSNAME);
loginForm.addEventListener("submit", onLoginSubmit);
} else {
//show the greeting
paintGreetings(savedUsername);
}
✍🏻 코드 설명
event.preventDefault();
을 사용한 이유는 ?loginForm.classList.add(HIDDEN_CLASSNAME);
을 해준 이뉴는?username
이라는 변수를 생성하여 저장함greeting.classList.remove(HIDDEN_CLASSNAME);
을 한 이유는?<h1 id="greeting" class="hidden"></h1>
hidden 클래스를 이용하여 h1태그를 생성하였기에, 로그인 전에는 #greeting 부분을 hidden으로 가려주고, 로그인 후에는 hidden이라는 클래스를 remove를 이용하여 지워줌!const quotes = [
{
quote: "신은 용기있는자를 결코 버리지 않는다",
author: "켄러",
},
{
quote: "어제와 똑같이 살면서 다른 미래를 기대하는 것은 정신병 초기증세다",
author: "아인슈타인",
},~~~
];
const quote = document.querySelector("#quote span:first-child");
const author = document.querySelector("#quote span:last-child");
const todayQuote = quotes[Math.floor(Math.random() * quotes.length)];
quote.innerText = todayQuote.quote;
author.innerText = todayQuote.author;
💡 코드 설명
const toDoForm = document.getElementById("todo-form");
const toDoInput = document.querySelector("#todo-form input");
const toDoList = document.getElementById("todo-list");
const TODOS_KEY = "todos";
let toDos = [];
function saveToDos() {
localStorage.setItem(TODOS_KEY, JSON.stringify(toDos));
}
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");
const button = document.createElement("button");
button.innerText = "❌";
button.addEventListener("click", deleteToDo);
li.appendChild(span);
li.appendChild(button);
span.innerText = newTodo.text;
toDoList.appendChild(li);
}
function handleToDoSubmit(event) {
event.preventDefault();
const newTodo = toDoInput.value;
toDoInput.value = "";
const newToDoObj = {
text: newTodo,
id: Date.now(),
};
toDos.push(newToDoObj);
paintToDo(newToDoObj);
saveToDos();
}
toDoForm.addEventListener("submit", handleToDoSubmit);
const savedToDos = localStorage.getItem(TODOS_KEY);
console.log(savedToDos);
if (savedToDos !== null) {
const parsedToDos = JSON.parse(savedToDos);
toDos = parsedToDos;
parsedToDos.forEach(paintToDo);
}
✍🏻 코드 설명
localStorage.setItem(TODOS_KEY, JSON.stringify(toDos))
이렇게 저장함parsedToDos.forEach(paintToDo);
forEach 통해 parsedToDos를 각각 paintToDo()함수를 이용하여 그려준다.const API_KEY = "*************************";
function onGeoOk(position) {
const lat = position.coords.latitude;
const lng = position.coords.longitude;
console.log("You live in", lat, lng);
const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lng}&appid=${API_KEY}&units=metric`;
fetch(url)
.then((response) => response.json())
.then((data) => {
const weather = document.querySelector("#weather span:first-child");
const city = document.querySelector("#weather span:last-child");
city.innerText = data.name;
weather.innerText = `${data.weather[0].main} / ${data.main.temp}`;
});
}
function onGeoError() {
alert("X");
}
navigator.geolocation.getCurrentPosition(onGeoOk, onGeoError);
✍🏻 코드 설명
👏🏻 왼쪽 : mometun vs 오른쪽 : 직접구현!