[textarea 리사이징]

사용자의 입력값에 따라 textarea 크기가 자동으로 조정되는 auto-resizing 기능이 있는 아래와 같은 textarea를 구현해보자.

1. 유저가 값을 입력했을 때 textarea 영역의 높이를 자동으로 증가/축소시킨다

2. 입력 가능한 라인 수(textarea 높이)는 제한한다

3. 입력시엔 textarea를 사용하고, 노출(읽기모드)시엔 textarea 대신 border가 없는 다른 tag를 사용한다

 

[구현에 필요한 사전지식]

1. HTML DOM element 와 jQuery Object

this 사용시 this가 jQuery Object 인지 DOM element 인지 명확히 구분해야 한다. (참고1, 참고2)

1. $(): jQuery Object
2. $var: jQuery 변수
3. $.each(function(){ 여기서 this는 DOM element }) 
4. jQuery Object에서 DOM element를 꺼내는 방법
- $(el).get(0)
- $(el)[0]

2. offsetHeight, clientHeight, scrollHeight 의 차이 (참고)

1. clientHeight : returns the inner height of an element in pixels, including padding but not the horizontal scrollbar height, border, or margin
padding을 포함한 엘리먼트의 pixel 높이를 리턴, 가로스크롤바의 높이, border, margin 값은 포함하지 않음

2. offsetHeight : is a measurement which includes the element borders, the element vertical padding, the element horizontal scrollbar (if present, if rendered) and the element CSS height.
엘리먼트의 borders, 수직 padding 값, 가로 스크롤바(존재할경우)를 포함한 css 높이

3. scrollHeight : is a measurement of the height of an element's content including content not visible on the screen due to overflow
엘리먼트 내용물의 높이 (overflow로 보이지 않는 영역 포함)

3. textarea 의 문자열을 입력한 그대로(줄바꿈 형태 유지) 출력하는 방법

1) 출력시에도 textarea 를 그대로 사용

2) <pre> tag 혹은 줄바꿈/탭/자동줄바꿈 처리에 대한 white-space 속성 사용 

( 발췌 및 참고 : www.codingfactory.net/10597 )

  스페이스와 탭1 줄바꿈2 자동 줄바꿈3
normal 병합 병합 O
nowrap 병합 병합 X
pre 보존 보존 X
pre-wrap 보존 보존 O
pre-line 병합 보존 O

 

[구현]

1. CSS / HTML

noticeBox : 공지영역을 감싸고 있는 div

noticeTextarea : 작성모드에서의 textarea

noticeP : 읽기모드에서의 p태그. white-space:pre-wrap 속성을 주어 모든 스페이스/탭/줄바꿈에 대한 처리를 보존하고 자동 줄바꿈을 설정.

1
2
3
4
5
6
7
8
#noticeBox {display:none;}
#noticeTextarea {font-size:15px;
                margin-left:10px; 
                box-sizing: border-box; resize: none; border:1px solid #ccc; 
                vertical-align: center; box-sizing:border-box; 
                padding-left:12px; max-height:300px; /* overflow:hidden; */ /* width:95%; */
                }
#noticeP {font-size:15px; padding-left:50px; font-weight:bold; white-space:pre-wrap; width:95%;}
cs
1
2
3
4
5
6
7
8
9
10
11
<div id="noticeBox" class="contents">
    <div class="left_box">
        <span id="noticeLabel">공지</span><br>
        <span id="noticeCautionLabel" class="noticeAdminEle" style="color:red; font-size:8px;">(※500자 이하)</span><br>
    </div>
    <textarea id="noticeTextarea" class="noticeAdminEle" rows="2" cols="200" maxLength="500"><c:out value="${Notice.notice}"/></textarea>
    <p id="noticeP" class="noticeUserEle" ><c:out value="${Notice.notice}"/></p>
    <div class="right_box noticeAdminEle">
        <a href="javascript:noticeTextarea.upsertNotice();" class="redBtn">저장</a>
    </div>
</div>
cs

2. script document ready

var IS_NOTICE_AUTH = 공지사항작성권한 Y/N

공지사항작성권한 유무에 따라 Y는 textarea 사용, N 은 읽기모드로 textarea 대신 border 없는 tag 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script type="text/javascript">
var IS_NOTICE_AUTH = '<%=sample.SessionUtils.getIsNoticeAuth(request)%>';
 
