자바스크립트 예제

js 예제: clock - todo_list_날씨받기

자무카 2022. 11. 6.

js 예제: clock - todo_list_날씨받기

노마드 코더 자바스크립트 입문 강의에 찬사를 보낸다.

정말 이 강의는 구성이 천재적이다.

딥다이브 ES6 까지 완료 후, 처음부터 2회독을 시작할까? 고민이 있었다. Array ~ DOM ~ 등은, 비동기 setTime, 콜백, fetch, promise, async 등은 실용적인 쉬운 예제들로 학습하기로 계획을 바꿨는데, 휴 다행이였다.

  1. 특히, 간단한 예제를 하면서, html css 를 지금껏 기초도 모른채 사용했다는 생각에, 주요 css 도 들여다보며, 연습하는 계기가 됐다.
  2. 여러 예제 중, 이론적으로는 생활코딩의 비동기 강의가 좋았고,
  3. 노마드코더의 바닐라 자바스크립트 강의.
    이런 강의가 무료라니. 헐. 영어에 자막이라는 부분이 거부감이 있었으나, 오히려 코드에 더 집중하는 결과? ^^ 유튜브 풀스택 유료 강의 코스가 있길래, 잠깐 후기를 봤더니 ... 음 의외로 후기가 ... 흠. 그래서, 다음 코스는 좀 더 검토해보기
  4. 대부분의 사람들이 하는 html, css, javascript 코스를 탔어야 했는데, 어설프게 아는 것도 아니면서, 백엔드만 겉핥기로 이것저것 떠들어본 세월이 원망스럽다. 슬프고 슬프다. 뭐... 이제라도.. 다행이긴 하다.
  5. html 과 css 가 간단하지만, 이렇게 중요할 줄은 몰랐다. 그냥 불필요한 효과라고 생각했는데, 오히려 백엔드 언어에서 제공하는 방법들이 굉장히 돌아가는 길이고, 협소하고, 잘 쓰이지 않는 방법들이였다. ㅠㅠ

이를 계기로,

  • 간단한 js 예제는 몰아치기보다, 예제 중심으로 건건이 유튜브 공개 영상 위주로 연습.
  • 리액트, 노드js 시작.

index.html

<!DOCTYPE html>
<html>
    <head>
        <title>Make a better day</title>
        <link rel="stylesheet" href="index.css"/>
        <meta charset="utf-8"/>
    </head>
    <body>
        <span class='js-temp'></span>
        <span class='js-place'></span>

        <div class="js-clock">
            <h1>00:00</h1>
        </div>
        <h4 class="js-greetings greetings"></h4>

        <h5>Write down things to do today</h5>

        <form class="js-form form">
            <input type='text' placeholder="What is your name?"/>
        </form>

        <form class="js-toDoForm">
            <input type="text" placeholder=""/>
        </form>
        <ul class="js-toDoList">
        </ul>

        <script src="clock.js"></script>
        <script src="greeting.js"></script>
        <script src="todo.js"></script>
        <script src="bg.js"></script>
        <script src="weather.js"></script>
    </body>
</html>

index.css

body{
    background-color: #2d3436;
    text-align: center;
    color: #ecf0f1;
    padding: 1%;
}

h1{
    font-size: 112px;
    margin-top:13%;
    margin-bottom: 0px;
}

h5{
    font-weight: 100;
    font-size: 22px;
    margin-bottom: 10px;
}

input {
    border: none;
    background: transparent;
    font-size: 22px;
    margin: 3px;
    text-align:center;
    color: #ecf0f1;
    border-bottom: 2px solid #ecf0f1;
}

ul {
    margin-left: 40%;
}

li{
    list-style: none;
    font-size: 20px;
    text-align:left;
    color: #ecf0f1;
}
li:before{
    content:'🤍';
    display: inline;
    vertical-align: left;
    padding: 5px;
}

button{
    border: none;
    background: transparent;
    font-size: 22px;
}

.form,
.greetings {
    display: none;
}

