Programming/JavaScript

[JavaScript] BOM: 링크 조작, 이미지 조작, 다량의 요소의 이벤트 처리 (일괄 처리)

Isaac S. Lee 2023. 10. 6. 11:50

🍁링크 조작


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>링크</h1>

    <a href="https://isaac-christian.tistory.com" name="link1">블로그</a>

    <hr>

    <input type="button" value="버튼" name="btn1">
</body>
</html>

document 아래에 forms가 없기 때문에 할아버지가 손자를 자식으로 취급하는 말이 안 되는 상황이 발생한다.

이렇게 폼이 없는 상황에서는 all을 사용해서 접근한다.

 

all을 사용하여 접근

<script>
    document.all['btn1'].onclick = m1;

    function m1() {
        alert();
    }
</script>

원래는 블로그 링크를 클릭하면 블로그로 이동하지만, 버튼을 클릭하면 링크가 [JavaScript] BOM과 DOM: HTML 계층 구조 글로 이동하는 걸로 바뀌게 했다.

그런데 사용자는 링크가 바뀌었는지 알기 어렵다. 이럴 때 풍선 도움말을 활용할 수 있다.

 

BOM

//BOM
document.links['link1'].href = 'https://isaac-christian.tistory.com/entry/JavaScript-BOM%EA%B3%BC-DOM';
document.links['link1'].target = '_blank';
document.links['link1'].title = '[JavaScript] BOM과 DOM: HTML 계층 구조';

풍선 도움말로 마우스를 올리면 어디로 이동하는지 알 수 있게 되었다.

하지만 링크의 이름 자체를 바꾸는 방법을 사용할 수도 있다.

 

DOM

document.links['link1'].innerText = '[JavaScript] BOM과 DOM: HTML 계층 구조';

 

🍁이미지 조작


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>이미지</h1>

    <input type="button" value="버튼" name="btn1">

    <hr>

    <img src="../asset/images/dog01.jpg" name="dog1">

    <script>
        document.all['btn1'].onclick = m1;

        function m1() {
            document.images['dog1'].src = '../asset/images/dog03.jpg';
        }
    </script>
</body>
</html>

버튼을 클릭하면 강아지 사진을 조작하여 다른 사진으로 변경한다.

 

Rollover Image (롤오버 이미지)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>이미지</h1>

    <input type="button" value="버튼" name="btn1">

    <hr>

    <img src="../asset/images/dog01.jpg" name="dog1">
    
    <hr>

    <img src="../asset/images/dog01.jpg" name="dog2">

    <script>
        document.all['btn1'].onclick = m1;

        function m1() {
            document.images['dog1'].src = '../asset/images/dog03.jpg';
        }

        document.images['dog2'].onmouseover = m2;
        document.images['dog2'].onmouseout = m3;

        function m2() {
            document.images['dog2'].src = '../asset/images/dog03.jpg';
        }

        function m3() {
            document.images['dog2'].src = '../asset/images/dog01.jpg';
        }
    </script>
</body>
</html>

마우스를 위에 올렸을 때 사진이 바뀌는 이미지를 롤오버 이미지라고 한다.

마우스가 사진 밖으로 빠져나갔을 때 원래 이미지를 기억하지 못하므로 새로 작성해 주어야 한다.

 

Toggle Image (토글 이미지)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>이미지</h1>
    
    <img src="../asset/images/switch_on.png" name="sw">
    
    <script>
        document.images['sw'].onclick = m1;
        document.images['sw'].onmouseout = m2;

        function m1() {
            //alert(document.images['sw'].src.endsWith('switch_on.png'));

            if (document.images['sw'].src.endsWith('switch_on.png')) {
                document.images['sw'].src = '../asset/images/switch_off.png';
                document.body.bgColor = '#000';
            } else {
                document.images['sw'].src = '../asset/images/switch_on.png';
                document.body.bgColor = '#FFF';
            }
        }
    </script>
</body>
</html>

버튼을 눌렀을 때 이미지를 on/off switch로 바꾸면서 배경색을 바꿔주었다.

 

Image Viewer

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>이미지</h1>

    <img src="../asset/images/0.png" name="num">

    <img src="../asset/images/circle_icon01.png" name="icon">

    <img src="../asset/images/dog01.jpg" name="viewer">
    
    <script>
    document.images['icon'].onclick = m1;
    var n = 1;

    function m1() {
        if (n < 18) {
            n++;
        }

        document.images['icon'].src = '../asset/images/circle_icon' + (n + '').padStart(2, '0') + '.png';
    }

    //방향키로 이미지 이동
    window.onkeydown = m2;
    var no = 1;

    function m2() {
        if (event.keyCode == 37) {
            no--;

            if (no < 1) {
                alert('처음 이미지입니다.');
                no++;
                return;
                //no = 5;
            }
        } else if (event.keyCode == 39) {
            no++;

            if (no > 5) {
                alert('마지막 이미지입니다.');
                no--;
                return;
                //no = 1;
            }
        }

        document.images['viewer'].src = '../asset/images/dog0' + no + '.jpg';

        if (event.keyCode >= 48 && event.keyCode <= 57) {
            document.images['num'].src = '../asset/images/' + (event.keyCode - 48) + '.png';
        }
    }
