[JS]TIL(Today I Learned)_230905

Aspyn Choi·2023년 9월 5일
0

TIL

목록 보기
32/37

☝🏻오늘 배운 것

1. 간이계산기2

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>05_간이계산기2</title>
</head>
<body>
    
    <h1>간이 계산기 만들기</h1>

    첫번째 값 : <input type="number" id="num1"><br>
    두번째 값 : <input type="number" id="num2"><br>

    <button onclick="calculate(this)">+</button>
    <button onclick="calculate(this)">-</button>
    <button onclick="calculate(this)">*</button>
    <button onclick="calculate(this)">/</button>
    <button onclick="calculate(this)">%</button>
    <br>
    <br>

    계산 결과 : <span id="result"></span>

    <script>

        function calculate(btn){

        // btn에는 this(클릭된 버튼 요소)가 전달되어짐
        console.log(btn);

        const op = btn.innerText; // 버튼의 내용(+-*/%)을 얻어옴

        // 함수 호출 시 매개변수 this 이벤트가 발생한 요소 자체를 의미한다.

        // input에 입력된 값을 얻어와 number 타입으로 변환
        const num1 = Number( document.getElementById("num1").value );
        const num2 = Number( document.getElementById("num2").value );

        // 결과 저장용 변수
        let rs = 0;

        switch(op){
            case '+' : rs = num1 + num2; break;
            case '-' : rs = num1 - num2; break;
            case '*' : rs = num1 * num2; break;
            case '/' : rs = num1 / num2; break;
            case '%' : rs = num1 % num2; break;
        }

        // span 태그에 결과 출력
        document.getElementById("result").innerText = rs;
        }

    </script>
    
</body>
</html>

2. 간이계산기3

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>05_간이계산기3</title>
</head>
<body>
    
    <h1>간이 계산기 만들기</h1>

    첫번째 값 : <input type="number" id="num1"><br>
    두번째 값 : <input type="number" id="num2"><br>

    <button onclick="calculate(this)">+</button>
    <button onclick="calculate(this)">-</button>
    <button onclick="calculate(this)">*</button>
    <button onclick="calculate(this)">/</button>
    <button onclick="calculate(this)">%</button>
    <br>
    <br>

    계산 결과 : <span id="result"></span>

    <script>

        function calculate(btn){

        // btn에는 this(클릭된 버튼 요소)가 전달되어짐
        console.log(btn);

        const op = btn.innerText; // 버튼의 내용(+-*/%)을 얻어옴

        // 함수 호출 시 매개변수 this 이벤트가 발생한 요소 자체를 의미한다.

        // input에 입력된 값을 얻어와 number 타입으로 변환
        const num1 = Number( document.getElementById("num1").value );
        const num2 = Number( document.getElementById("num2").value );

        // eval("코드 형식 문자열")
        // -> 작성된 문자열을 JS코드로 해석하는 함수
        // -> 속도+보안 이슈가 있어서 사용을 지양함

        // -> 해결방법 : new Function() 사용
        document.getElementById("result").innerText = new Function("return " + num1 + op + num2)();
        
        }

    </script>
    
</body>
</html>

3. 이벤트 (Event)

이벤트(Event) : 동작, 행위
-> 브라우저의 동작, 행위 : click, keyup, keydown, mouseover, drag, change, submit...
https://www.w3schools.com/jsref/dom_obj_event.asp
-> 다양한 이벤트 참조
이벤트 리스너(Event Listener)
-> 이벤트가 발생하는 것을 대기하고 있다가
이벤트가 발생하는 것이 감지되면 연결된 기능(함수)를 수행하는 것
ex) onclick, onkeyup, onchange, onsubmit ...(on 이벤트명)
이벤트 핸들러(Event Handler)
-> 이벤트 리스너에 연결된 기능으로
이벤트 발생 시 수행하고자 하는 내용을 작성해둔 함수

4. 이벤트 모델

