[CPU ToyProj] 니꼴라스 크롬 앱 만들기

💗 [CPU ToyProj] 니꼴라스 크롬 앱 만들기

✔ Welcome to JavaScript...

💚 JavaScript의 장점

  • 💙 JavaScript가 생긴 과정
    넷스케이프 : 웹사이트를 인터렉티브하게 만들고 싶었음. 그래서 JavaScript 탄생하게 되었다.

  • 💙 Why JavaScript..?

  1. 프론트엔드에 유일하게 쓰이는 언어이다.
  2. 자바스크립트는 모든 브라우저에 내장되어 있기 때문에, 다운로드 할 필요가 전혀 없다. (브라우저에 내장 : HTML & CSS & 자바스크립트)
    심지어 핸드폰에서도 돌아간다. 브라우저가 있는 곳이라면 어디든지 돌아간다.
  3. three.js를 이용하여 3D 구현도 가능하다.
    ➕ 게임도 만들 수 있다.
    ➕ React.js와 desktop app을 만들어주는 일렉트론 등이 있다.
    ➕ 머신 러닝도 가능하다.
    ➕ socket.io로 채팅 기능을 구현할 수 있다.
    ➕ 심지어 백엔드도 가능하다.

이러한 이유 덕분에 자바스크립트를 쓰지 말아야 하는 이유는 전혀 없~~다.

💚 About JavaScript...

  • 💙 이미 자바스크립트가 브라우저에 내장되어 있기 때문에, 개발자 도구인 F12를 이용해서 브라우저 console을 이용하면 된다. 하지만 코드가 길어지면 불편하다. 그래서 vscode를 이용하면 된다.

  • 💙 HTML의 중요성
    브라우저는 HTML을 열어주고, HTML은 CSS와 JavaScript를 가져온다. HTML은 접착제이다. 그 안에서는 CSS 엔진과 JavaScript 엔진이 돌아가고 있다.

💚 기본적인 데이터 타입 2가지

기본적인 데이터 타입이 2가지가 있다. 자바스크립트에는 type이 존재한다.

  • 숫자형 (number)
    : 정수형 (integer) & 실수형 (float)

  • 문자형 (string)

💚 변수 Variable

calculator를 통해서 변수에 대해서 알아볼 수 있다.

const firstNum = 5;
const secNum = 2;

console.log(firstNum + secNum);
console.log(firstNum * secNum);
console.log(firstNum / secNum);

✔ 변수를 통해서 변하는 변수인지 변하지 않는 변수인지 알 수 있다.

💚 변수 정의 const & let

  • const : 변하지 않는 변수를 의미한다. 대부분은 const를 이용하기. (update X)
  • let : 변할 수 있는 변수를 의미한다. 때에 따라서 let를 이용해주면 된다. (update O)
let player = "hello";
console.log(player);
player = "hi"; // update
console.log(player);
  • var : var..는 사용하지 않기! 스코프 문제가 있기 때문에 위의 2개를 사용하는 것이 좋다. ➕ 좋지 않은 이유는 실수로 업데이트를 해도 언어가 잘못되었다고 말을 해주지 않기 때문이다. 실수를 잡아내지 못 하기 때문이다...
let myName = "tino";
const veryLongVariableName = 0; 
// Python은 _를 이용하고, JS는 대문자를 사용한다.

console.log("Hello, " + myName + "!!"); 
// (let) 한번 myName 생기면 그냥 계속 업데이트 시켜주면 된다. const는 불가능하다.
console.log(veryLongVariableName);

myName = "nicolas"; // variable update!
console.log("And... your name is " + myName + ".");

💚 Boolean ➕➕ 그 외

  • Boolean (value 있음)
    : true (기능이 켜져 있음, on) & false (기능이 꺼져 있음, off)
    (ex) 사용자가 로그인을 하였는가? , 웹사이트가 로딩되고 있는가? 등등
  • null : 변수에 값이 할당되어 있지만, 비어 있음, 아무 것도 없는 상태로 채워져있다. null과 false는 같지 않다.
  • undefined : 변수에 값 자체가 할당되어 있지 않다. 메모리와 컴퓨터가 변수가 있음을 인지하고는 있지만, 값 자체가 없다.
const amIfat = null;
let something; // undefined , 값이 주어지지 않음
console.log(amIfat);
console.log(something);
console.log(something, amIfat);

💚 배열 Array

✔ 데이터를 정리하는 방법 중 하나이다. (데이터를 가능한 최선으로 정리하기.)

  1. 시작과 끝은 대괄호를 이용해서 묶어준다.
  2. 요소는 콤마로 구분하고, 모든 것을 넣어줘도 상관없다.

✔ 알아야 하는 부분

  1. how to create Array
  2. element in array -> 받아오는 방법

✔ 좋지 않은 코드

const mon = "mon";
const tue = "tue";
const wed = "wed";
const thu = "thu";
const fri = "fri";
const sat = "sat";
const sun = "sun";

const dayOfWeek = mon + tue + wed + thu + fri + sat + sun;
console.log(dayOfWeek); // 1개의 요일에 접근하기가 굉장히 어렵다. 그저 text이다.

const week = [mon, tue, wed, thu, fri, sat, sun]; // variable 갖지 않고 해도 된다.

✔ 좋은 코드

const week = ["mon", "tue", "wed", "thu", "fri", "sat"];
console.log(week);
console.log(week[0]); // index 이용하기.
console.log(week[4]); // index는 0부터 시작한다.

// Add one more day to the array
week.push("sun"); // 뒤에 item을 붙여주기.
console.log(week);

const nonsense = [1, 2, "Hello", false, undefined, true, null, "tino"];
console.log(nonsense);

