[JavaScript] Table을 Excel 처럼 즉시 수정가능하게 만들기[JavaScript] Table을 Excel 처럼 즉시 수정가능하게 만들기

Posted at 2020. 6. 24. 09:46 | Posted in JavaScript & jQuery/JavaScript




주의 : 해당 포스팅의 샘플 코드에서 사용하는 addEventListener( ) 메서드의 경우 Internet Explorer에서는 정상적으로 작동하지 않습니다.

           호환되지 않는 Internet Explorer에서의 사용의 경우는 addEventListener( ) 메서드를 attachEven( )로 변경하여 작업을 진행하셔야 합니다.






contenteditable 속성을 이용한 텍스트 내용 수정




기본적으로 웹 환경에서 값을 변경하기 위해서는 <input type="text" value="값">이 기본 형태였지만.


HTML5가 나오면서 contenteditable을 이용해 좀더 재미있는 사용자 경험을 제공할 수 있게 되었다.


해당 포스팅에서는 웹 페이지에 출력된 텍스트 문구를 contenteditable 속성을 이용하여 수정해 보려 한다.




# 소스코드

<html>
<head>
<title>:: JavaScript Contenteditable ::</title>
</head>
<body>
<p contenteditable="false">
    이 단락은 편집을 원하는 경우 더블 클릭해 주세요
</p>
</body>
</html>
<script type="text/javascript">

    // @breif contenteditable 속성을 가진경우
    var content = document.querySelector( "[contenteditable]" );
    var edtButton = document.querySelector( "button" );

    document.addEventListener("DOMContentLoaded", function() {

        // @breif 더블클릭시 실행
        content.addEventListener("dblclick", function(event) {

            // @details contenteditable 속성이 수정 불가인 경우 실행( false )
            if(content.isContentEditable == false) {

                // @details 편집 가능 상태로 변경
                content.contenteditable = true;

                // @details 텍스트 문구 변경
                content.textContent = "편집 가능한 상태로 변경되었습니다.";

                // @details CSS 효과 추가
                content.style.border = "1px solid #FE7F9C";

                // @details 포커스 지정
                content.focus();
            }

            // @details contenteditable 속성이 수정 가능인 경우 실행( true )
            else {

                // 편집 불가 상태로 변경
                content.contenteditable = false;
                content.style.border = "0px";
            }
        });
    });
</script>




# 출력결과












■ 테이블을 엑셀처럼 즉시 변경가능하게 만들기





이제 contenteditable 태그를 좀더 심도있게 활용을 해보자.


바로 테이블에 출력되어 있는 내용을 엑셀처럼 즉시 수정을 하고 해당내용을 적용하는 것이다.


즉각적으로 수정된 내용을 데이타 베이스( DataBase )에 적용하는 예제는 아니지만.


해당 내용의 결과물을 본다면 어떻게 사용하는것이 좋을지 바로 감이 올 거라 생각한다.



# 소스코드

<html>

<head>

<title>:: JavaScript Contenteditable ::</title>

<style type="text/css">

    table { border-collapse:collapse;border:1px gray solid; }

    .rowColumn { border-radius:5px;margin:5px; }

</style>

</head>

<body>

<table border="1">

    <thead>

        <tr>

            <th style="width:50px;">번호</th>

            <th style="width:120px;">가수</th>

            <th style="width:350px;">노래</th>

            <th style="width:100px;">발매일</th>

        </tr>

    </thead>

    <tbody>

        <tr>

            <td style="text-align:center;">1</td>

            <td>

                <p class="rowColumn" contenteditable="false" data-default="윤하">윤하</p>

            </td>

            <td>

                <p class="rowColumn" contenteditable="false" data-default="오렌지 첫사랑">오렌지 첫사랑</p>

            </td>

            <td>

                <p class="rowColumn" contenteditable="false" data-default="2007-10-23">2007-10-23</p>

            </td>

        </tr>

        <tr>

            <td style="text-align:center;">2</td>

            <td>

                <p class="rowColumn" contenteditable="false" data-default="도원경">도원경</p>

            </td>

            <td>

                <p class="rowColumn" contenteditable="false" data-default="다시 사랑한다면">다시 사랑한다면</p>

            </td>

            <td>

                <p class="rowColumn" contenteditable="false" data-default="2001-05-01">2001-05-01</p>

            </td>

        </tr>

        <tr>

            <td style="text-align:center;">3</td>

            <td>

                <p class="rowColumn" contenteditable="false" data-default="더더">더더</p>

            </td>

            <td>

                <p class="rowColumn" contenteditable="false" data-default="it's You">it's You</p>

            </td>

            <td>

                <p class="rowColumn" contenteditable="false" data-default="1998-11-01">1998-11-01</p>

            </td>

        </tr>

        <tr>

            <td style="text-align:center;">4</td>

            <td>

                <p class="rowColumn" contenteditable="false" data-default="박기영">박기영</p>

            </td>

            <td>

                <p class="rowColumn" contenteditable="false" data-default="시작">시작</p>

            </td>

            <td>

                <p class="rowColumn" contenteditable="false" data-default="1999-04-07">1999-04-07</p>

            </td>

        </tr>

        <tr>

            <td style="text-align:center;">5</td>

            <td>

                <p class="rowColumn" contenteditable="false" data-default="이소은">이소은</p>

            </td>

            <td>

                <p class="rowColumn" contenteditable="false" data-default="오래오래">오래오래</p>

            </td>

            <td>

                <p class="rowColumn" contenteditable="false" data-default="2002-12-21">2002-12-21</p>

            </td>

        </tr>

    </tboyd>

