베이스캠프를 시작한 지 일주일이 흘렀다! 지난주 금요일에 친구의 부름에 과제만 마치고 후다닥 놀러 나가는 바람에 5일차와 6일차를 같이 쓰게 돼버렸다 ㅎㅎ.. 빼먹지 말자..
자 오늘도 열공 가보자!
// html
<!DOCTYPE html>
<html lang="ko">
<head>
<title>function</title>
<script src="./06-timer.js"></script>
</head>
<body>
<input id="target" type="text" placeholder="000000" disabled="true">
<button id="send" onclick="sendNum()">인증번호 전송</button>
<div id="time">3:00</div>
<button id="finish">인증완료</button>
</body>
</html>
// js
let isStarted = false;
let sendNum = () => {
if (isStarted === false) {
// 타이머가 작동중이 아닐떄
isStarted = true
document.getElementById("finish").disabled = false
const token = String(Math.floor(Math.random() * 1000000)).padStart(6, "0")
document.getElementById("target").value = token
document.getElementById("target").style.color = `#${token}`
// document.getElementById("target").style.color = "#" + token
let time = 10
let timer
timer = setInterval(function () {
if (time >= 0) {
let min = Math.floor(time / 60)
let sec = String(time % 60).padStart(2, "0")
document.getElementById("time").innerText = min + ":" + sec
time = time - 1
} else {
document.getElementById("finish").disabled = true
isStarted = false
clearInterval(timer)
}
}, 1000)
} else {
// 타이머가 작동중일때
}
}
4일차 때 인증번호 전송 버튼을 여러 번 누르게 되면 setInterval 함수가 계속 발동되는 문제가 생겼다
그래서 타이머가 작동 중인지 아닌지 판별할 변수를 생성해서 조건을 추가하였고 setInterval을 변수화 시켜서 clearInterval에 담아주어 멈추는 기능까지 생성하여 문제를 해결하였다!
// html 일부
<div class="wrapper__right">
<div class="wrapper__right__header">
<div class="right__header__title">사이좋은 사람들, 싸이월드</div>
<div class="right__header__setting">사생활보호설정►</div>
</div>
<div class="wrapper__right__body">
<iframe id="contentsFrame" src="./home.html"></iframe>
</div>
</div>
<div class="navigation">
<div class="navigation__item" id="menuHome" onclick="menuHome()">홈</div>
<div class="navigation__item" id="menuJukebox" onclick="menuJukebox()">쥬크박스</div>
<div class="navigation__item" id="menuGame" onclick="menuGame()">게임</div>
</div>
//js
const menuHome = () => {
document.getElementById("contentsFrame").setAttribute("src","home.html")
document.getElementById("menuHome").style = "color : black; background-color: white;"
document.getElementById("menuJukebox").style = "color : white; background-color: #298eb5;"
document.getElementById("menuGame").style = "color : white; background-color: #298eb5;"
}
const menuJukebox = () => {
document.getElementById("contentsFrame").setAttribute("src","jukebox.html")
document.getElementById("menuHome").style = "color : white; background-color: #298eb5;"
document.getElementById("menuJukebox").style = "color : black; background-color: white;"
document.getElementById("menuGame").style = "color : white; background-color: #298eb5;"
}
const menuGame = () => {
document.getElementById("contentsFrame").setAttribute("src","game.html")
document.getElementById("menuHome").style = "color : white; background-color: #298eb5;"
document.getElementById("menuJukebox").style = "color : white; background-color: #298eb5;"
document.getElementById("menuGame").style = "color : black; background-color: white;"
}
<!DOCTYPE html>
<html lang="ko">
<head>
<title>회원가입</title>
<link rel="stylesheet" href="./final.css">
<script src="./final.js"></script>
</head>
<body>
<div class="wrapper">
<div class="title">코드캠프 회원가입</div>
<div class="info">
<input id="email" type="text" placeholder="이메일을 입력해 주세요.">
<div class="errorMessage" id="emailErrorMessage"></div>
</div>
<div class="info">
<input id="name" type="text" placeholder="이름을 입력해 주세요.">
<div class="errorMessage" id="nameErrorMessage"></div>
</div>
<div class="info">
<input id="pw1" type="text" placeholder="비밀번호를 입력해 주세요.">
<div class="errorMessage" id="pw1ErrorMessage"></div>
</div>
<div class="info">
<input id="pw2" type="text" placeholder="비밀번호를 다시 입력해 주세요.">
<div class="errorMessage" id="pw2ErrorMessage"></div>
</div>
<div class="phone__wrapper">
<div class="phoneNumDiv">
<input id="pNum1" type="text" maxlength="3" oninput="changeFocus1()">-
<input id="pNum2" type="text" maxlength="4" oninput="changeFocus2()">-
<input id="pNum3" type="text" maxlength="4" oninput="changeFocus3()">
</div>
<div class="tokenSendDiv">
<div class="tokenText" id="tokenNum">000000</div>
<button class="tokenBtn" id="tokenSend" onclick="tokenSend()" disabled="true">인증번호 전송</button>
</div>
<div class="tokenSubMitDiv">
<div class="tokenText" id="tokenTimer">3:00</div>
<button class="tokenBtn" id="tokenSubmit" onclick="tokenSubmit()" disabled="true">인증확인</button>
</div>
</div>
<div class="locationDiv">
<select id="location">
<option disabled="true" selected="true">지역을 선택하세요.</option>
<option>인천</option>
<option>서울</option>
<option>경기</option>
</select>
<div class="errorMessage" id="locationErrorMessage"></div>
</div>
<div class="genderDiv">
<div class="gender">
<input type="radio" name="gender" value="W" id="gender1">여성
<input type="radio" name="gender" value="M" id="gender2">남성
</div>
<div class="errorMessage" id="genderErrorMessage"></div>
</div>
<div class="divideLine"></div>
<button class="submit" id="submit" onclick="submit()" disabled="true">가입하기</button>
</div>
</body>
</html>
큰 구조를 먼저 잡고 차근차근 만들어나가니 헷갈리긴 했지만 어렵진 않았다!
다음 css!
* {
box-sizing: border-box;
margin: 0;
}
html,
body {
width: 1920px;
height: 1196px;
}
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.wrapper {
width: 540px;
height: 960px;
background-color: #ffffff;
border: 1px solid #AACDFF;
box-shadow: 7px 7px 39px rgba(0, 104, 255, 0.25);
border-radius: 20px;
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
}
.title {
width: 380px;
text-align: left;
font-family: 'Noto Sans CJK KR';
font-style: normal;
font-weight: 700;
font-size: 32px;
line-height: 47px;
margin : 10px 0px;
color: #0068FF;
}
.info>input {
width: 380px;
height: 60px;
background: #FFFFFF;
border: 1px solid #D2D2D2;
border-radius: 7px;
}
.errorMessage {
width: 380px;
text-align: center;
font-size: 7px;
color: red;
}
.phone__wrapper {
width: 380px;
display: flex;
flex-direction: column;
}
.phoneNumDiv {
width: 380px;
/* font-size: 11px; */
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.phoneNumDiv>input {
width: 100px;
height: 40px;
background: #FFFFFF;
border: 1px solid #D2D2D2;
border-radius: 7px;
}
.tokenSendDiv {
margin-top: 15px;
width: 380px;
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
}
.tokenSubMitDiv {
margin-top: 15px;
width: 380px;
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
}
.tokenText {
font-style: normal;
font-weight: 400;
font-size: 18px;
line-height: 27px;
color: #0068FF;
}
.tokenBtn {
width: 120px;
height: 40px;
border-radius: 7px;
border: 1px solid #D2D2D2;
margin-left: 15px;
font-family: 'Noto Sans CJK KR';
font-style: normal;
font-weight: 400;
font-size: 16px;
line-height: 24px;
text-align: center;
}
#location {
width: 380px;
height: 60px;
background: #FFFFFF;
border: 1px solid #D2D2D2;
border-radius: 7px;
}
.genderDiv {
width: 380px;
display: flex;
flex-direction: column;
justify-content: center;
}
.gender {
display: flex;
flex-direction: row;
justify-content: center;
}
.gender>input {
margin: 3px;
}
#gender2 {
margin-left: 15px;
}
.divideLine {
border-top: 1px solid #E6E6E6;
width: 380px;
}
.submit {
width: 380px;
height: 75px;
border-radius: 10px;
border: 1px solid #D2D2D2;
}
input , select {
padding: 10px;
}
정렬의 고수가 된 기분이랄까? 조금 헤매긴 했다 ㅎㅎ..
다음 js!
// 핸드폰 번호 포커싱 옮기기
const changeFocus1 = () => {
let pNum1 = document.getElementById("pNum1").value
if (pNum1.length === 3) {
document.getElementById("pNum2").focus()
}
}
const changeFocus2 = () => {
let pNum2 = document.getElementById("pNum2").value
if (pNum2.length === 4) {
document.getElementById("pNum3").focus()
}
}
const changeFocus3 = () => {
let pNum2 = document.getElementById("pNum3").value
if (pNum2.length === 4) {
document.getElementById("tokenSend").disabled = false
document.getElementById("tokenSend").style = "background-color:#FFFFFF; border-color: #0068FF; color: #0068FF; cursor: pointer;"
}
}
// 인증번호 전송 기능
let timer
const tokenSend = (arg) => {
const token = String(Math.floor(Math.random() * 1000000)).padStart(6, "0")
document.getElementById("tokenSend").disabled = true
document.getElementById("tokenSend").style = ""
document.getElementById("tokenNum").innerText = token
let time = 180
timer = setInterval(function () {
if (time >= 0) {
let min = Math.floor(time / 60)
let sec = String(time % 60).padStart(2, "0")
time = time - 1
document.getElementById("tokenSubmit").disabled = false
document.getElementById("tokenSubmit").style = "background-color:#0068FF; color: #FFFFFF; cursor: pointer;"
document.getElementById("tokenTimer").innerText = min + ":" + sec
} else {
document.getElementById("tokenNum").innerText = "000000"
document.getElementById("tokenTimer").innerText = "3:00"
document.getElementById("tokenSubmit").disabled = true
document.getElementById("tokenSubmit").style = ""
document.getElementById("tokenSend").disabled = false
document.getElementById("tokenSend").style = "background-color:#FFFFFF; border-color: #0068FF; color: #0068FF; cursor: pointer;"
clearInterval(timer)
}
}, 1000)
}
// 인증완료 기능
const tokenSubmit = () => {
let tokeTimer = document.getElementById("tokenTimer").innerText
if (tokenTimer !== "0:00") {
alert("인증이 완료되었습니다.")
clearInterval(timer)
document.getElementById("tokenNum").innerText = "000000"
document.getElementById("tokenTimer").innerText = "3:00"
document.getElementById("tokenSubmit").disabled = true
document.getElementById("tokenSubmit").innerText = "인증완료"
document.getElementById("tokenSubmit").style = ""
document.getElementById("tokenSend").disabled = true
document.getElementById("submit").disabled = false
document.getElementById("submit").style = "background-color:#FFFFFF; border-color: #0068FF; color: #0068FF; cursor: pointer;"
}
}
// 가입완료 기능
const submit = () => {
let email = document.getElementById("email").value
let name = document.getElementById("name").value
let pw1 = document.getElementById("pw1").value
let pw2 = document.getElementById("pw2").value
let location = document.getElementById("location").value
let gender = document.querySelector("input[name='gender']").checked
let isValid = true
if(!email.includes("@")) {
document.getElementById("emailErrorMessage").innerText = "이메일이 올바르지 않습니다."
isValid = false
} else {
document.getElementById("emailErrorMessage").innerText = ""
}
if(name === "") {
document.getElementById("nameErrorMessage").innerText = "이름이 올바르지 않습니다."
isValid = false
} else {
document.getElementById("nameErrorMessage").innerText = ""
}
if(pw1 === "" || pw2 === "" || pw1 !== pw2) {
document.getElementById("pw1ErrorMessage").innerText = "비밀번호를 입력해 주세요."
document.getElementById("pw2ErrorMessage").innerText = "비밀번호를 입력해 주세요."
isValid = false
} else {
document.getElementById("pw1ErrorMessage").innerText = ""
document.getElementById("pw2ErrorMessage").innerText = ""
}
if(location === "지역을 선택하세요.") {
document.getElementById("locationErrorMessage").innerText = "지역을 선택해주세요."
isValid = false
} else {
document.getElementById("locationErrorMessage").innerText = ""
}
if(!gender) {
document.getElementById("genderErrorMessage").innerText = "성별을 선택해주세요."
isValid = false
} else {
document.getElementById("genderErrorMessage").innerText = ""
}
if(isValid) {
alert("코드캠프 가입을 축하합니다.")
}
}
지금 코드를 다시 보니 뭔가 지저분한 느낌이다 함수 하나에 여러 기능을 포함하고 있어서 지저분한 것 같다
기능별로 함수를 나눠서 호출하는 방식으로 더 세분화했어도 괜찮았을 것 같다.
한 주의 마지막 과제인 만큼 시간이 좀 걸리긴 했지만 확실히 강의를 듣고 만들다 보니 아 여기서 이 때 배운 이걸 쓰면 되겠는지? 가 파파파팍 머리에 바로 떠올랐다 블로그로 매일매일 정리하는 것도 혼자만의 코드 리뷰 느낌이라 복습도 되고 좋은 것 같다 매일매일 빼먹지 말고 앞으로도 파이팅!!
inline style
<!--태그에 직접 style 적용-->
<h1 style="color:blue"> 제목이에요~ </h1>
style 태그 사용하기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>html 사이트
</title>
<style>
h1 {
color : blue;
}
</style>
</head>
<body>
<h1> 제목이에요~ </h1>
</body>
</html>
위 두 가지 방법은 당장 사용하긴 편하지만 유지 보수에 불리하므로 css 파일을 따로 분리해 주어야 한다!
<!--link 태그는 head태그 안에 있어야 한다.-->
<link href="./style.css" rel="stylesheet"/>
사용되는 선택자를 알아 보자!
/*태그 선택자*/
div {
background-color : red;
}
/*id 선택자*/
#id {
property : property value;
}
/*class 선택자*/
.class {
property : property value;
}
/* 자손 선택자 사용예시 - .box 안에 있는 #title을 선택한다. */
.box #title {
color : red
}
/* 다중 선택자 사용예시 - .box 이면서 동시에 #title인 요소를 선택한다. */
.box#title {
color : red
}
/* 전체 선택자 */
* {
property : property value
}
/* 그룹 선택자를 이용해서 한번에 처리 */
h2, p, div {
color : blue
}
.some-box:hover{ background-color: red; } /* 마우스를 요소에 올렸을때 */
.container-boxs:first-child{ margin-left: 0; } /* 첫번째 자식 선택자 */
.container-boxs:last-child{ margin-right: 0; } /* 마지막 자식 선택자 */
.contentsBox:nth-child(3){ color: red; } /* 입력한 자식 선택자 */
.title {
font-size : 15px; /* 글자 크기 조절 */
font-weight : bold; /* 글자 굵기 조절 */
font-style : italic; /* 글자 모양 조절 */
text-decoration: underline; /* 글자 모양 조절 */
color : red; /* 글자 색상 지정 */
}
box-sizing
사실 잘 알지 못하고 사용하다가 강의를 듣고 알게 된 내용이다
기본 속성은 content-box로 되어있지만 레이아웃이 깨지지 않는 게 좋기 때문에 border-box로 설정 해놓는 것이 좋다!
css 레이아웃
HTML의 요소들을 배치하는 것을 레이아웃이라고 부르며 이 시스템에는 역사가 있습니다
float -> flex -> grid 순서로 등장하였으며 보편적으로 flex와 grid를 혼용하는 추세다!!
그럼 왜 float를 요즘 잘 쓰지 않는지 float와 flex로 같은 화면을 만들어보자
<!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>나만의 일기장!!</title>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<header class="header">
<div class="header-inner">
<div class="logo">
<h1>
<a href="#none">HAGD</a>
</h1>
</div>
<div class="menu">
<ul class="menu__ul">
<li>
<a href="#none">어제의 일기</a>
</li>
<li>
<a href="#none">오늘의 일기</a>
</li>
<li>
<a href="#none">내일의 일기</a>
</li>
<!-- <div class="clearfix"></div> -->
</ul>
</div>
<div class="user">
<img src="./img/portrait.png" alt="유저 정보" width="32" height="32">
</div>
<!-- <div class="clearfix"></div> -->
</div>
</header>
<div class="container">
<div class="wrapper">
<div class="wrapper__head">
<h1 class="wrapper__head__title">
나만의 일기장
</h1>
<p class="wrapper__head_sub-title">
나만의 일기장입니다!<br>
원하는 색과 사이즈로 일기장을 커스텀해보세요.
<span id="point">
Have a Good Day.😄
</span>
</p>
</div>
<div class="wrapper__body">
<div class="wrapper__body_content">
<p class="diary-title">
📌 쭈꾸미의 일기
</p>
<p>
오늘은 <span class="kimchi">김치찜을</span> 먹었다. <span class="egg">계란말이</span> 도 함께 있는 세트였다.<br>
맛있어서 정신없이 먹다 보니 배가 너무 불러서 힘들었다.<br>
내일은 <span class="highlight">과식하지 말아야겠다!!</span>
</p>
<p class="diary-date">
2022년 7월 5일<br>
날씨 흐림 😭
</p>
</div>
</div>
</div>
</div>
</body>
</html>
/* float 사용*/
.header {
border-bottom: 1px solid gray;
}
.header-inner {
width: 900px;
height: 100%;
margin: 0 auto;
}
.logo h1 a {
text-decoration: none;
color: orange;
}
.logo {
float: left;
width: 100px;
height: 80px;
padding-top: 22px;
}
.menu {
float: left;
width: calc(100% - 200px);
height: 80px;
text-align: center;
}
.menu__ul {
display: inline-block;
}
.menu__ul li {
float: left;
list-style: none;
}
.menu__ul li a {
display: block;
color: black;
text-decoration: none;
padding: 29px 20px;
}
.menu__ul li a:hover {
color: orange;
}
.user {
float: left;
width: 100px;
height: 80px;
padding-top: 23px;
}
.clearfix {
clear: both;
}
/* flex 사용 */
.header {
height: 80px;
display: flex;
justify-content: center;
align-items: center;
border-bottom: 1px solid gray;
}
.header-inner {
width: 900px;
height: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.logo {
width: 100px;
}
.logo h1 a {
text-decoration: none;
color: orange;
}
.menu__ul {
display: flex;
flex-direction: row;
}
.menu__ul li {
list-style: none;
}
.menu__ul li a {
display: block;
padding: 10px 20px;
text-decoration: none;
color: #000;
}
.user {
width: 100px;
}
거의 같은 html 구조에서 float는 더 많은 양의 코드를 요구하고 사용하기에도 편리하지 않다
하지만 flex는 더 간결하며 사용하기도 편리하기 때문에 요즘에는 float 구조는 잘 쓰지 않는다.
요번 주는 지난주에 배웠던 css에 대해 더 자세히 알아보는 시간이었다 세세하게 수업을 듣다 보니 확실히 이해하기 편했고 한번 배운 뒤 복습하는 느낌이라 더 쉽게 느껴지기도 했다.
아! 그리고 블로그 빼먹지 말자.. 2를 치는 양이 너무 많다