const toBuy = ["apple", "banana", "potato", "strawberry", "pizza"];
console.log(toBuy);
toBuy.push("cola");
console.log(toBuy);
console.log(toBuy[4]);
// out of index : Error!

💚 Object

✔ 데이터를 정리하는 방법 중에 하나이다. (데이터를 가능한 최선으로 정리하기.)
✔ property를 가진 데이터를 정리할 수 있다. (Array 같은 경우는 데이터가 무엇을 뜻하는지 알 수 없다. ➕ 요일 같은 경우에는 설명이 필요없기 때문에, array를 사용하는 것이 가능하다.)
✔ object 안과 밖이 문법이 다르다.

✔ 좋지 않은 코드

const playerName = "tino-kim";
const playerPoints = 121212;
const playerHandsome = false;
const playerFat = "little-bit";
별로 좋지 않다. 변수 이름을 모두 기억해야하고, property 이름도 기억해야 한다.
*/

// 이를 가능한 최선으로 정리하기 위해서 Array 형태를 이용해보자!
/*
const player = ["tino-kim", 121212, false, "little-bit"];
Array에서도 좋지 않음. 어떤 것을 나타내는지 제대로 안 알려주기 때문이다.

✔ 좋은 코드

const player = {
  name: "tino-kim",
  points: 10,
  handsome: false,
  fat: "little-bit",
};

console.log(player); // console이 object이고, 그 안의 어딘가에 log가 있다는 의미이다. 
// log는 function을 의미한다.
console.log(player.name);
console.log(player["name"]);
// 데이터를 정리하는 아주 좋은 방법이다.
// 리스트는 모든 값이 같은 의미를 가진다. 
// 예를 들면, week 리스트를 가지면 그 리스트에 있는 모든 것이 한 주의 요일이라는 것을 알 수 있다.

console.log(player);
player.handsome = true;
player.lastName = "potato";
player.points = player.points + 15;
console.log(player);
// object 안의 무언가를 수정하는 것이다. object 자체는 동일하다.
// constant 안의 무언가를 업데이트하는 것은 아무 문제가 없다.
// 원하면 너가 원하는 property를 만들 수 있다.

💚 함수 Function

계속 반복해서 사용할 수 있는 코드를 제작하는 것을 의미한다.
계속 반복되는 부분을 계속 작성하는 것은 좋은 코드가 아니다. -> 코드의 반복을 최소한으로 줄여야 한다.

✔ function의 example & 계산기 만들기

function sayHello(name, age) {
  // 인수 argument : 함수를 실행하는 동안에 어떤 정보를 함수에게 보낼 수 있는 방법이다.
  // function에는 소괄호가 반드시 필요하다. 괄호 2개가 함수를 실행하는 방법이다.
  console.log(`Hello, my name is ${name}, and my age is ${age}.`);
}

sayHello("tino", 25); // ()를 통해서 출력한 것이고, "tino" 라는 데이터를 함수에 보내고 있다.
sayHello("nico", 10);
sayHello("amy", 13);

// 계산기 만들기

function plus(firstNum, secNum) {
  // 여기에 있는 인수들은 함수 내에서만 동작한다.
  // 블록 밖에서는 이 인수들이 존재하지 않는다.
  console.log(firstNum + secNum);
}

plus(3, 7); // 3 + 7 = 10, 인수는 순서대로 들어간다.

function multiple(firstNum, secNum) {
  // 여기에 있는 인수들은 함수 내에서만 동작한다.
  // 블록 밖에서는 이 인수들이 존재하지 않는다.
  console.log(firstNum * secNum);
}

multiple(5, 8); // 5 * 8 = 40

✔ object 안에 function을 넣어줄 수 있다.

const user = {
  nickName: "tino-kim",
  sayHello: function (otherPersonName) {
    console.log("hello! " + otherPersonName + " Nice to meet you!");
    // object 안에서 함수를 정의할 수도 있다. 함수 이름이 들어오는 순서가 달라지는 것을 기억하자.
  },
};

console.log(user.nickName);
user.sayHello("lynn"); // object 안에 있는 함수를 불러오는 방법이다.
user.sayHello("peter");
user.sayHello("merry jane"); // 함수에게 데이터를 보내는 방법이다.

💚 Recap 1

// 1. data-type: number, string
// 2. variable : const를 이용하고, 가끔 let을 이용하고, var는 절대로 사용하지 않기.

const a = 5;
let isNicoFat = true; // 업데이트 하고 싶은 경우에 let을 이용한다.
console.log(a);
console.log(isNicoFat);
isNicoFat = false; // 다시 let을 붙이지 않아도 된다.
console.log(isNicoFat);

// 3.  true, false, null, undefined
// boolean : true, false
// null : 변수에 값이 할당되어 있다. 값은  "비어있음" 이다.
// undefined : 변수가 값이 할당되어 있지 않다.
let hello; // undefined
console.log(hello);

// 4. Array
const days = [1, 2, true, "text", null, undefined];
console.log(days);
const toBuy = ["potato", "pizza", "orange", "apple", "candy"];
console.log(toBuy);
console.log(toBuy[2]);
toBuy.push("water");
console.log(toBuy);
toBuy[2] = "strawberry";
console.log(toBuy);

// 5. Object
// Array의 문제 : 의미 있는 property 저장할 때 문제가 생긴다.
const player = {
  name: "tino",
  age: 25,
  hobby: "watch movie",
};

console.log(player.age); // console = object
console.log(player);
player.name = "nicolas";
console.log(player);
player.sexy = "soon";
console.log(player);

// 6. function
function plus() {
  console.log(2 + 2);
}

plus(); // 함수를 출력시켜준다.
plus();
plus();
plus();

// 함수 안으로 데이터 보내는 것도 가능하다. 소괄호 안에 데이터를 넣어주면 된다.

function divide(potato, salad) {
  console.log(potato / salad);
}

divide(6, 3); // 인수의 순서가 굉장히 중요하다.
divide(3, 6);

function multiple(potato) {
  // 인수는 블록 내에서만 정의되어 있다.
  console.log(potato - 5); // body
}

multiple(5, 12, 1234, 2335, 77999); // 5 - 5 = 0
// console.log(potato); not defined

const calculator = {
  add: function (a, b) {
    console.log(a + b);
  },
  minus: function (a, b) {
    console.log(a - b);
  },
  multiple: function (a, b) {
    console.log(a * b);
  },
  divide: function (a, b) {
    console.log(a / b);
  },
  squared: function (a, b) {
    console.log(a ** b);
  },
};

calculator.add(5, 1);
calculator.minus(5, 1);
calculator.multiple(5, 2);
calculator.divide(6, 3);
calculator.squared(5, 2);

💚 조건문 Conditional

  • 조건문은 if가 키워드이고, true/ false를 나타내는 것이 필요하다.
  • 음주가 가능한지 가능하지 않은지 확인하는 함수를 만들 것이다.
    : true/ false를 출력하기 위해서 "isNaN()" 이라는 함수를 사용하자.
// 음주가 가능한지 가능하지 않은지 확인하는 함수를 만들 것이다.
const user = parseInt(prompt("나이가 어떻게 되시나요?"));
// 사용자에게 창을 띄울 수 있다. string이라고 인식한다. 자바스크립트 코드를 멈추게 한다. css로 스타일 변경도 못 한다. 오래된 방식이다.
// 요즘에는 자기가 html, css로 만든 창을 사용한다.
// 취소하면, null이 뜬다.
// 근데 string이기 때문에, number로 바꿔줘야한다.
// userNum = parseInt(user); parseInt가 숫자로 변경시켜준다. 굳이 새롭게 변수 만들 이유가 없다.
const calculateUserAge = {
  calculate: function (userAge) {
    /*
    // age가 숫자가 아닌 경우 다시 입력하라고 정보를 전달할 것이다.
    if (isNaN(userAge)) {
      // userAge가 not a number, 즉 숫자가 아니라는 의미이다.
      // isNaN인지 물어보는 것이 좋다.
      return "숫자가 아니니 다시 입력해주세요.";
    } else {
      if (userAge > 19) {
        return "이 분께서는 음주가 가능하십니다.";
      } else {
        return "이 분께서는 음주가 불가능하십니다.";
      }
    }
    */
    if (isNaN(userAge) || userAge < 0) {
      // 음수가 아닌 경우도 포함하기.
      // 위에서부터 아래로 차례로 코드를 실행한다.
      // 여기서는 ||를 사용한다. 1가지 경우만 만족하면 되기 때문이다.
      return "양의 숫자를 다시 입력해주세요.";
    } else if (userAge < 18) {
      return "이 분께서는 음주가 불가능하십니다.";
    } else if (userAge >= 18 && userAge < 50) {
      // && 2개다 만족해야 한다. 2개 모두 true이면  true이다.
      // || 1개만 만족하면 된다. 2개 모두 false이면 false이다.
      return "이 분께서는 음주가 가능하십니다.";
    } else if (userAge > 50 && userAge <= 80) {
      return "이 분께서는 운동을 하셔야 합니다.";
    } else if (userAge > 80) {
      return "이 분께서는 원하시는 대로 하시면 됩니다.";
    }
  },
};

