반응형
들어가며
Selection? Range?
- input이나 contenteditable 영역의 커서(caret)를 핸들링하는 javascript 객체를 말한다.
예제로 이해하기
기본 사용
<pre id="editor" contenteditable="true"></pre>
<script>
const KEY_CODE = { ESC: 27 };
const $editor = document.querySelector('#editor');
$editor.addEventListener('keydown', (e) => {
if (e.keyCode === KEY_CODE.ESC) {
e.preventDefault();
const selection = document.getSelection();
const range = selection.getRangeAt(0);
console.log({ selection, range });
}
});
</script>
undefinedcopy
커서가 위치한 노드 range 선택하기
const selection = document.getSelection();
const range = selection.getRangeAt(0);
range.selectNode(range.startContainer);
// range.setStart(range.startContainer, 0);
// range.setEnd(range.startContainer, range.startContainer.nodeValue.length);
undefinedcopy
range 선택 제거
const selection = document.getSelection();
selection.removeAllRanges();
undefinedcopy
range에 포함된 노드 제거
const selection = document.getSelection();
const range = selection.getRangeAt(0);
range.deleteContents();
undefinedcopy
현재 커서 위치에 노드 추가
const selection = document.getSelection();
const range = selection.getRangeAt(0);
const $span = document.createElement('span');
const $text = document.createTextNode("I'm text");
$span.innerText = "I'm span";
range.insertNode($span);
range.insertNode($text);
undefinedcopy
응용하기
tab, back tab 구현
<pre id="editor" contenteditable="true"></pre>
<script>
const KEY_CODE = { TAB: 9 };
const NODE_TYPE = { TEXT: 3 };
const INDENT = ' ';
const $editor = document.querySelector('#editor');
$editor.addEventListener('keydown', (e) => {
if (e.keyCode !== KEY_CODE.TAB) {
return;
}
e.preventDefault();
const selection = document.getSelection();
const range = selection.getRangeAt(0);
let start = range.startContainer;
if (!start.parentNode.getAttribute('contenteditable')) {
start = start.parentNode;
}
while (true) {
const node = start.nodeType === NODE_TYPE.TEXT ? start : start.firstChild;
if (e.shiftKey) {
if (node.nodeValue.indexOf(INDENT) >= 0) {
node.nodeValue = node.nodeValue.substring(INDENT.length);
}
} else {
node.nodeValue = INDENT + node.nodeValue;
}
if (!start.nextSibling || start === range.endContainer.parentNode) {
break;
}
start = start.nextSibling;
}
range.setStart(range.startContainer, 0);
range.setEnd(range.endContainer, range.endContainer.nodeValue.length);
});
</script>
undefinedcopy
참고
반응형
'Development > JS' 카테고리의 다른 글
[BackboneJS] 예제 (0) | 2021.06.26 |
---|---|
[Javascript] remark, rehype (1) | 2021.01.07 |