.showing{
    display: block;
    transition: color .5s ease-in-out;
    font-size: 34px;
    margin-top: 0px;
}

.bgImg{
    position: absolute;
    top:0;
    left: 0;
    width:100%;
    height: 100%;
    z-index: -1;
    animation: fadeIn 0.5s linear;
}

.js-temp{
    font-weight: 500;
    font-size: 22px;
    padding-left: 95%;
}

.js-place{
    font-weight: 300;
    font-size: 12px;
    padding-left: 95%;
}

@keyframes fadeIn{
    from {
        opacity: 0;
    }
    to{
        opacity : 1;
    }
}

clock.js

// js-clock class의 h1 가져오기
const clockContainer = document.querySelector(".js-clock");
const clockTitle = clockContainer.querySelector("h1");

// 시간을 받아서 h1의 innerText에 업데이트
function getTime() {
    const date = new Date();
    const minutes = date.getMinutes();
    const hours = date.getHours();
    const seconds = date.getSeconds();
    clockTitle.innerText = `${hours<10?`0${hours}`:hours}:${minutes<10? `0${minutes}`:minutes}:${seconds < 10 ? `0${seconds}` : seconds}`;
}

// 1초마다 getTime()실행
function init () {
    getTime();
    setInterval(getTime, 1000);
}

init()

greeting.js

// js-form의 input과 js-greetings 가져오기
const form = document.querySelector(".js-form"),
    input = form.querySelector("input"),
    greeting = document.querySelector(".js-greetings");

const USER_LS = "currentUser",
    SHOWING_CN = "showing";

// 이름을 로걸저장소에 저장
function saveName(text){
    localStorage.setItem(USER_LS, text);
}

// 제출을 누르면 해당 값(이름)을 출력하고 저장
function handleSubmit(event){
    event.preventDefault();
    const currentValue = input.value;
    paintGreeting(currentValue);
    saveName(currentValue);
}

// js-form이 보이게 해서 이름 물어보기
function askForName() {
    form.classList.add(SHOWING_CN);
    form.addEventListener("submit", handleSubmit);
}

// 이름 보여주기
function paintGreeting(text) {
    // 이름 물어보는거 안보이게 하기
    form.classList.remove(SHOWING_CN);
    // js-greeting 보이게 하기
    greeting.classList.add(SHOWING_CN);
    // 시간 받아오기
    const date = new Date();
    const hours = date.getHours();
    let mention = 'Hello';
    if(0<= hours && hours <= 4 || 20 < hours){
        // 시간이 0시~4시 이거나 20시 넘으면 굿나잇
        mention = 'Good night';
    } else if (hours<12){
        // 시간이 5시~12시이면 굿모닝
        mention = 'Good morning';
    } else{
        // 13시부터 20시까지는 굿애프터눈
        mention = 'Good afternoon';
    }
    // js-greeting에 innerText 넣어주기
    greeting.innerText = `${mention}, ${text}.`;
}

// 이름 불러오기
function loadName() {
    const currentUser = localStorage.getItem(USER_LS);
    // 저장된 이름이 없으면 물어보기
    if(currentUser === null){
        askForName();
    }else{
        // 저장된 이름이 있으면 출력하기
        paintGreeting(currentUser);
    }
}
function init() {
    loadName();
}

init();

todo.js

// document에서 html 태그로 js-toDoForm의 input과 js-toDoList 가져오기
const toDoForm = document.querySelector(".js-toDoForm"),
    toDoInput = toDoForm.querySelector("input"),
    toDoList = document.querySelector(".js-toDoList");

// toDo list
const TODOS_LS = 'toDos';

// toDo를 추가 삭제 해줘야 하기때문에 let으로 선언
let toDos = [];

// todo 삭제하기
function deleteToDo(event){
    const btn = event.target;
    const li = btn.parentNode;
    toDoList.removeChild(li);
    const cleanToDos = toDos.filter(function(toDo){
        return toDo.id !== parseInt(li.id);
    });
    toDos = cleanToDos;
    saveToDos();
}