➕ 주의할 점 : conditional의 조건문은 반드시 true 또는 false가 출력되어야만 한다. "userAge === NaN" 이라고 코드를 작성하는 순간, NaN이라는 글자 자체와 같지는 않기 때문에 false가 출력되어, 뒤의 코드가 실행된다.

// (주의) userAge === NaN라고 지정하면, false가 되기 때문에 뒤의 else 코드로 들어가게 된다.
/*
if (conditon) {  condition은 반드시 boolean -> true, false 이어야만 한다.
  condition === true;
} else {
  condition === false;
}
*/

const isDrinking = calculateUserAge.calculate(user);
console.log(isDrinking);

/*
console.log(user, parseInt(user)); // string, number
console.log(user);
console.log(parseInt(user)); // 숫자로 바꿀 수 없으면 not a number가 뜬다.
*/
  • || 그리고 &&... (OR 그리고 AND)
    : ||는 1개만 만족하면 true이고, &&는 2개 모두 만족해야만 true이다.
// || 그리고 && (OR 그리고 AND)
console.log(true || true); // true
console.log(false || true); // true
console.log(true || false); // true
console.log(false || false); // true
console.log(true && true); // true
console.log(false && true); // false
console.log(true && false); // false
console.log(false && false); // false

💚 Recap 2

  • 괄호를 이용하여 우선 순위를 정해줄 수 있다. (feat. &&, ||)
// conditional
const calculateUserAge = {
  // =, 값을 할당하는 것이다.
  calculate: function (userAge) {
    if (isNaN(userAge) || userAge < 0) {
      // boolean을 출력한다. (true/ false)
      // 음수가 아닌 경우도 포함하기.
      // 위에서부터 아래로 차례로 코드를 실행한다.
      // 여기서는 ||를 사용한다. 1가지 경우만 만족하면 되기 때문이다.
      return "양의 숫자를 다시 입력해주세요.";
    } else if (userAge < 18) {
      return "이 분께서는 음주가 불가능하십니다.";
    } else if (userAge >= 18 && userAge < 50) {
      // && 2개다 만족해야 한다. 2개 모두 true이면  true이다.
      // || 1개만 만족하면 된다. 2개 모두 false이면 false이다.
      return "이 분께서는 음주가 가능하십니다.";
    } else if (userAge > 50 && userAge <= 80) {
      return "이 분께서는 운동을 하셔야 합니다.";
    } else if (userAge === 100) {
      // 반대 의미 : !==
      // ===, 좌우가 같다는 의미이다.
      // 실행될 이유가 없다. 이미 위에서 실행되었기 때문이다. 그래서 순서를 이런 식으로 해야 된다.
      // else if는 "양자택일"이다.
      return "당신은 현명하시네요!";
    } else if (userAge > 80) {
      return "이 분께서는 원하시는 대로 하시면 됩니다.";
    }
  },
};