- 인라인 이벤트 모델

요소 내부에 이벤트를 작성하는 방법으로 'on이벤트명 = 함수명()' 형태로 작성함.

<button onclick="test1(this)">인라인 이벤트 모델 확인</button>

function test1(btn){
    console.log(btn);

    btn.style.backgroundColor = "black";
    btn.style.color = "white";
}

- 고전 이벤트 모델

요소가 가지고 있는 이벤트 속성(이벤트 리스너)에 이벤트핸들러를 연결하는 방법으로
인라인모델처럼 HTML요소에 JS코드를 포함시키는 것이 아님.
script 에서만 이벤트 관련 코드를 작성할 수 있다.

주의사항
고전/표준 이벤트 모델은 랜더링된 HTML요소에 이벤트에 관련된 동작을 부여하는 코드이다.
-> 랜더링이 되지 않은 요소에는 관련 동작을 추가할 수 없다!
(문제원인 : HTML코드 해석 순서 위 - > 아래)

-> 해결방법 : HTML요소가 먼저 랜더링 된 후 JS코드를 수행할 수 있도록 body태그 맨 아래 script태그를 넣는다.

  • 고전 이벤트 모델 확인하기
<button id="test2-1">고전 이벤트 모델 확인</button>

document.getElementById("test2-1").onclick = function(){
    // 익명함수 = function() -> 이벤트 핸들러에 많이 사용함

    alert("고전 이벤트 모델로 출력된 대화 상자");
}
  • 고전 이벤트 모델 제거
<button id="test2-2">고전 이벤트 모델 제거</button>

// 이벤트 제거
document.getElementById("test2-2").onclick = function(){
    document.getElementById("test2-1").onclick = null;
}
  • 고전 이벤트 모델 단점

    고전 이벤트 모델 단점
    -> 한 요소에 동일한 이벤트 리스너(onclick)에 대한 다수의 이벤트 핸들러(배경색변경,폰트크기변경 등)를 작성할 수 없다. (마지막으로 해석된 이벤트 핸들러만 적용)

<button id="test2-3">고전 이벤트 모델 단점</button>

document.getElementById("test2-3").onclick = function(event){
    // 버튼 색 바꾸기
    // 방법 1) 요소를 문서에서 찾아서 선택
    // document.getElementById("test2-3").style.backgroundColor = "pink";

    // 방법 2) 매개변수 e 또는 event 활용하기
    // -> 이벤트 핸들러에 e 또는 event를 작성하는 경우
    // 해당 이벤트와 관련된 모든 정보가 담긴 이벤트객체가 반환된다.
    // console.log(event);
    // event.target : 이벤트가 발생한 요소
    // event.target.style.backgroundColor = "pink";
    
    // 방법 3) this 활용하기 -> 이벤트가 발생한 요소
    this.style.backgroundColor = "pink";
}

document.getElementById("test2-3").onclick = function(){
    this.style.fontSize = "30px";
}

- 표준 이벤트 모델(addEventListener)

[작성법]
요소.addEventListener("click", function() {})

  • W3C (HTML, CSS, JS 웹표준 지정 단체)에서 공식적으로 지정한 이벤트 모델(이벤트 동작 지정 방법)
  • 한 요소에 여러 이벤트 핸들러를 설정할 수 있음.
    -> 고전 이벤트 모델 단점 보완
<div id="test3">클릭하면 크기가 늘어나요!</div>


document.getElementById("test3").addEventListener("click", function(){

    console.log(this.clientWidth); // 현재 요소의 너비(테두리 제외)

    this.style.width = this.clientWidth + 20 + "px";

});

// test3에 이미 click 이벤트에 대한 동작이 존재하는데,
// 중복해서 적용이 되었음(고전 이벤트 모델 문제점 해결 확인)
document.getElementById("test3").addEventListener("click", function(){

    this.style.height = this.clientHeight + 20 + "px";

});

- 이벤트 복습 문제