$(document).ready(function() {
switch(IS_NOTICE_AUTH){
        case 'Y':
            //admin유저인 경우 화면처리
            noticeTextarea.editMode();
            
            //공지영역 리사이징
            noticeTextarea.addResizingEvtListener();
            noticeTextarea.initSizing();
            break;
        default:
            //일반 유저인 경우 화면처리
            noticeTextarea.readMode();
            break;
    }
})
</script>
cs

3. script function (참고)

1). noticeTextarea.addResizingEvtListener();

유저가 값을 입력했을 때 textarea 영역의 높이를 자동으로 증가시키기 위한 이벤트리스너(eventlistener)로 textarea에 keyup 이벤트에 걸어준다. 해상도가 정해진 환경에서 개발하므로 높이는 230으로 고정했으나 보다 정확한 라인 수 제한을 위해선 1줄짜리 textarea 를 생성한 후 높이값을 가져와 (높이 값 * 높이 제한 라인 수)로 maxHeight 를 뽑아 사용하는게 정확할 듯 하다.(1줄짜리 textarea는 사용자에겐 보이지 않게 hidden 처리)

 

2). noticeTextarea.initSizing();

최초 화면 로드시 textarea 영역 높이 조절. 이벤트 리스너를 걸어주고 $textarea.keyup(); 으로 강제로 이벤트를 호출해도 무방.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
var noticeTextarea = {
    //초기 로딩시 notice값 기준으로 textarea height 재조정
    initSizing : function(){
        var orgEle = $("#noticeTextarea")[0];
        var offsetOrgEle = orgEle.offsetHeight - orgEle.clientHeight;
        $(orgEle).css('height''auto').css('height', orgEle.scrollHeight + offsetOrgEle);
    } ,
    //resizing keyup 이벤트 걸기
    addResizingEvtListener : function(){
        var maxHeight = 230;
        $("#noticeTextarea").on('keyup input'function(e) {
            var offset = this.offsetHeight - this.clientHeight;
            if(this.scrollHeight + offset > maxHeight){
                //입력 가능 제한 줄 수 maxHeight 초과시, 가장 아랫줄 한글자씩 제거
                while(this.scrollHeight + offset > maxHeight) { 
                    $(this).val($(this).val().substr(0, $(this).val().length-1));
                    $(this).css('height''auto').css('height'this.scrollHeight + offset);
                } 
                alert("입력 가능한 줄 수가 초과되었습니다."); 
            }
            $(this).css('height''auto').css('height'this.scrollHeight + offset);
        });
    } ,
    //admin
    editMode : function(){
        $('#noticeBox').show();        //공지 영역 show
        $('.noticeUserEle').hide();    //user 영역 elements hidden
        $('.noticeAdminEle').show();//admin 영역 elements show
    } , 
    //user
    readMode : function(){
        $('.noticeAdminEle').hide();    //admin 영역 elements hide
        var noticeContents = $('#noticeP').text();
        noticeContents = noticeContents.replace(/\s|\r?\n|\r/g, '');
        if(noticeContents != null && noticeContents.length > 0){
            //공지 텍스트가 존재할 경우
            $('#noticeBox').show();    //공지 영역 show
            $('.noticeUserEle').show();//user 영역 elements show
        } else {
            $('#noticeBox').hide();    //공지 영역 hide
        }
    } , 
    upsertNotice : function (){
        if(confirm("공지를 저장하시겠습니까?")){
            //ajax 저장/수정 처리
        }
    }
}
cs

 

[결과]

1. 최초 화면에서의 textarea 크기

2. 엔터를 입력하여 늘어난 textarea 크기

3. 작성가능 유저가 아닌 일반유저에게 보이는 읽기전용 화면

 

[기타]

* 문자열 길이 제한 maxLength 사용시 주의사항 (참고)

특수문자 사용시 varchar2 기준 최대 3bytes 까지 차지할 수 있으므로 이를 고려하여 설계해야함.

ex) varchar2(1500) 으로 테이블 설계시 textarea maxLength 는 500자를 줘야함. (특수문자 3bytes * 500자 = 1500)

 

반응형

+ Recent posts