</talbe>

</body>

</html>

<script type="text/javascript">


    // @breif contenteditable 속성을 가진경우

    var contents = document.getElementsByClassName("rowColumn");


    document.addEventListener("DOMContentLoaded", function() {


        // @breif rowColumn 클래스의 갯수 만큼 반복문을 실행한다.

        Array.from(contents).forEach(function(content) {


            // @breif 마우스로 해당영역을 더블클릭 한경우

            content.addEventListener("dblclick", function(event) {


                // @breif 전체 테이블 컬럼( td > p )에서 현재 사용중인 값의 존재여부를 확인한다.

                Array.from(contents).forEach(function(defaultVal) {


                    /*
                    // @details 빈값( null )이 존재하는지 체크한다.
                    if(
                           defaultVal.textContent == ""
                        || defaultVal.textContent == null
                        || defaultVal.textContent == undefined
                        || (defaultVal.textContent != null
                        && typeof defaultVal.textContent == "object"
                        && !Object.keys(defaultVal.textContent).length == ""))
                    {

                        // @details 내용이 존재하지 않다면 data 태그의 기본값으로 되돌린다.
                        defaultVal.textContent = defaultVal.dataset.default;
                    }
                    */

                    // @details 저장하지 않은 내용이라고 판단하여 data 태그의 기본값으로 되돌린다.
                    defaultVal.textContent = defaultVal.dataset.default;

                    // @breif 수정 불가 상태로 되돌린다.

                    defaultVal.contenteditable = false;

                    defaultVal.style.border = "0px";

                });


                if(content.isContentEditable == false) {


                    // @details 편집 가능 상태로 변경

                    content.contenteditable = true;


                    // @details 텍스트 문구 변경

                    // content.textContent = "";


                    // @details CSS 효과 추가

                    content.style.border = "1px solid #FFB6C1";


                    // @details 포커스 지정

                    content.focus();

                }

            });


            // @breif 키보드 입력이 방생한 경우 실행

            content.addEventListener("keypress", function(event) {


                // @breif Enter키 입력시 실행

                if(event.key === "Enter") {


                    // @details 입력된 값이 빈값( null )인지 체크한다.

                    if(

                           content.textContent == ""

                        || content.textContent == null

                        || content.textContent == undefined

                        || (content.textContent != null

                        && typeof content.textContent == "object"

                        && !Object.keys(content.textContent).length == ""))

                    {


                        // @details 내용이 존재하지 않다면 data 태그의 기본값으로 되돌린다.

                        content.textContent = content.dataset.default;

                    } else {


                        // @details 내용의 수정이 완료되었다면 data 태그의 기본값도 바꿔준다.

                        content.dataset.default = content.textContent;

                    }


                    // @breif 수정 불가 상태로 되돌린다.

                    content.contenteditable = false;

                    content.style.border = "0px";

                }

            });

        });

    });

</script>




위 코드의 결과는 아래와 같이 직접 확인을 진행해 보자.




# 출력결과

번호

가수

노래

발매일

1

윤하

오렌지 첫사랑

2007-10-23

2

도원경

다시 사랑한다면

2001-05-01

3

더더

it's You

1998-11-01

4

박기영

시작

1999-04-07

5

이소은

오래오래

2002-12-21

주의해당 출력결과Internet Explorer에서는 정상적으로 작동하지 않습니다.



위에 가수, 노래, 발매일 항목을 마우스로 더블클릭( dblclick )하면 내용을 수정하고, 키보드 Enter 키를 눌러 변경한 내용을 반영할 수 있다.

( 단 공란( null )은 사용할 수 없게 처리되어 있다. )



또한 하나의 컬럼을 수정하던중 다른 컬럼을 더블클릭( dblclick )한 경우 수정중이던 컬럼영역은


data-default에 저장되어있는 기존값으로 다시 돌아가게 설계되어 있다.


이와같은 예외처리는 용도에 맞게 코드를 조금 손보면 바로 적용할 수 있을 것이다.





자체과제 : 심화코드 만들어보기






Name __

Password __

Link (Your Website)

Comment

SECRET | 비밀글로 남기기