티스토리 뷰

발생일: 2014.12.31

키워드: Selection, Range, 레인지, 셀렉션, window.getSelection()

문제:
요새 우리 서비스는 글쓰기 에디터에 몇 가지 골치 아픈 버그가 있어 어려움을 겪고 있다.
이 작업은 주로 뒷자리 A가 하고 있는데, 도움을 주고 싶어도 에디터 쪽은 기반 지식이 좀 있어야 해서 어렵더라.

에디터에서는 셀렉션과 레인지에 대한 이해가 꼭 필요하다고 한다.
몇 달 전에 summernote 에디터를 작성한  에디터 전문가 H에게 일장 강의를 들은 적도 있는데...
다 까먹었다… -_-;;

함수의 동작보다는, 앵커니 포커스니 하는 개념을 잘 몰라 이해하기 어렵더라.
이 참에 MDN 페이지를 보고 정리해두려고 한다.


해결책:

Selection

Selection 은 window.getSelection() 이나 다른 메서드의 호출로 생성되는 객체이다.
사용자가 드래그 등으로 여러 엘리먼트에 걸쳐 선택한 텍스트를 대표한다.

selection 객체는 사용자가 선택한 `range`로 표현된다.
보통 한 개의 range 만 갖고 있고, 아래 코드처럼 가져올 수 있다.

var selObj = window.getSelection();
var range  = selObj.getRangeAt(0);

selObj: Selection 객체
range: Range 객체


선택된 값은 selection 객체의 toString()을 호출해서 가져올 수 있다.

selObj.toString(); //—> 현재 선택한 텍스트



Selection 에 사용되는 용어 정리

anchor
  셀렉션의 시작점.
  마우스로 드래그해서 선택했다면, anchor 는 최초에 마우스가 클릭된 지점이다.
  사용자가 마우스나 키보드로 셀렉션을 수정해도, anchor 는 변경되지 않는다.
  텍스트를 위/아래로 드래그했을 때 고정된 지점이 anchor 이다.

focus
  셀렉션의 끝점.
  마우스로 셀렉션을 만들었다면, 마우스를 뗀 곳이 셀렉션의 focus 지점이다.
  사용자가 마우스나 키보드로 셀렉션을 수정할 때마다 변경된다.

range
  문서에 인접한 부분.
  텍스트 노드를 포함한 전체 노드를 포함할 수 있다.
  일반적으로 사용자는 한 개의 레인지만 선택할 수 있지만, 컨트롤 키 등으로 멀티 레인지를 선택할 수도 있다.
  레인지는 range 객체로 리턴되며, 스크립트에 의해 추가되거나 삭제될 수 있다.



Selection의 주요 속성

Selection.anchorNode
  시작 노드

Selection.anchorOffset
  시작 노드에서 anchor 의 오프셋.
  anchorNode 가 텍스트 노드이면 anchor 이전의 문자열의 개수이고,
  anchorNode 가 엘리먼트일 경우엔 anchor 보다 앞에 있는 자식 노드의 개수를 의미한다.

Selection.focusNode
  끝 노드

Selection.focusOffset
  끝 노드에서 focus 의 오프셋.
  focusNode 가 텍스트 노드이면 focus 이전의 문자열의 개수이고,
  focusNode 가 엘리먼트일 경우엔 focus 보다 앞에 있는 자식 노드의 개수를 의미한다.

Selection.isCollapsed
  셀렉션의 시작지점과 끝지점이 동일한지의 여부

Selection.rangeCount
  셀렉션 내의 레인지 개수



Range

Range 인터페이스는 노드와 텍스트 노드를 포함한 문서의 일부(fragment)이다.
'문서의 특정 부분’을 정의하는 것이라 생각하면 쉽다.

레인지를 생성할 수 있는 방법은 아래와 같다.
- document.createRange()
- Selection 객체의 getRangeAt() 메서드
- Range() 생성자


Range의 주요 속성

Range.collapsed
  레인지의 시작점과 끝점이 동일한지 여부

Range.commonAncestorContainer
  시작 컨테이너와 끝 컨테이너를 포함하고 있는 상위 노드

Range.endContainer
  레인지가 끝나는 지점의 끝 컨테이너 노드

Range.endOffset
  endContainer 노드에서 끝 지점의 오프셋

Range.startContainer
  레인지가 시작하는 지점의 컨테이너 노드

Range.startOffset
  startContainer 노드에서 시작 지점의 오프셋



용어만 잘 이해하면 나머지는 메서드의 설명을 보거나 사용 예를 보면 쉽게 이해할 수 있을 거라 생각한다.
API에 대한 자세한 건 아래 링크를 참고하면 된다.

참고:

반응형
댓글
공지사항