</script>
</body>
</html>

이미지에는 키 이벤트를 걸 수 없다. 키 이벤트는 입력을 할 수 있는 객체에 대해서만 걸 수 있기 때문이다.

그래서 키보드 좌우 키의 입력을 받아 이미지를 전환하도록 했다.

 

🍁다량의 요소의 이벤트 처리 (일괄 처리)


다량의 요소를 정적, 동적으로 처리하는 방법에 대해서 알아 보도록 하자.

 

정적으로 처리

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .item {
            border: 1px solid #CCC;
            background-color: #EEE;
            padding: 10px;
            width: 400px;
            text-align: center;
            margin: 15px;
        }
        .item > input[type=button] {
            border: 1px solid #CCC;
            background-color: #FFF;
            width: 100px;
            height: 60px;
            margin: 10px;
            outline: none;
        }
        .item > input[type=button]:hover {
            box-shadow: 0px 0px 10px #CCC;
        }
    </style>
</head>
<body>
    <h1>다량의 요소의 이벤트 처리 (일괄 처리)</h1>

    <form name="form1">
        
        <div class="item">
            <input type="button" name="btnRed" value="빨강" onclick="m1();">
            <input type="button" name="btnYellow" value="노랑" onclick="m2();">
            <input type="button" name="btnBlue" value="파랑" onclick="m3();">
        </div>

    </form>

    <script>
        function m1() {
            document.body.bgColor = 'tomato';
        }
        function m2() {
            document.body.bgColor = 'gold';
        }
        function m3() {
            document.body.bgColor = 'cornflowerblue';
        }
    </script>
</body>
</html>

onclick을 이용하여 이벤트 처리를 해보도록 하자.

정적 방식으로 구현하면 함수를 재사용하지 않기 때문에 코드가 낭비된다.

 

동적으로 처리

<body>
    <h1>다량의 요소의 이벤트 처리 (일괄 처리)</h1>

    <form name="form1">
        
        <div class="item">
            <input type="button" name="btnRed" value="빨강" onclick="m7('tomato');">
            <input type="button" name="btnYellow" value="노랑" onclick="m7('gold');">
            <input type="button" name="btnBlue" value="파랑" onclick="m7('cornflowerblue');">
        </div>

    </form>

    <script>
        function m7(color) {
            document.body.bgColor = color;
        }
    </script>
</body>

 

동적으로 처리: this

<body>
    <h1>다량의 요소의 이벤트 처리 (일괄 처리)</h1>

    <form name="form1">

        <div class="item">
            <input type="button" name="btnRed" value="빨강" onclick="m8(this);">
            <input type="button" name="btnYellow" value="노랑" onclick="m8(this);">
            <input type="button" name="btnBlue" value="파랑" onclick="m8(this);">
        </div>

    </form>

    <script>
        function m8(btn) {
            //alert(obj);
            //alert(btn.name);

            var color;

            if (btn.name == 'btnRed') {
                color = 'tomato';
            } else if (btn.name == 'btnYellow') {
                color = 'gold';
            } else if (btn.name == 'btnBlue') {
                color = 'cornflowerblue';
            }
            
            document.body.bgColor = color;
        }
    </script>
</body>

this는 상대 표현으로, event가 걸린 태그 자신을 의미한다.

this를 이용하면 누가 나를 호출했는지 알 수 있다.

 

식별자 추출

<body>
    <h1>다량의 요소의 이벤트 처리 (일괄 처리)</h1>

    <form name="form1">

        <div class="item">
            <input type="button" name="btnRed" value="빨강" onclick="m9(this);">
            <input type="button" name="btnYellow" value="노랑" onclick="m9(this);">
            <input type="button" name="btnBlue" value="파랑" onclick="m9(this);">
        </div>

    </form>

    <script>
        function m9(btn) {
            document.body.bgColor = btn.name.substr(3);
        }
    </script>
</body>

식별자의 단어를 추출해서 값으로 사용할 수도 있지만, 식별자 자체에 다른 의미를 가지게 하는 것은 좋지 않다.

식별자는 식별자의 역할로 끝나야 한다.

 

🍂사용자 정의 속성

<body>
    <h1>다량의 요소의 이벤트 처리 (일괄 처리)</h1>

    <form name="form1">

        <div class="item">
            <input type="button" name="btnRed" value="빨강" data-color="tomato" onclick="m10(this);">
            <input type="button" name="btnYellow" value="노랑" data-color="gold" onclick="m10(this);">
            <input type="button" name="btnBlue" value="파랑" data-color="cornflowerblue" onclick="m10(this);">
        </div>

    </form>

    <script>
        function m10(btn) {
            //alert(btn.dataset['color']);
            document.body.bgColor =  btn.dataset['color'];
        }
    </script>