색상을 영어로 입력한 후 변경 버튼을 클릭하면 #div1의 배경색이 변경되도록 하시오.

	<div id="div1"></div>
    <input id="input1">
    <button id="changeBtn1">변경</button>
  • 1번 방법
document.getElementById("changeBtn1").addEventListener("click", function(){

    const input1 = document.getElementById("input1").value;

    document.getElementById("div1").style.backgroundColor = input1;

    // 선생님 풀이
    // const div1 = document.getElementById("div1");
    // const iput1 = document.getElementById("input1");

    // const bgColor = input1.value;

    // div1.style.backgroundColor = bgColor;

});
  • 2번 방법
// input1에 작성한 값이 변경되었을 때 입력된 값으로 배경색 변경
document.getElementById("input1").addEventListener("change", function(){

    // change 이벤트
    // - text관련 input태그는
    // 입력된 값이 변할 때를 change라고 하지 않고

    // 입력이 완료된 후 포커스를 잃거나, 엔터를 입력하는 경우에
    // 입력된 값이 이전값과 다르면 change이벤트가 발생한것으로 인식

    console.log("change 이벤트 발생");

    const div1 = document.getElementById("div1");
    const iput1 = document.getElementById("input1");

    const bgColor = input1.value;

    div1.style.backgroundColor = bgColor;
});

5. HTML 요소 기본 이벤트 제거

- a태그 기본 이벤트 제거

<a id="moveNaver" href="https://www.naver.com">네이버로 이동</a>


// a태그 기본 이벤트 제거
document.getElementById("moveNaver").addEventListener("click", function(e){
    // 매개변수 e또는 event == 이벤트 발생 객체
    // 이벤트와 관련된 정보가 담겨있는 객체

    e.preventDefault(); // HTML요소가 가지고있는 기본 이벤트를 막음(제거)
});

6. 정규표현식

- 정규표현식

: 특정한 규칙을 가진 문자열 집합을 표현하는데 사용하는 형식 언어.
: 정규표현식을 이용하면 입력된 문자열에 대한 특정 조건 검색, 일치 여부 판단, 치환에 대한 조건문을 간단히 처리할 수 있다.

- 정규 표현식 참고 사이트

작성한 정규표현식을 그림으로 나타내주는 사이트 : https://regexper.com/
작성한 정규표현식 테스트 사이트 : http://regexr.com/

- 정규 표현식 객체 생성 및 확인하기

  1. 정규표현식 객체 생성 방법
    1) const regExp = new regEx("정규표현식");
    2) const regExp = /정규표현식/;
    -> 양쪽 '/'기호는 정규표현식의 리터럴 표기법

  2. 문자열 패턴 확인하는 메서드(함수)
    1) regExp.test(문자열)
    -> 문자열에 정규표현식과 일치하는 패턴이 있을 경우 true, 없으면 false
    2) regExp.exec(문자열)
    -> 문자열에 정규표현식과 일치하는 패턴이 있을 경우 처음 매칭되는 문자열을 반환, 없으면 null 반환

<button id="check1">확인하기</button>

// 정규 표현식 객체 생성 + 확인하기
document.getElementById("check1").addEventListener("click", function(){

    // 정규표현식 객체 생성
    const regExp1 = new RegExp("script");
                // "script"와 일치하는 문자열이 있는지 검사하는 정규표현식

    const regExp2 = /java/;
                // "java"와 일치하는 문자열이 있는지 검사하는 정규표현식

    // 확인하기
    const str1 = "저희는 지금 javascript를 공부하고 있습니다.";
    const str2 = "servlet/jsp(java server page)도 조만간 할겁니다.";
    const str3 = "java, java, java";

    console.log( "regExp1.test(str1) : " + regExp1.test(str1) );
    console.log( regExp1.exec(str1) );

    console.log( "regExp2.test(str2) : " + regExp2.test(str2) );
    console.log( regExp2.exec(str2) );

    // 일치하는게 없을 경우
    console.log( "regExp1.test(str2) : " + regExp1.test(str2) );
    console.log( regExp1.exec(str2) );

    // 일치하는게 여러개 있을 경우
    console.log( "regExp2.test(str3) : " + regExp2.test(str3) );
    console.log( regExp2.exec(str3) ); 
});