// todo localStorage에 저장하기
function saveToDos(){
    localStorage.setItem(TODOS_LS, JSON.stringify(toDos));
}

// localStorage 에서 todo 불러오기
function loadToDos(){
    const toDosLoaded = localStorage.getItem(TODOS_LS);
    if(toDosLoaded !== null){
        const parsedToDos = JSON.parse(toDosLoaded);
        parsedToDos.forEach(function(toDo) {
            paintToDo(toDo.text);
        });
    }
}

// todo list 생성 및 출력하기
function paintToDo(text){
    const li = document.createElement("li");
    const delBtn = document.createElement("button");
    delBtn.innerHTML = "❌";
    delBtn.addEventListener("click", deleteToDo);
    const span = document.createElement("span");
    const newid = toDos.length +1;
    li.id = newid;
    span.innerText = text;
    li.appendChild(span);
    li.appendChild(delBtn);
    toDoList.appendChild(li);

    const toDoObj = {
        text: text,
        id: newid
    };
    toDos.push(toDoObj);
    saveToDos();
}

// toDoForm 을 제출하면, 값을 받아와서 리스트로 만들기
function handleSubmit(event){
    event.preventDefault();
    const currentValue = toDoInput.value;
    paintToDo(currentValue);
    toDoInput.value = "";
}

// 페이지 로드 시 저장된 걸 불러오고, 이벤트를 처리함
function init(){
    loadToDos();
    toDoForm.addEventListener("submit", handleSubmit);
}

init();

bg.js

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

// 이미지 갯수
const IMG_NUMBER=5;

// 랜덤 숫자 생성
function genRandom(){
    return Math.ceil(Math.random()* IMG_NUMBER);
}

// 랜덤 이미지 출력
function paintImage(imgNumber) {
    const img = new Image();
    img.src = `images/${imgNumber}.jpg`;
    img.classList.add("bgImg");
    body.prepend(img);
}

// 랜덤 수 생성해서, 랜덤 이미지 출력하기
function init() {
    const randomNumber = genRandom();
    paintImage(randomNumber);
}

init();

weather.js

const tem= document.querySelector(".js-temp");
const pla= document.querySelector(".js-place");
const API_KEY = 'your key';
const COORDS = 'coords';

// api 에서 위도 경도를 가지로 날씨와 장소 받아오기
function getWeather(lat, lng){
    fetch(
        `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lng}&appid=${API_KEY}&units=metric`
        ).then(function(response){
            return response.json();
        }).then(function(json){
            const temperture = json.main.temp;
            const place = json.name;
            tem.innerText = `${temperture}°`;
            pla.innerText = place;
        });
}

// 위도 경도 저장하기
function saveCoords(coordsObj){
    localStorage.setItem(COORDS, JSON.stringify(coordsObj));
}

// 위치청보를 얻어왔을 때 위도경도 저장하고, 날씨 가져오기
function handleGeoSuccess(position){
    const latitude = position.coords.latitude;
    const longitude = position.coords.longitude;
    const coordsObj = {
        latitude,
        longitude
    };
    saveCoords(coordsObj);
    getWeather(latitude, latitude);
}

// 위치정보 얻는거 실패했을 때 로그찍기
function handleGeoFail(positon){
    console.log('Cant access geo location');
}

// 위치정보 물어보기
function askForCoords(){
    navigator.geolocation.getCurrentPosition(handleGeoSuccess, handleGeoFail);
}

// 위치정보 저장된거 불러오기
function loadCoords(){
    const loadCoords = localStorage.getItem(COORDS);
    // 저장된 위치정보가 없으면 물어보기
    if(loadCoords === null){
        askForCoords();
    }else {
        // 있으면 json 으로 파싱해서 날씨 가져오기
        const parseCoords = JSON.parse(loadCoords);
        getWeather(parseCoords.latitude, parseCoords.longitude);
    }
}

function init(){
    loadCoords();
}

init();

댓글