/*
if ((a && b) || (c && d) || (x || w)) {
  // 괄호 먼저 실행 된다...
  // &&, 둘다 true인 경우만 true이다.
  // ||, 하나만 true인 경우만 true이다.
}
*/

✔ JavaScript on the Browser...

💚 The Document Object & HTML in JavaScript

  • javascript가 html에 "어떻게" 상호 작용하는지 배울 것이다.
  • html : 접착제 (css, js 가져오는 역할 수행)
  • html의 element들을 .js통해 변경할 수 있고, 읽을 수 있다.
console.dir(document) 
// 인터렉티브한 property를 모두 보여준다. 엄청 중요하다.
// 여기에 나오는 다양한 항목들은 property 이다.
// 즉, javascripte object 내에 있는 property를 읽어올 수도 변경할 수 도 있다.
  • document.title 제목을 가져올 수 있다. js는 html을 읽어올 수 있다. html 코드를 js관점으로 바라보고 있다.
  • document.title = "Hello" html을 읽을 뿐만 아니라, html 변경도 가능하다.
  • 지금까지 document.title, document.body를 호출하는 방법 배웠다.
// document === website
// document.body

정리
1. html의 element를 .js에서 javascript를 이용해서 가져올 수 있다.
2. 가져오는 것 뿐만 아니라, 각 property를 변경할 수도 있다.
3. console.dir 함수를 이용해서 javascript object에 있는 모든 property를 확인할 수 있다.
4. document는 website를 의미한다.

💚 Searching For Elements

  • 지금부터는 html에서 특정 요소를 어떻게 가져오는지를 배울 것이다.

종류
1. document.getElementById("id");
: id를 이용해서 html에서 원하는 특정 요소 가져오기.
2. document.getElementsByClassName("class");
: class를 이용해서 html에서 원하는 특정 요소 가져오기.
3. document.querySelector("class인 경우는 . 이용하고, id인 경우는 # 이용하기");
: 거의 99.98%는 이것을 많이 이용한다. class인 경우는 . 이용하고, id인 경우는 # 이용하기. 여러 개가 있으면, 맨 앞에 있는 요소만 가져온다.
4. document.querySelectorAll("class인 경우는 . 이용하고, id인 경우는 # 이용하기");
: class인 경우는 . 이용하고, id인 경우는 # 이용하기. 여러 개가 있으면, 모두 가져온다.

const titleFirst = document.querySelector(".bye h1:first-child");
// 첫번째 요소를 반환시켜준다.
// console.log(titleFirst);

querySelectorAll 이용하고, 요소 1개만 가져오고 싶은 경우에는 위의 코드처럼 이용하면 된다.
5. document.getElementsByTagName("tag");
: tag 이름을 통해서 html에서 내가 원하는 특정한 요소를 가져올 수 있다.

const titleId = document.getElementById("title");
// html에서 id를 통해서 찾아준다.
// console.dir(titleId) 태그 1개에서 가져올 수 있는 것들을 보여준다.
// html에서 가져오지만, 그것을 js에서 html을 표현하는 object로 보여준다.
// titleId.innertext = "Got you!";

/*
console.log(titleId.title);
console.log(titleId.id);
console.log(titleId.className);
console.log(titleId.innertext);
*/

// js에 html 불러오기 위해서는 id 같아야 된다.
const titleClass = document.getElementsByClassName("hello");
// console.log(titleClass);
const title = document.getElementsByTagName("h2");
// tagname 가져오는 방법이다.
// console.log(title);

// querySelector 이용하는 것이 아주아주아주~ 좋다. (99.98% 이용)
const titleSel = document.querySelector(".hellos h2");
// 여러 개가 있으면, 첫번째 요소만 가지고 온다.
// css selector를 이용해서 가져오는 방법이다.
// css처럼 사용 가능하다.
// class = "hellos"에서 h2를 가져온다는 뜻이다.
// console.log(titleSel);
const titleSelAll = document.querySelectorAll(".hello");
// console.log(titleSelAll);
const titleFirst = document.querySelector(".bye h1:first-child");
// 첫번째 요소를 반환시켜준다.
// console.log(titleFirst);
const titleQueryId = document.querySelector("#title");
//console.log(titleQueryId);
// titleFirst = titleQueryId는 같은 결과를 가져온다.
// titleFirst.innerText : querySelector인 경우에만 변경된다.

➕ 꼭 기억해야할 것은 .js가 있기 때문에 javascript를 통해서 html의 내용을 가져올 수 있다.

💚 Events

  • html 요소를 .js에서 javascript를 이용해서 불러올 수 있고, 변경할 수도 있다.
  • .js에서 javascript로 style 변경도 가능하다. 하지만 주의해야할 점은 대,소문자를 잘 보고 적어주기. css에서 변경하는 것과는 대,소문자가 조금 다르다.
  • 모든 event는 javascript가 읽어낼 수 있다. (listen 가능)

💜 유용한 팁

Event 구글링 하는 방법 : 꼭 기억하기~! 유용하다~!

✔ 검색하는 방법 : 원하는 태그 + html element + mdn (document name) 그런 다음에 Web APIs로 들어가야 JavaScript 관점에서 찾아볼 수 있다.