- 정규표현식의 메타 문자

  • 정규표현식의 메타 문자

    문자열의 패턴을 나타내는 문자. 문자마다 지정된 특별한 뜻이 담겨있다.

        a (일반문자열) : 문자열 내에 a라는 문자열이 존재하는지 검색
        [abcd] : 문자열 내에 a,b,c,d 중 하나라도 일치하는 문자열이 존재하는지 검색
        ^ (캐럿) : 문자열의 시작을 의미
        $ (달러) : 문자열의 끝을 의미
    
        \w (단어) : 아무 글자(단, 띄어쓰기, 특수문자, 한글 X)
        \d (숫자) : 아무 숫자(0~9 중 하나)
        \s (공간) : 아무 공백 문자(띄어쓰기, 엔터, 탭 등)
    
        [0-9] : 0부터 9까지 모든 숫자
        [ㄱ-힣] : ㄱ부터 힣까지 모든 한글
        [a-z] : 모든 영어 소문자
        [A-Z] : 모든 영어 대문자
    
        * 특수문자의 경우 각각을 입력하는 방법밖엔 없음
    
        * 수량 관련 메타 문자
        a{5} : a문자가 5개 존재
        a{2,5} : a가 2개 이상 5개 이하
        a{2, } : a가 2개 이상
        a{ ,5} : a가 5개 이하
    
        * : 0개 이상
        + : 1개 이상
        ? : 0개 또는 1개
        . : 1칸 (개행문자를 제외한 문자 하나)
    
       \*, \+, \?, \. : *+?\가 있는지
<button id="btn1">확인하기</button>
    <div id="div1" class="area"></div>


// 메타 문자 확인하기
document.getElementById("btn1").addEventListener("click", function(){
    
    const div1 = document.getElementById("div1");

    // a (일반문자열) : 문자열 내에 a라는 문자열이 존재하는지 검색
    const regExp1 = /a/;
    div1.innerHTML += "/a/, apple : " + regExp1.test("apple") + "<hr>"; // true
    div1.innerHTML += "/a/, price : " + regExp1.test("price") + "<hr>"; // false

    // [abcd] : 문자열 내에 a,b,c,d 중 하나라도 일치하는 문자열이 존재하는지 검색
    const regExp2 = /[abcd]/;
    div1.innerHTML += "[abcd], apple : " + regExp2.test("apple") + "<hr>";
    div1.innerHTML += "[abcd], ssbss : " + regExp2.test("ssbss") + "<hr>";
    div1.innerHTML += "[abcd], qwerty : " + regExp2.test("qwerty") + "<hr>";
   
    // ^ (캐럿) : 문자열의 시작을 의미
    const regExp3 = /^group/; // 문자열의 시작이 group인지 확인
    div1.innerHTML += "/^group/, group100 : " + regExp3.test("group100") + "<hr>";
    div1.innerHTML += "/^group/, 100group : " + regExp3.test("100group") + "<hr>";

    // $ (달러) : 문자열의 끝을 의미
    const regExp4 = /group$/; // 문자열의 끝이 group인지 확인
    div1.innerHTML += "/^group/, group100 : " + regExp4.test("group100") + "<hr>";
    div1.innerHTML += "/^group/, 100group : " + regExp4.test("100group") + "<hr>";
});

- 이름 유효성 검사

<h5>한글 2~5글자</h5>
    이름 : <input type="text" id="inputName"> <br>
    <span id="inputNameResult"></span>