</body>

모든 HTML 태그에는 사용자 정의 속성을 정의할 수 있다.

이는 자바스크립트 용도로, HTML 용도가 아니다.

내가 원하는 이름이 color라면 name이나 value와 구분이 안 되기 때문에 'data-' 접두어를 붙이도록 한다.

이는 dataset 내장 배열에 저장된다.

일괄적으로 이벤트를 처리할 때, 사용할 수 있는 방법 중 사용자 정의 속성을 이용하는 방법이 가장 깔끔하고 체계적인 방법이다.

 

srcElement.name, target

<body>
    <h1>다량의 요소의 이벤트 처리 (일괄 처리)</h1>

    <form name="form1">
    
        <div class="item">
            <input type="button" name="btnRed" value="빨강" data-color="tomato" onclick="m11();">
            <input type="button" name="btnYellow" value="노랑" data-color="gold" onclick="m11();">
            <input type="button" name="btnBlue" value="파랑" data-color="cornflowerblue" onclick="m11();">
        </div>

    </form>

    <script>
        function m11(btn) {
            //alert(event.srcElement.name); //비표준(MS)
            //alert(event.target.name); //표준
            document.body.bgColor = event.target.dataset['color'];
        }
    </script>
</body>

this를 지웠지만, 어떤 버튼을 눌렀는지 알아내는 방법이 있다.

event.srcElement와 event.target이 this의 역할을 하여 이벤트를 발생시킨 객체가 눌린 버튼을 알려준다.

event.target이 표준 방식이므로 target을 이용하도록 한다.

 

동적으로 처리

<body>
    <h1>다량의 요소의 이벤트 처리 (일괄 처리)</h1>

    <form name="form1">

        <div class="item">
            <input type="button" name="btnRed3" value="빨강" data-color="tomato">
            <input type="button" name="btnYellow3" value="노랑" data-color="gold">
            <input type="button" name="btnBlue3" value="파랑" data-color="cornflowerblue">
        </div>
        
    </form>

    <script>
        document.form1.btnRed3.onclick = m12;
        document.form1.btnYellow3.onclick = m12;
        document.form1.btnBlue3.onclick = m12;

        function m12() {
            document.body.bgColor = event.target.dataset['color'];
        }
    </script>
</body>

위 방식을 동적으로 처리하였다.

 

🍂식별자의 이름을 똑같이 설정

<body>
    <h1>다량의 요소의 이벤트 처리 (일괄 처리)</h1>

    <form name="form1">

        <div class="item">
            <input type="button" name="btn" value="빨강" data-color="tomato">
            <input type="button" name="btn" value="노랑" data-color="gold">
            <input type="button" name="btn" value="파랑" data-color="cornflowerblue">
            <input type="button" name="btn" value="주황" data-color="orange">
            <input type="button" name="btn" value="초록" data-color="yellowgreen">
        </div>
        
    </form>

    <script>
        // alert(document.form1.btn.length); //배열

        for (var i=0; i<document.form1.btn.length; i++) {
            document.form1.btn[i].onclick = m13;
        }

        function m13() {
            document.body.bgColor = event.target.dataset['color'];
        }
    </script>
</body>

태그 이름이 동일한 객체가 2개 이상이면 배열이 된다. 식별자의 이름을 같지만 구분이 가능하다.

이 방법이 생산성이 높은 이유는 버튼을 추가하더라도 data-color만 설정해주기만 하면 자바스크립트를 수정할 필요가 없기 때문이다.

 

type

<body>
    <h1>다량의 요소의 이벤트 처리 (일괄 처리)</h1>

    <img src = "../asset/images/dog01.jpg" name="dog">
    <img src = "../asset/images/dog02.jpg" name="dog">
    <img src = "../asset/images/dog03.jpg" name="dog">
    <img src = "../asset/images/dog04.jpg" name="dog">
    <img src = "../asset/images/dog05.jpg" name="dog">

    <hr>

    <img src = "../asset/images/cat01.jpg" name="cat">

    <script>
        //alert(document.images['dog'].length); //X

        for (var i=0; i<document.images.length; i++) {
            if (document.images[i].name == 'dog') {
                document.images[i].onclick = m14;
                //document.images[i].onmouseover = m14;
            }

            function m14() {
                if (event.target.width == 250) {
                    event.target.width = 500;
                } else {
                    event.target.width = 250;
                }
            }
        }
    </script>
</body>

어떤 태그에서 이벤트가 일어났는지를 알고 싶으면 event.target을 사용하면 된다.

그리고 어떤 이벤트가 발생했는지를 알고 싶으면 event.type을 사용하면 된다.