✔ HTML Heading Element에서 event를 보다가 HTML Element로 들어가기.

✔ HTML Element에서 event를 보다가 Element로 들어가서 event 확인하기.

const title = document.querySelector(".hello h1");
// console.log(title);
// console.dir(title); 이 항목들이 전부 javascript object이다.
// javascript object 내부에 있는 property들의 값을 변경할 수 있다.
// element의 style도 javascript형식으로 작성되어있다.

title.innerText = "Hello";
title.style.color = "blue";
// .js에서 스타일 변경도 가능하다.
// 모든 이벤트는 자바스크립트가 읽을 수 있다.

function handleTitleClick() {
  title.style.color = "red";
  title.style.fontSize = "40px";
  console.log("title was clicked!");
}

function handleMouseEnter() {
  title.innerText = "Mouse is Here";
  title.style.color = "green";
}

function handleMouseLeave() {
  title.innerText = "Mouse is Gone";
  title.style.color = "black";
}

// 함수에 괄호를 넣지 않는다는 것을 기억하자.

// 1. title object에서 많은 정보 가져올 수 있고, 변경할 수 있다.
// 2. event를 listen 하는 방법을 배웠다.
// addEventListener(event, function);
// function에 실행 버튼 생기게 만들지 말고, 가져오기만 하자.

// console.dir(title); + on = event listener

title.addEventListener("click", handleTitleClick);
title.addEventListener("mouseenter", handleMouseEnter);
title.addEventListener("mouseleave", handleMouseLeave);

➕ 정리

    1. title object에서 많은 정보(property) 가져올 수 있고, 변경할 수 있다.
    1. event를 listen 하는 방법을 배웠다.
    1. addEventListener(event, function);
      : function에 실행 버튼 생기게 만들지 말고, 가져오기만 하자.
  • console.dir(title); + on = event listener
    : console.dir에 on이 앞에 붙은 property는 event이다.
h1.onclick = handleTitleClick; // title = html element
h1.onmouseenter = handleMouseEnter;
h1.onmouseleave = handleMouseLeave;
// 태그.이벤트 = 함수;

앞의 3개의 코드와 동일하다.

💚 event - window

: window를 사용해서 이용하는 이벤트가 따로 존재한다. 예를 들면, resize와 같은 이벤트들이 존재한다.

  • h1은 resize할 수 없지만, window는 resize가 가능하다.
  • document, document body, document title, document head는 f12에서 가져올 수 있다.
  • 하지만 div 같은 경우는 querySelector나 getElementById를 통해서 가져와야 한다.
function handleWindowResize() {
  document.body.style.backgroundColor = "tomato";
}

function handleWindowCopy() {
  alert("Copier!"); // copy를 해주면 이 알림창이 뜬다.
}

function handleWindowOffline() {
  alert("SOS! No WIFI");
}

function handleWindowOnline() {
  alert("It is Great!");
}

window.addEventListener("resize", handleWindowResize); // resize
window.addEventListener("copy", handleWindowCopy); // copy
window.addEventListener("offline", handleWindowOffline); // offline
window.addEventListener("online", handleWindowOnline); // online

💚 .js에서 style 지정하기

: .js에서 style을 지정할 수 있긴 하다. 하지만, css를 이용해서 style을 지정하는 것이 코드가 훨씬 짧고, 간결하다.

  • color를 변경해봤자 h1에 영향을 끼치지 않기 때문에 이 코드를 넣어줘야 한다.
h1.style.color = newColor; 

h1의 색깔은 newColor로 변경하겠다는 의미이다.

  • newColor를 이용해서 h1의 색깔을 변경해준다.
  • 변수를 이용해서 코드를 작성하는 것이 더 보기 좋고, 코드를 이해하기 편리하다. 또한, Error 발생이 적다.
function handleTitleClick() {
  console.log(h1.style.color);
  h1.style.color = "green";
  console.log(h1.style.color);
  
  const currentColor = h1.style.color;
  let newColor; // 변경 가능하다.
  if (currentColor === "blue") {
    newColor = "tomato";
  } else {
    newColor = "blue";
  }
  h1.style.color = newColor; 
}

h1.addEventListener("click", handleTitleClick); // click

💚 event - className

  • style.css
body {
  background-color: beige;
}

h1 {
  color: cornflowerblue;
  transition: color 0.5s ease-in-out;
}

.active {
  color: tomato;
}

.sexy-font {
  font-family: "Franklin Gothic Medium", "Arial Narrow", Arial, sans-serif;
}

: className을 이용해서 이벤트를 지정할 수 있다.

➕ 문제점...

  • className은 모든 것을 교체해버린다. 기존의 것도 제거해버린다.
  • active를 2번 사용하기 때문에 Error의 위험성이 존재한다. 그래도 변수를 이용하면 Error 위험성이 줄어든다.
  • 만약에 여기서 클래스가 있으면, 클래스 이름을 바꾸는 문제가 발생해버린다.
function handleTitleClick() {
  // 1. className을 변경해서 코드 작성하는 방법 (모든 것을 교체해버린다.)
  h1.className = "active";
  console.log(h1.className);
  
  const activeClass = "active";
  if (h1.className === activeClass) {
    h1.className = "";
  } else {
    h1.className = activeClass; // active를 2번 사용하기 때문에 Error의 위험성이 존재한다. 그래도 변수를 이용하면 Error 위험성이 줄어든다.
    // 만약에 여기서 클래스가 있으면, 클래스 이름을 바꾸는 문제가 발생해버린다.
  }
}

h1.addEventListener("click", handleTitleClick); // click

💚 event - classList

  • style.css
body {
  background-color: beige;
}

h1 {
  color: cornflowerblue;
  transition: color 0.5s ease-in-out;
}

