23.10.23 ~ 26
📌 노션 클로닝 과제
- 보너스 요구사항 및 리팩토링
보너스 요구사항
- div와 contentEditable을 조합해서 좀 더 Rich한 에디터를 만들기
- 현재 편집 중인 Document의 하위 Document 링크 추가
- 편집기 내에서 다른 Document name을 적은 경우, 자동으로 해당 Document의 편집 페이지로 이동하는 링크
- 그외 개선사항 구현
일반 텍스트 형태로 입력만 받는 < input>의 활용은 제한적이다!
입력 내에서 태그를 사용하거나, 이미 < h2>등의 태그로 되어있는 내용에 편집도 할 수 있게 하려면? contentEditable 속성값을 이용하자!
<div contenteditable=“true”>
Input이나 textarea와 다르게 값이 inner로 들어가기 때문에 e.target.value로 접근하지 않는다!
아이디어1) render에서 innerHTML로 그리기 전에 본문에 대해서 Rich작업을 거쳐보자.
const range = document.createRange();
range.selectNodeContents($editor.querySelector(".editor_content"));
range.collapse(false);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
여기까지 수정을 거치다가 근본적인 다른 방법을 떠올렸다.
아이디어2) 저장할때부터 태그로 바꾸자!
아이디어1이 마크다운으로 저장을 하고 그릴때 태그로 바꿨다면, 애초에 입력을 감지해서 태그로 저장해보자.
다시 생각하면서 엎으려다가, 팀원분이 그러기엔 아깝다하셔서,,,, 다시 머리를 벅벅
아이디어2+) 저장할때부터 태그로 바꾸자!
##가 입력되면 입력창을 < div>에서 < h2>로 바꿔주는 형식!
로직을 정리해보자!
let allHTML = e.currentTarget.parentNode.innerHTML;
if (e.currentTarget.innerHTML.indexOf("# ") === 0) {
const txt = e.currentTarget.innerHTML.substring(7);
const newline = document.createElement("h1");
newline.className = "editor_content_block r";
newline.setAttribute("contenteditable", true);
newline.addEventListener("keyup", (e) => handleChangeContent(e));
newline.innerHTML = txt;
e.currentTarget.after(newline);
newline.focus();
allHTML = e.currentTarget.parentNode.innerHTML;
e.currentTarget.remove();
}
const nextState = {
...this.state,
content: allHTML,
};
console.log(nextState);
await onEditing(nextState, "content");
}
성공 🥰
☄️ 트러블 슈팅
const blocks = document.getElementsByClassName("editor_content_block");
for (let block of blocks) {
block.addEventListener("keyup", (e) => handleChangeContent(e));
}
이렇게 요소들을 찾아서 각각에 이벤트 리스너를 심었다.
근데!? 이렇게 하면 한 페이지 내에서 새로고침을 했을 때 위의 캡쳐처럼 요소들을 못찾는다!!!! 콘솔에 코드를 입력하면 찾는다. 렌더링 순서의 문제일까.
일단, 해결방법은 .editor_content_block를 document에서 찾지 않았다.
// $editor.appendChild($editor_content);해놓은 $editor_content에 붙였다.
$editor_content.getElementsByClassName("editor_content_block");
정리한 글
요약 : after는 해당 요소 "뒤"에! 즉, 형제관계
append는 해당 요소 "하위"에! 즉, 자식관계
https://developer.mozilla.org/ko/docs/Web/API/console/dir
주어진 JavaScript 객체의 모든 속성을 콘솔에서 볼 수 있는 방법으로서 이를 사용하면 개발자가 객체의 속성을 쉽게 확인할 수 있습니다.
기본 요구사항 구현은 큰 무리없이 끝냈는데, 이번주 보너스 요구사항에서 꽤나 힘이 들었다. 아직 모르는 부분이 많았고 고려해야 할 부분이 정말 정말 많았다..
어느정도 마무리가 된 후에 갑자기 의욕이 많이 꺾였었다. 내 결과물에 100%만족할 수 없는데, 여기서 다 갈아엎기엔 시간도 힘도 부족하게 느껴지고 그게 또 힘에 부치는 딜레마였다.