Selection & Range

Chanhee Jang·2023년 1월 31일

https://ko.javascript.info/selection-range

위 주소의 글을 제가 알아야 되는 부분만 번역했습니다.


문서의 Selection 과 더불어<input /> 과 같은 폼 양식의 Selection도 다룬다.

JS는 기존의 Selection을 가져오고, 전체, 부분적으로 선택과 해제할 수 있다.

또한 문서에서 selected된 부분을 제거하고, 태그로 감싸는 등의 작업을 수행할 수 있다.


Selection에 앞서 Range를 보자.

selection의 기본 개념은 range(range start와 range end의 ’경계 지점’ - boundary points의 쌍)이다.

각 지점(range start, range end)은 그 지점의 출발점으로부터의 relative offset을 가진 부모 DOM 노드로 표현된다.

부모 노드가 element node라면 offset은 자식의 숫자로 나타나고,

텍스트 노드라면 offset은 텍스트안의 위치로 나타난다.

무언가 select 해보자.

먼저 range 를 만들자. (생성자는 파라미터가 없다.)

let range = new Range();

이제 range.setStart(node, offset)range.setEnd(node, offest) 을 사용해 selection의 경계 지점을 설정할 수 있다.

예제를 위한 HTML snippet이다.

<p id="p">Example: <i>italic</i> and <b>bold</b></p>

text node에 더 집중하며 DOM 구조를 보자.

지금은 Example: <i>italic</i> 를 select 해보자. (text node를 포함하면) p태그의 0번째, 1번째 자식이다.

let range = new Range();

const p = document.getElementById('p');

range.setStart(p, 0);
range.setEnd(p, 2);

alert(range); // Example: <i>italic</i>

document.getSelection().addRange(range);

0과 1이 아니라 0과 2인 것은 노드와 노드의 ‘간격’, 텍스트 노드라면 글자와 글자 사이의 ‘간격’을 파라미터로 넣는다고 보면 이해가 쉽다.

p 태그는 총 4개의 자식을 갖고 있고, 노드와 노드 사이의 간격은 0 ~ 4인 것이다. Example 이라는 텍스트 노드의 왼쪽이 0, <b>bold</b> 의 오른쪽이 4인 것이다.


텍스트 노드 부분 선택하기

let range = new Range();

range.setStart(p.firstChild, 2);
range.setEnd(p.querySelector('b').firstChild, 3);

range 오브젝트는 이런 속성들이 있다.

  • startContainer, startOffset - 출발점의 node와 offset
    • 위의 예제에서는 p의 첫번째 텍스트 노드와 2이다.
  • endContainer, endOffset - 끝점의 node와 offset
    • 위의 예제에서는 b의 텍스트노드와 3이다.
  • collapsed - boolean형으로 range의 start와 end가 같으면 true를 리턴한다. (start와 end가 같으므로 range 내용이 없다.)
    • 위의 예제에서는 false이다.
  • commonAncestorContainer - Range의 모든 노드의 가장 가까운 공통 조상이다.
    • 위의 예제에서는 p이다.

range의 메소드들은 설명을 생략한다. 이름만 봐도 사용법을 알 수 있고, 우리가 주의할 건 요소 노드인지, 텍스트 노드인지 주의하는 것뿐이다. (요소 노드의 offset은 건너뛸 요소 노드들이고, 텍스트 노드의 offset은 건너뛸 문자들이기 때문이다.)

  • setStart(node, offset)
    • setStartBefore, setStartAfter
  • setEnd(node, offset)
    • setEndBefore, setEndAfter
  • selectNode(node)
    • selectNodeContents(node)
  • collapse(toStart)
  • cloneRange

Selection

selection은 이런 속성들이 있다.

일단 range와 비스무리하게 start와 end를 표헌한, ‘anchor’와 ‘focus’가 있다.

  • anchorNode – selection이 시작되는 지점
  • anchorOffset – selection 시작점으로부터 anchorNode의 offset
  • focusNode – selection이 끝나는 지점,
  • focusOffset – selection 끝 지점으로부터 focusNode의 offset,
  • isCollapsed – selection에 선택된게 아무것도 없거나 존재하지 않을 시 true를 리턴
  • rangeCount – selection의 range 개수를 리턴한다. Firefox를 제외한 모든 브라우저가 최대 1을 가진다.

메소드들은 생소한 것 빼고 설명을 생략한다.

range와 관련된 메소드들이다.

  • getRangeAt(i)
  • addRange(range)
  • removeRange(range)
  • removeAllRanges()
  • empty()

range 의 메소드를 사용하지 않고 selection range를 직접 관리할 수 있는 메소드들이다.

  • collapse(node, offset) – 선택된 range를 node의 offset에서 시작하고 끝나는 새 range로 바꾼다.
  • setPosition(node, offset) – collapse의 alias이다.
  • collapseToStart()
  • collapseToEnd()
  • extend(node, offset) – node와 offset으로 selection의 focus를 옮긴다.
  • setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset) – 주어진 파라미터들로 selection range를 바꾼다. anchor와 focus 사이에 있는 노드들은 전부 다 선택된다.
  • selectAllChildren(node)
  • deleteFromDocument()
  • containsNode(node, allowPartialContainment = false)
profile
What is to give light must endure burning

0개의 댓글