.active {
  color: tomato;
}

.sexy-font {
  font-family: "Franklin Gothic Medium", "Arial Narrow", Arial, sans-serif;
}

: classList를 이용해서 이벤트를 지정할 수 있다.

function handleTitleClick() {
  // 2. classList를 변경해서 코드 작성하는 방법
  const activeClass = "active";
  if (h1.classList.contains(activeClass)) {
    h1.classList.remove(activeClass);
  } else {
    h1.classList.add(activeClass);
    // className을 변경하지 않는다. 그리고 이 코드는 toggle과 같은 기능을 수행할 수 있다.
  }
}

h1.addEventListener("click", handleTitleClick); // click

밑의 코드는 toggle을 이용해주었다.
toggle = add + remove가 함께 있는 함수이다.

function handleTitleClick() {
  // 2. classList를 변경해서 코드 작성하는 방법
  h1.classList.toggle(activeClass); // toggle = add + remove
}

h1.addEventListener("click", handleTitleClick); // click

코드가 정말 간결해졌다.

➕ 정리...

  1. element를 찾기.
  2. event를 연결하기.
    : getElementById와 같은 것으로 element를 가져온 것과 연결되는 ; event가 있고, window와 연결되는 event들이 있다.
  3. 어떤 event를 줄 것인지 생각해보기.
    : function을 제작하여, 내가 원하는 event를 주도록 하자. 물론 .js로도 style을 지정할 수는 있지만, 최대한 css를 이용하여 style을 주자. 그리고 classList와 className을 이용해서 style 변화가 가능한데, classList를 이용하자. className은 기존의 있던 것들이 제거되기 때문이다. 즉, Error가 날 가능성이 커진다.

✔ Login

: 밑의 3가지를 이뤄내야 한다.

💚 Username 가져오기 & 인사 건네기.

Username을 가져와야 한다.
element를 가져온 후에, 조건에 맞게 가져와야 된다.

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

function onClickLoginBtnClick() {
  // console.log("click!!!!");
  const username = loginInput.value;
  // console.log(`Hello, ${username}! Nice to Meet You!`); LoginInput에 대한 정보들을 볼 수 있다.
  // 하지만, 이름을 입력했을 경우에만 출력하고 싶다.
  if (username === "") {
    alert("Please write your name.");
  } else if (username.length > 15) {
    // 길이가 15보다 긴 경우
    alert("Your name is too long.");
  } else {
    console.log(`Hello, ${username}! Nice to Meet You!`);
  }
}

loginButton.addEventListener("click", onClickLoginBtnClick);

js 코드를 작성하지 않아도, html을 이용하여 기능을 구현할 수 있다. 따라서 이 click 코드에 신경쓸 필요가 없다. form이 알아서 submit 해주고 있기 때문이다.

✔ html을 이용해서 작성한 코드

<form class="hidden" id="login-form">
      <input
        required
        maxlength="15"
        type="text"
        placeholder="What is your name?"
      />
      <input type="submit" value="Log In" />
</form>

하지만 우리는 form이 submit되는 것을 막아주고 싶다. submit이 되어 버리면, 가지고 있던 것들이 모두 날아가기 때문이다.

그래서 우리는 밑의 코드를 이용해줄 것이다.

event.preventDefault(); // 기본 설정을 없애준다.

argument
(information) : 필요할 만한 정보를 주는 것이다. 첫 번째 인수는 지금 막 벌어진 일들에 대한 정보를 제공한다. 즉, 방금 실행된 event에 대한 여러 정보이다.

const greeting = document.querySelector("#greeting");
const HIDDEN_CLASSNAME = "hidden"; // 중요한 코드가 아닌 문자열 -> 대문자로 변수 만들기. 모두 같아야 되는 경우...
const USERNAME_KEY = "username"; // 중요한 코드가 아닌 문자열 -> 대문자로 변수 만들기. 모두 같아야 되는 경우...

function onLoginSubmit(event) {
  event.preventDefault(); // form을 submit하면 새로고침을 하는데, 이 함수를 추가해서 그 일을 막아주고 있다.
  loginForm.classList.add(HIDDEN_CLASSNAME);
  const username = loginInput.value;
  // console.log(username);
  paingGreetings(username); // 반복되는 행위는 함수로 만들어서 지정하기.
  /*
  const username = loginInput.value;
  console.log(username); // submit 자체는 인지하지만, 새로고침은 못 막고 있다.
  */
}

function paingGreetings(username) {
  greeting.innerText = `Hello, ${username}`;
  greeting.classList.remove(HIDDEN_CLASSNAME);
} // 뒤에도 계속 반복되기 때문에 작성된 코드이다.

loginForm.addEventListener("submit", onLoginSubmit); // onLoginSubmit()는 바로 실행시켜준다. 하지만, addEventListener는 바로 실행시켜주는 것이 아니다.

onLoginSubmit의 의미
1. 제출하는 순간에 브라우저에 제출되는 기본 업무를 막아주고 있다.
2. loginForm에 className을 추가시켜준다.
3. 이름과 함께 인사를 건넬 수 있다.
4. 다시 className을 제거하여, loginForm을 보이지 않게 만들어 준다.

✔ 문제점
: 새로 고침 하는 순간 정보들이 모두 사라진다. 정보를 브라우저에 저장할 수 없다.

❗❗ 해결 방법
: local storage API를 이용한다.

💚 Username 저장하기 & 새로고침 후에도 정보를 남기기.

: local storage API를 이용한다. (무료로 브라우저에 정보를 저장해줄 수 있는 API 이다.)

