개발/html&css&javascript

contenteditable hashtag(#) 적용 구현하기(대화창 형식) placeholder, 커서,caret 적용

JangHC 2022. 1. 24. 02:19

 

textarea로는 글 쓰면서 hashtag를 인식하여 color를 변경할 수 없습니다.

실시간으로 변경하게 하려면 div 두개를 겹쳐서 input은 투명하게 하고 입력 받는 즉시 output으로 복사해서 구현해야 합니다.

 

언제쯤 textarea로 구현할 수 있을지ㅠㅠ

 

<div class="input_content_box">
    <div class="output_content" id="output_content_<?= $note_cnt ?>"></div>
    <div class="input_content" contenteditable="true" id="input_content_<?= $note_cnt ?>"></div>
</div>

 

 

저는 대화창 형식으로 구현할 때 사용하였는데, 대화 형식이 아니라면 id에 note_cnt를 빼고 구현하면 됩니다.

 

 .input_content {
             position: absolute;
             width: 100%;
             z-index: 1;
             font-size: 16px;
             font-weight: 400;
             line-height: 24px;
             white-space: normal;
             color: rgba(0,0,0,0);
             outline: none;
             caret-color: #000000;
             word-break:break-all;
        }
        
        .output_content span{
           color: #8F0AA5;
        }
        
        .output_content {
           position: absolute;
           width: 100%;
           z-index: 1; 
           font-size: 16px;
           font-weight: 400;
           line-height: 24px;
           background-color: transparent;
           color: #000000;
           white-space: normal;
           word-break:break-all;
        }
        
        [contenteditable][placeholder]:empty:before {
          content: attr(placeholder);
          display: block;
          color: gray;
          background-color: transparent;
   }

 

폰트 사이즈나 포지션은 구현 페이지에 맞춰서 수정하면 됩니다.

 

function placeCaretAtEnd(el) {
    el.focus();
    if (typeof window.getSelection != "undefined"
            && typeof document.createRange != "undefined") {
        var range = document.createRange();
        range.selectNodeContents(el);
        range.collapse(false);
        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
    } else if (typeof document.body.createTextRange != "undefined") {
        var textRange = document.body.createTextRange();
        textRange.moveToElementText(el);
        textRange.collapse(false);
        textRange.select();
    }
}

$(document).ready(function(){
	fn_input_note(0) // 글 저장하고 전달인자 ++ 해줘서 계속 event 적용시켜야함.
);

function fn_input_note(note_index) { // 각 line 마다 적용 
//save_note 후에 새로운 line 이 추가되면 note_index를 올려줘서 호출해줘야함.
//이전 index들은 hide 해줘야 이벤트가 적용안됨.
    placeCaretAtEnd(document.getElementById("input_content_"+note_index));
    $("#input_content_"+note_index).on('input keyup', converter);
    $("#input_content_"+note_index).keydown(function(e) {
      if(e.keyCode == 13 && $(this).text().trim() == "") {
            return false;
        } else {
            if (e.keyCode == 13) { // enter
                save_note(); // content 저장하는 소스(커스터마이징해서 사용하길)
            } else {
                if(e.keyCode == 113) { // f2 눌렀을 시 추가되는 과정 (특정 key 눌렀을시 추가)
                    var str = escapeHtml($(this).text());
                    var str2 = str+"⭐";
                    $("#input_content_"+note_index).html(str2);
                    placeCaretAtEnd(document.getElementById("input_content_"+note_index)); // 커서 맨 끝으로 이동하는 함수
                }
            }
        }
    });
}

function converter (){
    var str = $("#input_note_content_"+note_index).text(); // input 글자 그대로 가져옴
    str = str.replace(/(#[ㅏ-ㅣㄱ-ㅎ가-힣a-zA-Z0-9\_]{1,10})/g, "<span>$1</span>"); // {1,10}은 해쉬태그 10글자만 가능하게 함 
    $("#output_note_content_"+note_index).html(str); // output에는 html로 span 적용 (text(),html() 다름)
}

 

각자 환경에 맞춰서 수정해서 구현하면 될 듯 합니다.

 

궁금한점이 있으면 댓글 남겨주세요.

'개발 > html&css&javascript' 카테고리의 다른 글

html text(),html() 차이점  (0) 2022.01.28