// 이름 유효성 검사
document.getElementById("inputName").addEventListener("keyup", function(){

    // 결과 출력용 span
    const span = document.getElementById("inputNameResult");

    // 한글 2~5글자 정규표현식
    const regExp = /^[가-힣]{2,5}$/;

    // 빈칸인지 검사
    if(this.value.length == 0){
        span.innerText = "";
        return;
    }

    // 유효성 검사
    if( regExp.test(this.value) ){
        // 유효한 경우
        span.innerText = "유효한 이름 형식입니다";
        span.style.color = "green";
        span.style.fontWeight = "bold";        
    }else{
        span.innerText = "유효하지 않은 형식입니다";
        span.style.color = "red";
        span.style.fontWeight = "bold";        
    }
});

- 주민등록번호 유효성 검사

<h3>주민등록번호 유효성 검사</h3>
    주민등록번호 : <input type="text" id="inputPno"> <br>
    <span id="inputPnoResult"></span>


// 주민등록번호 유효성 검사
document.getElementById("inputPno").addEventListener("keyup", function(){

    const span = document.getElementById("inputPnoResult");

    if(this.value.length == 0 ){
        span.innerText = "주민등록번호를 작성해주세요";
        
        span.classList.remove("comfirm");
        span.classList.remove("error");

        return;
    }
    // 생년월일(6)-고유번호(7)
    const regExp = /^\d{6}\-\d{7}$/;

    if(regExp.test(this.value)){
        span.innerText = "유효한 주민등록번호 형식입니다.";

        span.classList.remove("error");
        span.classList.add("confirm");
    }else{
        span.innerText = "유효하지 않습니다";

        span.classList.remove("confirm");
        span.classList.add("error");
    }
});

7. 정규표현식 연습문제

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>07_회원가입양식</title>
    <style>
        .btn-area{    text-align: right; }
        td{ padding: 5px; }
        fieldset{ width: 430px;}
        span{font-size: 14px;}
        .confirm{ color : green; }
        .error{ color : red; }
    </style>
</head>
<body>
    <form action="main.html" method="post" onsubmit="return validate()">
        <fieldset>
            <legend>회원 가입 양식</legend>

            <table>
                <tr>
                    <td>아이디</td>
                    <td>
                        <input type="text" id="inputId">
                    </td>
                    <td>
                        <button type="button">중복확인</button>
                    </td>
                </tr>
                <tr>
                    <td>비밀번호</td>
                    <td>
                        <input type="password" id="inputPw">
                    </td>
                    <td>
                        <span id="pwMessage"></span>
                    </td>
                </tr>
                <tr>
                    <td>비밀번호확인</td>
                    <td>
                        <input type="password" id="inputPwConfirm">
                    </td>
                    <td></td>
                </tr>
                <tr>
                    <td>이름</td>
                    <td>
                        <input type="text" id="inputName">
                    </td>
                    <td>
                        <span id="nameMessage"></span>
                    </td>
                </tr>
                <tr>
                    <td>성별</td>
                    <td>
                        <label><input type="radio" name="gender" value="m"></label> 
                        <label><input type="radio" name="gender" value="f"></label> 
                    </td>
                    <td></td>
                </tr>
                <tr>
                    <td>전화번호</td>
                    <td>
                        <input type="text" id="inputTel">
                    </td>
                    <td></td>
                </tr>
                <tr>
                    <td>이메일</td>
                    <td>
                        <input type="text" id="inputEmail">
                    </td>
                    <td></td>
                </tr>
                <tr>
                    <td></td>
                    <td class="btn-area">
                        <button type="reset">초기화</button>
                        <button>회원가입</button>
                    </td>
                    <td></td>
                </tr>
            </table>
        </fieldset>
    </form>


        

    <script src="js/07_회원가입양식.js"></script>
</body>
</html>
// 유효성 검사 객체
const checkObj = {
    "inputId" : false, // 아이디
    "inputPw" : false, // 비번
    "inputPwConfirm" : false, // 비번확인
    "inputName" : false, // 이름
    "gender" : false, // 성별
    "inputTel" :false // 전화번호
}