const greeting = document.querySelector("#greeting");
const HIDDEN_CLASSNAME = "hidden"; // 중요한 코드가 아닌 문자열 -> 대문자로 변수 만들기. 모두 같아야 되는 경우...
const USERNAME_KEY = "username"; // 중요한 코드가 아닌 문자열 -> 대문자로 변수 만들기. 모두 같아야 되는 경우...

function onLoginSubmit(event) {
  event.preventDefault(); // form을 submit하면 새로고침을 하는데, 이 함수를 추가해서 그 일을 막아주고 있다.
  loginForm.classList.add(HIDDEN_CLASSNAME);
  const username = loginInput.value;
  localStorage.setItem(USERNAME_KEY, username);
  // console.log(username); // submit 자체는 인지하고 새로고침도 막아준다.
  // console.log(username);
  paingGreetings(username); // 반복되는 행위는 함수로 만들어서 지정하기.
  /*
  const username = loginInput.value;
  console.log(username); // submit 자체는 인지하지만, 새로고침은 못 막고 있다.
  */
}

function paingGreetings(username) {
  greeting.innerText = `Hello, ${username}`;
  greeting.classList.remove(HIDDEN_CLASSNAME);
} // 뒤에도 계속 반복되기 때문에 작성된 코드이다.

loginForm.addEventListener("submit", onLoginSubmit); // onLoginSubmit()는 바로 실행시켜준다. 하지만, addEventListener는 바로 실행시켜주는 것이 아니다.

onLoginSubmit의 의미
1. 제출하는 순간에 브라우저에 제출되는 기본 업무를 막아주고 있다.
2. loginForm에 className을 추가시켜준다.
3. ❗❗ username을 브라우저가 기억할 수 있다.
4. 이름과 함께 인사를 건넬 수 있다.
5. 다시 className을 제거하여, loginForm을 보이지 않게 만들어 준다.

✔ 문제점
: 새로 고침 하는 순간 정보들이 사라지지는 않지만, 브라우저에 보이지 않고 loginForm이 다시 보이게 된다.

❗❗ 해결 방법
: 조건문을 이용해서 이름이 들어온 경우에는 loginForm을 없애고 인사를 계속 건네고, 이름이 들어오지 않은 경우에는 loginForm을 보여줘서 이름을 입력하게 만들어 준다.

const savedUsername = localStorage.getItem(USERNAME_KEY);
console.log(savedUsername); // null

if (savedUsername === null) {
  // 없는 경우에는 null이 뜨기 때문이다.
  // show the form
  loginForm.classList.remove(HIDDEN_CLASSNAME);
  loginForm.addEventListener("submit", onLoginSubmit); // onLoginSubmit()는 바로 실행시켜준다. 하지만, addEventListener는 바로 실행시켜주는 것이 아니다.
} else {
  // show the greeting
  paingGreetings(savedUsername); // 반복되는 행위는 함수로 만들어서 지정하기.
}
  • 이름이 없는 경우에는 loginForm의 className(hidden)을 제거하고,
    (= loginForm이 보이도록 설정하기) addEventListener를 통해서 정보 저장 및 인사를 건네게 처리해준다.

  • 이름이 있는 경우에는 인사를 건네게 만들고, greeting의 className(hidden)은 제거시켜 준다. (= greeting이 보이도록 설정하기)

💚 Recap 3

💚 Login 기능 구현하는 방법 💚

  • form을 이용해서 html로 구현하자. 예를 들면, 글자 수 제한과 공백 제거이다. 물론 click event를 이용해서 js로 작성할 수 있지만 효율성이 떨어진다.
  • form 자체가 알아서 submit 기능을 수행해준다. 우리는 username을 기억을 해야 되는데, 새로고침을 누르면 브라우저가 기억을 못 하고 있다. 그래서 username을 기억하기 위해서 local storage API를 이용한다.
  • 문제는 새로고침을 하면 브라우저가 정보를 기억을 하지만, 화면 상에는 보이지 않게 된다. 조건문을 활용하여, 값이 없는 경우에는 loginForm을 보여주고 값이 있는 경우에는 Greeting을 보여주도록 하자.

➕ 중요하지 않지만 계속 반복되는 문자열 : 대문자로 이루어진 변수로 나타낼 수 있다.

➕ 반복되는 코드 : 함수로 만들어준 이후에 이용하자.

➕ 처음에 form과 h1은 모두 class = "hidden" 상태로 놓아주기.
나는 1개만 hidden 상태로 놓아주고 코드를 짰는데 add & remove를 이용할 때에는 둘다 hidden으로 놓아주는 것이 편리하다.

✔ Clock

: new Date()를 이용해서 시간, 분, 초를 가져올 수 있다.

const date = new Date();
const hour = date.getHours();
const minute = date.getMinutes();
const second = date.getSeconds();

여기서 우리는 길이가 2보다 작은 경우에는 앞에 0을 붙여주도록 한다. (= 길이가 1인 경우에 앞에 0을 붙여준다.) padStart 라는 문자열 함수를 이용해주도록 하자.

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

function sayTime() {
  const date = new Date();
  const hour = String(date.getHours()).padStart(2, "0");
  const minute = String(date.getMinutes()).padStart(2, "0");
  const second = String(date.getSeconds()).padStart(2, "0");
  clock.innerText = `${hour}:${minute}:${second}`;
}

sayTime();
setInterval(sayTime, 1000); // 1s = 1000ms

최신 메소드를 이용하지 않고, 글자 수를 세어 앞에 0 붙여주는 함수 만들기.

✔ 참고 공식 문서 : MDN Document Function

공식 문서에서 나오는 인수(argument)를 이용해서 함수를 만들 수도 있다. 나는 일단 인수 없이 함수를 제작해보았다.

