스케치북 스킨 기반에서 대댓글을 textarea가 아니라 위지윅에디터로 바로 작성할 수 있는 팁입니다.
... 새로고침 없는 대댓글 작성까지는 아니고 그냥 현재 페이지에서 에디터를 불러오는 방식입니다.
... ck에디터로만 작업을 해봤으니 다른 에디터로도 될지는 잘 모르겠네요
그동안 대댓글 작성은 페이지 이동을 해서 따로 에디터를 불러와 작성하거나, 스케치북처럼 댓글 목록 하단에 textarea를 불러와서 간단하게 작성하는 게 보통이었습니다.
... 이곳 타운의 대댓글 방식이 바로 그렇죠. 유저들에게 에디터 선택을 하게 해준다고 하는데 에디터를 선택하면 새 창으로 넘어가버립니다.
... 구글링해보니 다른 곳에서는 이런 민원도 있었네요. https://www.newri.net/newri_issue/122954
이하의 팁은 스케치북 스킨을 기반으로 작성한 것이며, 에디터 호출 방식이 position 속성을 통해 좌표값으로 위치를 이동시키는 방식이어서 다분히 매뉴얼하다는 점 미리 안내해드립니다. (즉, 엄청난 모험일 수 있으니 백업 꼭 하세요)
... 에디터를 absolute 포지션으로 두는 것은 에디터 스킨에 있는 인라인 스크립트 때문인데요. 암튼 이와 관련된 속사정은 다음 문서의 댓글 대화를 참고해두시면 좋겠습니다. https://xetown.com/topics/1710052#comment
0. _comment.html 확인
- 이거는 그냥 확인차 남기는 기록입니다. (아시는 분은 그냥 패스)
- 대댓글 에디터를 여는 동작은 각 댓글의 메뉴에 있지요. 이 부분이에요. https://github.com/rhymix/rhymix-sketchbook/blob/f137bb37f24160e35501bd9f03973e9679a89e8c/_comment.html#L72
- 스케치북 기준으로는 고칠 필요가 없지만, 다른 스킨에서는 이렇게 대댓글폼을 여는 동작이 선행해야 한다는 사실을 염두에 두셔야 합니다.
1. _comment_write.html 수정
- https://github.com/rhymix/rhymix-sketchbook/blob/f137bb37f24160e35501bd9f03973e9679a89e8c/_comment_write.html#L69-L118
- 이런 부분이 있는데요. 여기가 바로 대댓글 입력폼입니다. 이 부분을 잘라내기(Ctrl + x) 해둡니다.
2. _comment_re_write.html 생성
- 빈 파일을 만들어 위에서 잘라낸 부분을 붙여넣기 하고 _comment_re_write.html라는 이름으로 파일을 생성합니다.
- 파일의 위치는 _comment_write.html과 같은 위치면 됩니다.
3. _comment_re_write.html 수정
- 새로 만들었던 파일을 수정합니다. 다음과 같습니다.
<!--@if($grant->write_comment && $oDocument->isEnableComment())--> <!--// 대댓글 --> <div cond="$rd_idx==0" id="re_cmt"> <label for="editor_2" class="cmt_editor_tl fl"><i class="fa fa-share fa-flip-vertical re"></i><strong>{$lang->write_comment}</strong></label> <div class="editor_select fr"> <a class="close" href="#" onclick="jQuery('#re_cmt').fadeOut(); jQuery('#comment_'+jQuery('#re_cmt').find('[name=parent_srl]').val()).find('.dummy_for_re_cmt').fadeOut(); jQuery('#comment_'+jQuery('#re_cmt').find('[name=parent_srl]').val()).find('.re_comment').focus();return false"><i class="fa fa-times"></i> {$lang->cmd_close}</a> </div> <form action="/" method="post" onsubmit="return procFilter(this,insert_comment)" class="bd_wrt clear"> <input type="hidden" name="mid" value="{$mid}" /> <input type="hidden" name="document_srl" value="{$oDocument->document_srl}" /> <input type="hidden" name="comment_srl" value="" /> <input type="hidden" name="parent_srl" value="" /> <input type="hidden" name="use_html" value="Y" /> <div class="simple_wrt"> <input type="hidden" id="htm_2" value="n" /> <textarea id="editor_2" cols="50" rows="8" name="content" style="display: none;"></textarea> {$oDocument->getCommentEditor()} </div> <div class="edit_opt" cond="!$is_logged"> ...(중략)... </form> </div> <!--@end-->
- 맨 위와 맨 아래에 조건문을 넣어봤습니다. 대댓글 권한 체크입니다.
- 기존 코드와 비교하면 에디터 선택 버튼이 제거됐고, 닫기 버튼의 onclick 속성값이 대폭 수정됐으며
- 원래 있던 input[name=content]를 제거한 대신, textarea에 name=content 속성을 부여했으며 동시에 hidden 처리했습니다.
- 그리고 textarea 대신 {$oDocument->getCommentEditor()} 로 모듈 관리 페이지의 추가 설정 > 위지윅 에디터에서 설정한 에디터를 가져오게 했습니다.
4. _read.html 수정
- 위에서 만든 파일은 _read.html에서 include할 겁니다.
- 위치는 https://github.com/rhymix/rhymix-sketchbook/blob/f137bb37f24160e35501bd9f03973e9679a89e8c/_read.html#L384 입니다.
- 아래와 같이 수정합니다.
<div id="cmtPosition" aria-live="polite"><include target="_comment.html" /><include target="_comment_re_write.html" /></div>
- 이것은 대댓글 폼이 id cmtPosition 안에 추가(append)된다는 것을 의미합니다.
- 그리고 스케치북 스킨에서는 cmtPosition보다 상위요소인 .fdb_lst 요소에 clear라는 클래스가 포함되어 있는데 여기에 position: relative가 걸려 있습니다.- 우리는 나중에 js에서 대댓글 입력폼에 absolute position을 줘서 .fdb_lst에 따라 디스플레이하게 될 겁니다. (귀찮으시죠? 포기하시는 게 나을지도... 쿨럭)
5. board.js - 함수 수정
- https://github.com/rhymix/rhymix-sketchbook/blob/f137bb37f24160e35501bd9f03973e9679a89e8c/js/board.js#L514-L522
- 여기를 보면 reComment 함수가 있는데 이걸 다음과 같이 바꿔줍니다.
function reComment(doc_srl,cmt_srl,edit_url){ var block = $('.fdb_lst'); var li = $('#comment_'+cmt_srl); var rmt = jQuery('#re_cmt').eq(0); if ( block.find('.dummy_for_re_cmt').length ) { block.find('.dummy_for_re_cmt').remove(); } rmt.find('input[name=error_return_url]').val('/'+doc_srl); rmt.find('input[name=mid]').val(current_mid); rmt.find('input[name=document_srl]').val(doc_srl); rmt.find('input[name=parent_srl]').val(cmt_srl); rmt.find('textarea[id=editor_2]').hide(); setReCommentPosition(block, li, rmt); if ( !li.find('.dummy_for_re_cmt').length ) { var dummy = '<div class="dummy_for_re_cmt"></div>'; $(dummy).css({'height': rmt.outerHeight() + parseInt(li.css('padding-bottom')) * 3}).appendTo(li); } rmt.hide().fadeIn(); }
- 대강 이런 식의 동작입니다.
- 댓글 목록에서 대댓글 달기 링크를 클릭해서 들어오면 mid, document_srl, parent_srl 등을 지정해줍니다. 특히 parent_srl은 onclick 속성을 통해 들어온 인자를 통해 삽입됩니다. 즉, 대댓글을 달다가도 다른 부모댓글로 가서 댓글 달기 버튼을 누르면 parent_srl이 해당 부모댓글의 comment_srl로 바뀌는 거죠.
- 그리고 대댓글 폼의 위치를 설정하는 함수를 실행합니다.
- 아래 6번 항목에서 보겠지만 대댓글폼이 absolute position이 될 것이기 때문에 각 댓글 항목 아래에 .dummy_for_re_cmt라는 더미 요소를 추가해주고, 대댓글폼의 높이만큼 넉넉히 빈공간을 확보해둡니다. 우리의 대댓글 에디터는 기존 스케치북 스킨처럼 부모댓글 아래에 삽입되는 것이 아니라 부모댓글 위치에 레이어로 올라가는 형식입니다. (왜 이렇게 복잡하게 해야 하냐 물으신다면, 에디터 스킨 자체의 인라인 스크립트가.... ㅜ)
- 마지막에는 위치가 확정된 대댓글 입력폼을 페이드인 시켜서 나타나게 합니다.
- 자, 대댓글 폼의 위치를 지정해주는 setReCommentPosition이라는 함수를 실행하게 헸으니 해당 함수도 추가해줘야겠지요?
6. board.js - 함수 추가
- 아래와 같은 코드의 함수를 reComment 함수의 위나 아래쯤에 추가해줍니다. 코드는 다음과 같습니다.
function setReCommentPosition(block, li, rmt) { var block_top_gap = parseInt(block.css('border-top')) + parseInt(block.css('padding-top')), block_right_gap = parseInt(block.css('border-right')) + parseInt(block.css('padding-right')); var li_top = li.position().top, li_bottom = li_top + li.outerHeight(), li_left = parseInt(li.css('margin-left')) + parseInt(li.css('border-left')) + parseInt(li.css('padding-left')), li_right = parseInt(li.css('margin-right')) + parseInt(li.css('border-right')) + parseInt(li.css('padding-right')), li_width = li.width(); rmt.css({ 'position': 'absolute', 'top': block_top_gap + li_bottom, 'right': block_right_gap + li_right, 'width': li_width }); if ( li.find('.dummy_for_re_cmt').length ) { rmt.css({ 'top': block_top_gap + li_bottom - li.find('.dummy_for_re_cmt').height() }); } }
- 대강 설명하면 다음과 같습니다. .fdb_lst 요소 그리고 대댓글의 타겟이 되는 부모댓글의 요소 등의 위치값과 넓이를 계산해서 대댓글폼의 위치와 넓이를 확정시켜주는 겁니다.
- 스케치북에서는 댓글 리스트의 오른쪽을 기준으로 댓글들의 depth에 따라 좌측 여백이 가변적이므로, top값, right값, width값만 있으면 부모댓글 바로 아래에 대댓글폼을 show할 수 있지요. 이 위치값은 스킨마다 다를 수 있기 때문에 개발자의 맞춤형 노가다가 필요합...
- 끝으로 18~22행에 알쏭달쏭한 코드가 보일 텐데요. 이거는 부모댓글 리스트 중에 위의 6번 과정에서 만들어뒀던 더미 요소에 관한 것입니다. 이거는 평상시에는 별 의미가 없는 코드인데요. 왜냐면 이 함수는 더미요소를 삽입하기 이전에 실행되는 함수이기 때문이에요. 즉, 앞선 5번의 함수를 보면 지금의 setReCommentPosition 함수 실행 전에 더미요소를 제거했던 것을 알 수 있죠. 그럼 언제 이 코드가 작동하느냐? 그건 바로 윈도우가 resize 될 때입니다. 에디터가 보이는 상황에서 윈도우 resize가 일어나면 에디터는 absolute 포지션을 갖기 때문에 뭔가 붕떠버리는 상황이 발생할 수밖에 없습니다. 이때 resize 이벤트로 대댓글폼을 대응하도록 만들어서 마치 반응형 에디터인 것처럼 보이게 할 겁니다.
7. board.js - 동작 추가
- 이제 마지막입니다. 마지막일 걸요...?
- https://github.com/rhymix/rhymix-sketchbook/blob/f137bb37f24160e35501bd9f03973e9679a89e8c/js/board.js#L473-L474 여기 473행과 474행 사이쯤에 아래와 같은 코드를 추가해줍니다.
// Recomment Editor Resize var re_cmt = $('#re_cmt'); $(window).on('resize', function() { if ( re_cmt.is(':hidden') ) { return; } var block = $('.fdb_lst'); var cmt_srl = re_cmt.find('[name="parent_srl"]').val(); var li = $('#comment_'+cmt_srl); setReCommentPosition(block, li, re_cmt); }); var observer = new ResizeObserver(entries => { for (let entry of entries) { var target_srl = re_cmt.find('[name="parent_srl"]').val(); var target = $('#comment_' + target_srl); var dummy = target.find('.dummy_for_re_cmt'); if ( dummy.length ) { dummy.css({height: re_cmt.outerHeight() + parseInt(target.css('padding-bottom')) * 3}); } } }); observer.observe(re_cmt[0]);
- 이게 바로 에디터 리사이즈와 관련된 동작 코드입니다.
- 윈도우가 라사이즈될 때, 대댓글폼이 visible 상태라면, 대댓글폼의 위치값을 다시 구해서 스타일로 반영합니다.
- 그리고 에디터 안에서 도구상자를 여닫는다는가, 파일 첨부를 해서 파일리스트로 인해 에디터 높이가 달라진다면 거기에 맞춰 부모댓글의 더미요소의 높이도 똑같이 대응하도록 해주는 거죠.
- 이렇게 하면 대댓글 에디터 달기 프로젝트는 어느 정도 완성된 거라 보시면 되겠습니다. (빼먹은 거 없겠죠? ㄷㄷㄷㄷ)
작업한 과정을 기억나는대로 찾아서 코드를 소개하긴 했는데요. 빼먹은 부분이 있을 수 있습니다.
그나저나 퇴고하는 차원에서 글을 다시 보는데 이걸 누가 따라하나 싶네요ㅜㅜㅜㅜ
따라하기 힘드니까 그냥 수정하신 버전을 올려주시죠!^^
스케치북 스킨은 GPL 라이선스입니다. "타인의 자료를 무단으로 재배포하시면 감사합니다."
https://xetown.com/topics/1480720