// 아이디
document.getElementById("inputId").addEventListener("change", function(){

    const regExp = /^[a-z]+[\w\d\-\_]{5,13}/g;

    // if(this.value.length == 0){
    //     return;
    // }

    if( regExp.test(this.value) ){
        this.style.backgroundColor = "springgreen";

        checkObj.inputId = true; // 유효성검사객체 중 아이디 값 true로 바꿔주기
    }else{
        this.style.backgroundColor = "red";
        this.style.color = "white";

        checkObj.inputId = false; // 유효성검사객체 중 아이디 값 false로 바꿔주기
    }
});

// 비밀번호

const inputPw = document.getElementById("inputPw");
const inputPwConfirm = document.getElementById("inputPwConfirm");

inputPwConfirm.addEventListener("keyup", function(){

    if(inputPw.value.length == 0){

        this.value = "";
        alert("비밀번호를 입력해주세요");
        inputPw.focus();

        checkObj.inputPw = false;
    }
});

const pwMessage = document.getElementById("pwMessage");    

inputPw.addEventListener("keyup", function(){

    if( (inputPw.value == inputPwConfirm.value) && inputPw.value.length != 0){
        pwMessage.innerText = "비밀번호 일치"

        pwMessage.classList.add("confirm");
        pwMessage.classList.remove("error"); 
        
        checkObj.inputPw = true;
        checkObj.inputPwConfirm = true;
    }else{
        pwMessage.innerText = "비밀번호 불일치"

        pwMessage.classList.remove("confirm");
        pwMessage.classList.add("error"); 

        checkObj.inputPwConfirm = false;
    }
});

inputPwConfirm.addEventListener("keyup", function(){
    if( (inputPw.value == pwConfirm.value) && inputPw.value.length != 0){
        pwMessage.innerText = "비밀번호 일치"

        pwMessage.classList.add("confirm");
        pwMessage.classList.remove("error"); 
        
        checkObj.inputPw = true;
        checkObj.inputPwConfirm = true;
    }else{
        pwMessage.innerText = "비밀번호 불일치"

        pwMessage.classList.remove("confirm");
        pwMessage.classList.add("error"); 

        checkObj.inputPwConfirm = false;
    }
});


// 이름
document.getElementById("inputName").addEventListener("change", function(){

    const regExp = /^[가-힣]{2,5}$/;
    const span = document.getElementById("nameMessage");

    if(this.value.length == 0){
        span.innerText = "";
        span.classList.remove("confirm");
        span.classList.remove("error"); 
    }

    if( regExp.test(this.value) ){
        span.innerText = "정상입력";

        span.classList.add("confirm");
        span.classList.remove("error"); 

        checkObj.inputName = true;
    }else{
        span.innerText = "한글만 입력하세요";
        
        span.classList.remove("confirm");
        span.classList.add("error"); 

        checkObj.inputName = false;
    }
});

function validate(){
    
    // 성별
    const gender = document.getElementsByName("gender");

    if( !gender[0].checked && !gender[1].checked ){
        alert("성별을 선택해주세요");

        checkObj.gender = false;
        return false;
    }else{
        checkObj.gender = true;
    }
    
    
    // 전화번호
    const inputTel = document.getElementById("inputTel");
    const regExp = /^[0][0-9]{1,2}-[0-9]{3,4}-[0-9]{4}/;

    if( !regExp.test(inputTel.value) ){
        alert("전화번호의 형식이 올바르지 않습니다");
        checkObj.inputTel = false;
        return false;
    }else{
        checkObj.inputTel = true;
    }
    

    // checkObj가 전부 true일 떄 == 모든 유효성 검사를 통과했을 때 -> 회원가입
    for(let key in checkObj){
        if( !checkObj[key] ){
            return false;
        }
    }

    alert("회원가입 완료");
    return true;

}

0개의 댓글