function setLength() {
  // 만약에 길이가 2인 경우에는 그대로 출력하기.
  // 길이가 2보다 작은 경우에는 앞에 0 붙이기.
  const date = new Date();
  const hour = String(date.getHours());
  const minute = String(date.getMinutes());
  const second = String(date.getSeconds());
  const array = [hour, minute, second];

  for (i = 0; i < array.length; i++) {
    if (array[i].length < 2) {
      array[i] = "0".concat(array[i]);
      // console.log(array[i]);
      clock.innerText = `${array[0]}:${array[1]}:${array[2]}`;
    } else {
      array[i];
      // console.log(array[i]);
      clock.innerText = `${array[0]}:${array[1]}:${array[2]}`;
    }
  }
}

setLength();
setInterval(setLength, 1000);

💚 Recap 4

✔ 기억해야 할 점

  • 날짜를 이용해서 시간, 분, 초를 가져오기.
  • 글자 수에 맞춰서 출력하기. (= 글자의 개수가 2가 아닌 경우에는 앞에 0을 붙여주기.)
  • 참고 블로그 : 참고 블로그 주소

✔ 절대 경로와 상대 경로

  • 절대 경로 : 그냥 내 드라이브에서 주소를 텍스트로 복사 & 붙여넣기를 해주면 된다.
  • 상대 경로:

    / : 루트
    ./ : 현재 위치
    ../ : 현재 위치에서의 폴더 내부를 의미한다.

그래서 나는 또 다른 폴더를 만들어서 html, css, js를 보관하였기 때문에 ../을 이용해서 css, js를 html과 연결시켰다.

✔ Background & Quotes

  • 선수 지식
Math.random(); 이용하기

💚 Quotes

: quotes를 object 형태로 나타내어 Math.random 을 이용하여 무작위로 불러온다.

const quotes = [
  // object
  {
    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",
  },
];

➕ 과정
1. 일단 html에서 원하는 element를 불러오기.
2. 그 element 안에 넣을 quote와 author 변수를 만들어주기. 그리고 random 하게 뽑는 것을 생각하기.
3. random 하게 뽑은 것들은 html에서 불러온 element에 넣어주기.

여기서 주의할 점

Math.random() // 0 ~ 1 까지의 숫자를 랜덤하게 가져온다.
// 그래서 index로 이용하기 위해서는 X length 만큼 해줘야 index로 사용할 수 있다.
const quote = document.querySelector("#quote span:first-child");
const author = document.querySelector("#quote span:last-child");
const todaysQuote = quotes[Math.floor(Math.random() * quotes.length)];
// 0 ~ 1까지의 수를 찾아내기 때문에, 10 곱해주면 0 ~ 10까지의 수를 찾아낸다.
// 10 이라고 적는 대신에 length를 이용하기.

quote.innerText = todaysQuote.quote;
author.innerText = todaysQuote.author;

💚 Background

: background를 Array 형태로 나타내어 Math.random 을 이용하여 무작위로 불러온다.

여기서 주의할 점
: 항상 우리는 html에서 가져와서 js 코드를 작성해줬는데 이번에는 반대가 되었다. js에서 html 코드를 작성해줘야 하는 경우가 생겼다. 왜냐하면 html의 img 태그에서 random 하게 image를 뽑을 수 없기 때문이다.

➕ 과정

  • js에서 image array를 만들어준 다음, random 하게 뽑을 수 있도록 Math.random 을 이용하기.
const chosenImage = images[Math.floor(Math.random() * images.length)];
  • js 코드에서 html 코드를 작성해준다.
const bgImage = document.createElement("img");
  • js 코드에서 그 html 코드의 주소를 작성해준다.
bgImage.src = `../img/${chosenImage}`;
  • js 코드를 html 코드에 넣어준다.
document.body.appendChild(bgImage);

위의 코드를 잘 연결시키면 최종 코드가 작성된다.

const images = ["beach.jpg", "building.jpg", "night.jpg"];
const chosenImage = images[Math.floor(Math.random() * images.length)];
const bgImage = document.createElement("img"); 
// 이것만 이용하면 js에서 html 요소를 만들 수 있다. createElement 이용하기.
// console.log(bgImage);
bgImage.src = `../img/${chosenImage}`;
//console.log(bgImage);
document.body.appendChild(bgImage); // body에 html 추가할 것이다.

💚 Recap 5

2개 다 Math.floor() 와 Math.random() 을 이용해서 랜덤하게 값을 뽑아주었다. Math.floor와 Math.random() 으로 index를 만들어서 이용하였다.

실수를 정수로 처리하는 방법 3가지

Math.floor() // 값을 버려준다.
Math.ceil() // 값을 올려준다.
Math.round() // 값을 반올림 시켜준다. 0~4까지는 내리고, 5~9까지는 올린다.

Math.random()
random하게 값을 뽑는다.

위의 내용을 정리

뽑아야 하는 변수[Math.floor(Math.random() * 어떤 변수.length)]
// 위의 코드를 index로 이용한다.
  • quote : quotes -> quote와 author 변수를 만들어준다. -> todayQuote 변수를 만든 이후에 그 변수에서 quote, author를 innerText를 이용해서 html 파일에 넣어준다.
  • background : images -> chosenImage -> bgImage를 만들어서 createElement를 이용해서 img 태그로 만들어준다. -> bgImage.src를 이용해서 주소를 넣어준다. -> bgImage를 html body의 끝 부분에 추가시켜준다.
const p = document.createElement("p");
document.body.appendChild(p);
// html body에 p를 추가시켜준다.

중요한 점
1. Math.random()과 Math.floor()를 이용한 index 처리하기.
2. createElement를 이용해서 .js에서 html 태그를 만들어주기.
3. document.body.appendChild()를 이용해서 html body 맨 끝에 img 태그를 붙여주기.

✔ To-Do-List

✔ Weather

좋은 웹페이지 즐겨찾기