선택 API

W3C 작업 초안

문서에 대한 추가 정보
이 버전:
https://www.w3.org/TR/2025/WD-selection-api-20250105/
최신 공개 버전:
https://www.w3.org/TR/selection-api/
최신 편집자 초안:
https://w3c.github.io/selection-api/
이력:
https://www.w3.org/standards/history/selection-api/
커밋 이력
테스트 스위트:
https://wpt.fyi/results/selection/
편집자:
(Apple Inc.)
피드백:
GitHub w3c/selection-api (풀 리퀘스트, 새 이슈, 열린 이슈)

초록

이 문서는 Selection API 및 선택 관련 기능에 대한 사양의 예비 초안입니다. 이는 HTML specification의 오래된 몇몇 섹션과, 기존 DOM Range specification의 선택 부분을 대체합니다.

이 문서는 사용자가 문서의 일부를 선택하거나 복사, 붙여넣기 및 기타 편집 작업을 위해 관심 지점을 지정할 수 있도록 하는 선택을 위한 API를 정의합니다.

이 문서의 상태

이 섹션은 문서가 게재된 시점의 상태를 설명합니다. 현재 W3C 간행물 목록과 이 기술 보고서의 최신 개정본은 W3C 기술 보고서 색인에서 확인할 수 있습니다. https://www.w3.org/TR/.

이 문서는 작업 중입니다.

이 문서는 Web Editing Working Group에 의해 권고안 트랙을 사용하여 Working Draft로 발행되었습니다.

Working Draft로의 발행은 W3C 및 그 회원들의 승인(endorsement)을 의미하지 않습니다.

이 문서는 초안 문서이며 언제든지 업데이트되거나 교체되거나 다른 문서에 의해 폐기될 수 있습니다. 이 문서는 작업 중인 문서로만 인용하는 것이 적절합니다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에 의해 작성되었습니다.

W3C는 그룹의 산출물과 관련하여 이루어진 특허 공개의 공개 목록을 유지합니다; 해당 페이지에는 특허 공개 방법에 대한 지침도 포함되어 있습니다. 개인이 해당 개인이 포함되어 있다고 믿는 특허에 대한 실제 지식을 가지고 있는 경우 핵심 청구(essential claim)이 포함되어 있다고 생각하면, 해당 정보는 W3C 특허 정책의 섹션 6에 따라 공개해야 합니다.

이 문서는 2023년 11월 03일 W3C 프로세스 문서의 적용을 받습니다.

1. 배경

이 절은 규범적이지 않습니다.

IE9와 Firefox 6.0a2는 선택에서 임의의 범위를 허용하는데, 이는 이 명세가 원래 말한 내용과 같습니다. 그러나, 이것은 저자, 구현자, 명세 작성자가 모두 처리해야 하는 불쾌한 코너 케이스를 초래하며 실제로는 큰 의미가 없습니다. Chrome 14 개발자 버전과 Opera 11.11은 비어 있는 요소 안에 두지 않는 등 선택을 적극적으로 정규화하지만, 이것 또한 저자의 유연성을 빼앗기 때문에 좋은 생각으로 보이지 않습니다.

그래서 일부 단순화를 허용하면서 저자를 크게 제한하지 않는 타협안을 만들어 명세를 변경했습니다. 논의를 참고하세요. 기본적으로 일부 상황에서 예외를 던져 selection이 Element 또는 Text 노드가 아닌 경계점을 포함하거나 Document에서 파생되지 않은 경계점을 포함하는 것을 막으려 했습니다.

하지만 이로 인해 getRangeAt()이 참조가 아니라 복사본을 반환해야 했습니다. 또한, 코너 케이스에서 이상하게 실패할 가능성이 높아졌습니다. 특히 DOM 변화가 발생할 때, 예를 들어 경계점의 노드가 부모에서 제거되고 변경 규칙 때문에 새 경계점이 Text/Element 노드가 아닌 곳에 배치되는 경우 문제가 발생할 수 있습니다. 그리고 이전 명세는 두 대형 구현체와 동작이 일치하는 이점이 있었지만, 새 동작은 어느 쪽과도 맞지 않았습니다. 그래서 다시 되돌렸습니다.

참고

버그 15470를 참고하세요. IE9, Firefox 12.0a1, Chrome 17 개발자 버전, Opera Next 12.00 알파 모두 범위를 처음에 null로 만듭니다.

2. 정의

문서마다 브라우징 컨텍스트가 있으면 고유한 selection(선택)이 연결됩니다.

참고

이는 HTML 명세의 요구 사항입니다. IE9와 Opera Next 12.00 알파는 이에 따르는 것으로 보이며, Firefox 12.0a1과 Chrome 17 개발 버전은 그렇지 않은 것 같습니다. Mozilla 버그, WebKit 버그를 참고하세요.

selection문서의 모든 콘텐츠(중첩된 문서는 제외)에 공유되어야 하며, 편집 호스트도 포함됩니다.

selection은 하나의 range와 연관될 수 있습니다. range가 연결되지 않은 경우 selection비어 있음(empty) 상태입니다. selection은 처음에 비어 있어야 합니다.

참고

문서selection은 해당 문서에 연결된 단일 객체(singleton)이며, Document.open()이 호출되면 새 객체로 교체됩니다. 버그 15470를 참고하세요. IE9와 Opera Next 12.00 알파는 사용자가 클릭하여 나중에 범위를 null로 재설정할 수 있지만, Firefox 12.0a1과 Chrome 17 개발 버전은 그렇지 않습니다. 우리는 getRangeAt(0)이 예외를 던질 가능성이 적게 만드는 Gecko/WebKit의 방식을 따릅니다.

selection이 특정 range와 연결된 이후에는 이 명세에서 달리 요구하지 않는 한 계속 동일한 range와 연관되어야 합니다.

참고

예를 들어, DOM이 변경되어 range의 경계점이 바뀌거나, 스크립트가 경계점을 조작하는 경우에도 같은 range 객체가 selection에 계속 연결되어 있어야 합니다. 하지만 사용자가 selection을 변경하거나, 스크립트가 addRange()를 호출하면, 이 명세의 요구에 따라 selection은 새 range 객체와 연결되어야 합니다.

selectionrange가 null이 아니고 collapsed되어 있다면, 캐럿 위치는 해당 range경계점에 있어야 합니다. selection이 collapsed되어 있지 않은 경우, 이 명세는 캐럿 위치를 정의하지 않으므로 user agent는 selection의 시작, 끝, 혹은 다른 위치에 캐럿을 둘지 플랫폼 관례를 따라야 합니다.

selection방향(direction) 값을 갖습니다: forwards(정방향), backwards(역방향), 또는 무방향(directionless). 사용자가 selection을 어떤 경계점에서 시작하여(마우스 클릭) 다른 지점(드래그)으로 지정한 경우, 첫 번째 경계점이 두 번째 이후면 해당 selection은 역방향이어야 합니다. 첫 경계점이 두 번째 이전이면 정방향이고, 그렇지 않으면 무방향이어야 합니다.

selectionrange가 스크립트로 변형될 때(예: selectNode(node)로), 방향은 반드시 유지되어야 합니다.

selection앵커(anchor)포커스(focus)를 가집니다. selectionrange가 null이면 앵커포커스 모두 null입니다. selectionrange가 null이 아니고, 방향정방향이면 앵커rangestart이고, 포커스end입니다. 그렇지 않으면 포커스는 start이고, 앵커는 end입니다.

참고

selection앵커포커스는 반드시 문서 트리에 있을 필요는 없습니다. 동일한 문서셰도 트리(shadow tree)에 있을 수도 있습니다.

문서, input 요소, textarea 요소에는 부울값 has scheduled selectionchange event가 있으며, 최초에는 false입니다.

3. Selection 인터페이스

Selection 인터페이스는 각 문서와 연관된 selection과 상호작용하는 방법을 제공합니다.

WebIDL[Exposed=Window]
interface Selection {
  readonly attribute Node? anchorNode;
  readonly attribute unsigned long anchorOffset;
  readonly attribute Node? focusNode;
  readonly attribute unsigned long focusOffset;
  readonly attribute boolean isCollapsed;
  readonly attribute unsigned long rangeCount;
  readonly attribute DOMString type;
  readonly attribute DOMString direction;
  Range getRangeAt(unsigned long index);
  undefined addRange(Range range);
  undefined removeRange(Range range);
  undefined removeAllRanges();
  undefined empty();
  sequence<StaticRange> getComposedRanges(optional GetComposedRangesOptions options = {});
  undefined collapse(Node? node, optional unsigned long offset = 0);
  undefined setPosition(Node? node, optional unsigned long offset = 0);
  undefined collapseToStart();
  undefined collapseToEnd();
  undefined extend(Node node, optional unsigned long offset = 0);
  undefined setBaseAndExtent(Node anchorNode, unsigned long anchorOffset, Node focusNode, unsigned long focusOffset);
  undefined selectAllChildren(Node node);
  undefined modify(optional DOMString alter, optional DOMString direction, optional DOMString granularity);
  [CEReactions] undefined deleteFromDocument();
  boolean containsNode(Node node, optional boolean allowPartialContainment = false);
  stringifier;
};

dictionary GetComposedRangesOptions {
  sequence<ShadowRoot> shadowRoots = [];
};
anchorNode

이 속성은 앵커 노드this에서 반환해야 하며, 앵커가 null이거나 앵커문서 트리에 없으면 null을 반환해야 합니다.

anchorOffset

이 속성은 앵커오프셋this에서 반환해야 하며, 앵커가 null이거나 앵커문서 트리에 없으면 0을 반환해야 합니다.

focusNode

이 속성은 포커스 노드this에서 반환해야 하며, 포커스가 null이거나 포커스문서 트리에 없으면 null을 반환해야 합니다.

focusOffset

이 속성은 포커스오프셋this에서 반환해야 하며, 0을 반환해야 합니다. 만약 포커스가 null이거나 포커스문서 트리에 없을 경우에는 0을 반환해야 합니다.

isCollapsed

이 속성은 앵커와 포커스가 동일할 경우에만 true를 반환해야 합니다(둘 다 null인 경우 포함). 그렇지 않으면 false를 반환해야 합니다.

rangeCount

이 속성은 this비어 있음이거나 포커스 또는 앵커문서 트리에 없으면 0을 반환하고, 그렇지 않으면 1을 반환해야 합니다.

type

이 속성은 this비어 있음이거나 포커스 또는 앵커문서 트리에 없으면 "None"을 반환해야 하며, thisrangecollapsed이면 "Caret"를 반환하고, 그렇지 않으면 "Range"를 반환해야 합니다.

direction

이 속성은 this비어 있음이거나 이 선택이 무방향이면 "none"을 반환해야 합니다. 이 선택의 방향이 정방향이면 "forward"를, 역방향이면 "backward"를 반환해야 합니다.

getRangeAt() method

이 메서드는 index0가 아니거나, this비어 있음이거나 포커스 또는 앵커문서 트리에 없으면 IndexSizeError 예외를 던져야 합니다. 그렇지 않으면, thisrange에 대한 참조(복사본이 아님)를 반환해야 합니다.

Note

따라서 이 메서드를 연속해서 호출하면(그 사이에 이의 range가 제거되지 않았다면) 동일한 range 객체를 반환합니다. 특히, getSelection().getRangeAt(0) === getSelection().getRangeAt(0)selection비어 있지 않은 경우 true로 평가됩니다.

addRange() method

이 메서드는 다음 단계를 따라야 합니다:

  1. 만약 루트range의 경계점들이 속한 루트가 this와 연관된 문서가 아니라면, 이 단계를 중단합니다.
  2. 만약 rangeCount0이 아니면, 이 단계를 중단합니다.
  3. this의 range를 강한 참조로(복사본을 만들지 않고) range로 설정합니다.
Note

range가 참조로 추가되므로, 이후의 getRangeAt(0) 호출은 동일한 객체를 반환하며, 스크립트가 range를 추가한 이후에 range에 대해 수행하는 모든 변경은 selection에 반영되어야 합니다. 예를 들어 다음 코드를 실행한 후에는 selectiona가 아니라 b를 포함하게 됩니다: var r = document.createRange(); r.selectNode(a); getSelection().addRange(r); r.selectNode(b);

Note

2단계에서 Chrome 58과 Edge 25는 아무 작업도 하지 않습니다. Firefox 51은 멀티-레인지 선택을 제공합니다. 적어도 기존의 range는 유지합니다.

3단계에서는 Chrome 58과 Firefox 51이 여기서 설명한 대로 참조를 저장합니다. Edge 25는 복사본을 저장합니다. Firefox 51은 range가 수정되면 선택을 변경합니다.

removeRange() method

이 메서드는 this비어 있음 상태를 만들기 위해, 만약 thisrangerange이면 그 연관을 해제해야 합니다. 그렇지 않으면 NotFoundError를 던져야 합니다.

removeAllRanges() method

이 메서드는 this에 연관된 range이 있으면, 그 연관을 해제하여 비어 있음 상태로 만들어야 합니다.

empty() method

이 메서드는 removeAllRanges()의 별칭이며 동일하게 동작해야 합니다.

getComposedRanges() method
  1. 만약 this비어 있음이면, 빈 배열을 반환합니다.
  2. 그렇지 않으면, startNode연관된 range의 시작 노드로 정하고, startOffset시작 오프셋으로 정합니다.
  3. startNode노드이고, 그 startNode루트섀도우 루트이며, 그 루트가 options["shadowRoots"]의 어떤 항목의 shadow-including 포괄적 조상이 아니면, 다음 단계를 반복합니다:
    1. startOffsetstartNode의 루트의 인덱스로 설정합니다.
    2. startNode를 그 루트의 호스트부모로 설정합니다.
  4. endNode를 연관된 range의 끝 노드로 정하고, endOffset끝 오프셋으로 정합니다.
  5. endNode가 노드이고, 그 endNode의 루트가 섀도우 루트이며, 그 루트가 options["shadowRoots"]의 어떤 항목의 shadow-including 포괄적 조상이 아니면, 다음 단계를 반복합니다:
    1. endOffset를 그 루트의 호스트의 인덱스에 1을 더한 값으로 설정합니다.
    2. endNode를 그 루트의 호스트의 부모로 설정합니다.
  6. 시작 노드가 startNode, 시작 오프셋이 startOffset, 끝 노드가 endNode, 끝 오프셋이 endOffset인 새 StaticRange들의 배열을 반환합니다.
collapse() method

이 메서드는 다음 단계를 따라야 합니다:

  1. 만약 node가 null이면, 이 메서드는 removeAllRanges()와 동일하게 동작하고 이 단계들을 중단해야 합니다.
  2. 만약 nodeDocumentType이면, InvalidNodeTypeError 예외를 던지고 이 단계들을 중단해야 합니다.
  3. 만약 offsetnode길이보다 크면, IndexSizeError 예외를 던지고 이 단계들을 중단해야 합니다.
  4. 만약 this와 연관된 문서nodeshadow-including 포괄적 조상이 아니면, 이 단계들을 중단해야 합니다.
  5. 그렇지 않으면, newRange라는 새 range를 만들야 합니다.
  6. 시작점을 설정하여 newRangestartend를 (node, offset)로 설정해야 합니다.
  7. thisrangenewRange로 설정해야 합니다.
setPosition() method

이 메서드는 collapse()의 별칭이며 동일하게 동작해야 합니다.

collapseToStart() method

이 메서드는 InvalidStateError 예외를, 만약 this비어 있음이면 던져야 합니다. 그렇지 않으면 새 range를 생성하고, 그 range의 시작점을 설정하여 그 range의 startendthis의 range의 start로 설정한 다음, this의 range를 새로 생성한 range로 설정해야 합니다.

Note

collapseToStart/End의 경우, IE9는 기존 range를 변경(mutates)하고, Firefox 9.0a2와 Chrome 15 개발 버전은 새 것으로 교체합니다. 명세는 다수의 구현을 따라 새 것으로 교체하여 이전 Range 객체는 변경되지 않도록 합니다.

collapseToEnd() method

이 메서드는 InvalidStateError 예외를, 만약 this비어 있음이면 던져야 합니다. 그렇지 않으면 새 range를 생성하고, 그 range의 시작점을 설정하여 그 range의 startendthis의 range의 end로 설정한 다음, this의 range를 새로 생성한 range로 설정해야 합니다.

extend() method

이 메서드는 다음 단계를 따라야 합니다:

  1. 만약 this와 연관된 문서가 nodeshadow-including 포괄적 조상이 아니면, 이 단계들을 중단해야 합니다.
  2. 만약 this비어 있음이면, InvalidStateError 예외를 던지고 이 단계들을 중단해야 합니다.
  3. oldAnchoroldFocusthis앵커포커스로 두고, newFocus를 (node, offset)인 새로운 경계점으로 정합니다.
  4. newRange라는 새 range를 만듭니다.
  5. 만약 node루트this의 연관된 range의 루트와 다르면, newRange의 start와 end를 newFocus로 설정해야 합니다.
  6. 그렇지 않으면, 만약 oldAnchorbefore 또는 newFocus와 동일하면, newRange의 start를 oldAnchor로 설정한 다음, 그 end를 newFocus로 설정해야 합니다.
  7. 그렇지 않으면, newRange의 start를 newFocus로 설정하고 그 end를 oldAnchor로 설정해야 합니다.
  8. thisrangenewRange로 설정해야 합니다.
  9. 만약 newFocusbefore oldAnchor이면, thisdirectionbackwards로 설정해야 합니다. 그렇지 않으면 forwards로 설정해야 합니다.
Note

2011년 1월경 역공학된 내용입니다. IE는 이를 지원하지 않으므로 Firefox(extend()를 2000년 이전에 구현)와 WebKit(2007년에 구현)에 의존하고 있습니다. Opera는 구현이 호환되지 않는 것으로 간주하여 대부분 무시하고 있습니다. Firefox 12.0a1은 기존 range를 변경하는 것으로 보입니다. IE9는 extend()를 지원하지 않으며, Chrome 17 개발 버전이나 Opera Next 12.00 알파가 변경하는지 교체하는지 판단하기 어렵습니다(어차피 getRangeAt()가 복사본을 반환하기 때문). 그럼에도 불구하고 collapse()와 일관되도록 Gecko와는 다른 방식을 따릅니다.

setBaseAndExtent() method

이 메서드는 다음 단계를 따라야 합니다:

  1. 만약 anchorOffsetanchorNode길이보다 크거나, focusOffsetfocusNode길이보다 크면, IndexSizeError 예외를 던지고 이 단계들을 중단해야 합니다.
  2. 만약 this와 연관된 문서가 anchorNodefocusNodeshadow-including 포괄적 조상이 아니면, 이 단계들을 중단해야 합니다.
  3. anchor을 (anchorNode, anchorOffset)인 경계점으로, focus을 (focusNode, focusOffset)인 경계점으로 정합니다.
  4. newRange라는 새 range를 만듭니다.
  5. 만약 anchorbefore focus이면, newRange의 start를 anchor로, end를 focus로 설정합니다. 그렇지 않으면 start를 focus로, end를 anchor로 설정합니다.
  6. thisrangenewRange로 설정해야 합니다.
  7. 만약 focusbefore anchor이면, thisdirectionbackwards로 설정합니다. 그렇지 않으면 forwards로 설정합니다.
selectAllChildren() method

이 메서드는 다음 단계를 따라야 합니다:

  1. 만약 nodeDocumentType이면, InvalidNodeTypeError 예외를 던지고 이 단계들을 중단해야 합니다.
  2. 만약 node루트this와 연관된 문서가 아니면, 이 단계들을 중단해야 합니다.
  3. newRange라는 새 range를 만들고, childCountnode의 자식 수로 정합니다.
  4. newRangestart를 (node, 0)으로 설정합니다.
  5. newRangeend를 (node, childCount)으로 설정합니다.
  6. thisrangenewRange로 설정합니다.
  7. thisdirectionforwards로 설정해야 합니다.
Note

주로 Firefox 9.0a2를 기반으로 한 내용입니다. 재현하지 못한 버그가 있는데, 예를 들어 Document를 인자로 전달하면 end offset이 자식 수가 아닌 1이 되는 문제가 있습니다. 또한 구현이 DOMException과 합쳐지기 이전의 것이어서 RangeException을 던집니다.

IE9는 유사하게 동작하지만 결함이 있습니다. 노드가 분리되었거나 display:none인 경우 "Unspecified error."를 던지고, 일부 다른 무작위한 경우에도 에러를 던집니다. 분리된 코멘트에 대해서는 "Invalid argument."를 던집니다(오직 그 경우에만). 마지막으로 코멘트를 전달하면 텍스트 노드와 달리 코멘트 전체를 선택하는 것처럼 보입니다.

Chrome 16 개발 버전은 Selection 구현에 따라 예상대로 동작합니다. 보이지 않는 것을 선택하기를 거부하므로 거의 항상 잘못된 동작을 합니다. Opera 11.50은 모든 테스트에서 아무 작업도 하지 않습니다.

새 range는 기존의 것을 대체하며, 변경(mutates)하지 않습니다. 이는 IE9와 Firefox 12.0a1과 일치합니다. (Chrome 17 개발 버전과 Opera Next 12.00 알파는 getRangeAt()가 복사본을 반환하므로 테스트할 수 없습니다.)

modify() method

이 메서드는 다음 단계를 따라야 합니다:

  1. 만약 alter가 "extend" 또는 "move"와 ASCII 대소문자 구분 없이 일치하지 않으면, 이 단계를 중단합니다.
  2. 만약 direction가 "forward", "backward", "left", 또는 "right"와 ASCII 대소문자 구분 없이 일치하지 않으면, 이 단계를 중단합니다.
  3. 만약 granularity가 "character", "word", "sentence", "line", "paragraph", "lineboundary", "sentenceboundary", "paragraphboundary", "documentboundary" 중 하나와 ASCII 대소문자 구분 없이 일치하지 않으면, 이 단계를 중단합니다.
  4. 만약 this selection이 비어 있으면, 이 단계를 중단합니다.
  5. effectiveDirectionbackwards로 정합니다.
  6. 만약 direction가 "forward"와 ASCII 대소문자 구분 없이 일치하면, effectiveDirectionforwards로 설정합니다.
  7. 만약 direction가 "right"와 ASCII 대소문자 구분 없이 일치하고, inline base directionthis selectionfocus에 대해 ltr이면, effectiveDirectionforwards로 설정합니다.
  8. 만약 direction가 "left"와 ASCII 대소문자 구분 없이 일치하고, inline base directionthis selectionfocus에 대해 rtl이면, effectiveDirectionforwards로 설정합니다.
  9. this selectiondirectioneffectiveDirection으로 설정합니다.
  10. 만약 alter가 "extend"와 ASCII 대소문자 구분 없이 일치하면, this selectionfocus를 사용자가 granularity로 선택을 확장하라고 요청한 것과 같은 위치로 설정합니다.
  11. 그렇지 않으면, thisselectionfocusanchor를 사용자가 granularity로 선택을 이동하라고 요청한 것과 같은 위치로 설정합니다.
Note

각 granularity별로 선택을 확장하거나 이동한다는 것이 정확히 무엇을 의미하는지 더 정확히 정의할 필요가 있습니다.

deleteFromDocument() method

이 메서드는 deleteContents()thisrange에 대해 호출해야 합니다. 단, this비어 있음이 아니고, 포커스앵커문서 트리에 있을 때만입니다. 그렇지 않으면 이 메서드는 아무 작업도 하지 않아야 합니다.

Note

이것은 실제로 range를 교체하지 않고 변경(mutates)하는 유일한 메서드입니다. 이는 IE9와 Firefox 12.0a1과 일치합니다. (Chrome 17 개발 버전과 Opera Next 12.00 알파는 getRangeAt()가 복사본을 반환하므로 테스트할 수 없습니다.)

containsNode() method

만약 this비어 있음이거나, node루트this와 연관된 문서가 아니면, 이 메서드는 false를 반환해야 합니다.

그렇지 않으면, 만약 allowPartialContainmentfalse이면, 이 메서드는 다음 조건이 모두 성립할 때에만 true를 반환해야 합니다: 자신의 rangestartnode 안의 첫 번째 경계점보다 앞서거나 시각적으로 동등하고, 그 rangeendnode 안의 마지막 경계점보다 뒤이거나 시각적으로 동등해야 합니다.

만약 allowPartialContainmenttrue이면, 이 메서드는 다음 조건이 모두 성립할 때에만 true를 반환해야 합니다: 자신의 range의 시작이 node 안의 마지막 경계점보다 앞서거나 시각적으로 동등하고, 자신의 range의 끝이 node 안의 첫 번째 경계점보다 뒤이거나 시각적으로 동등해야 합니다.

stringifier

문자열화는 rangethis에 연관되어 있을 경우 렌더된 텍스트들을 연결한 문자열을 반환해야 합니다.

만약 선택이 textarea 또는 input 요소 내에 있으면, 해당 요소의 value에서 선택된 부분 문자열을 반환해야 합니다.

참고

Gecko의 nsISelection.idl도 참고하세요. 이 명세에는 아직 거기 있는 모든 내용이 포함되어 있지는 않습니다. 특히 selectionLanguageChange()와 containsNode()가 없습니다. 이것들은 Range의 용어로 어떻게 정의할지 알지 못해서 빠져 있습니다.

참고

원래 Selection 인터페이스는 Netscape의 기능이었습니다. 최초 구현은 Gecko(Firefox)에 이어졌고, 이 기능은 이후 다른 브라우저 엔진에서도 독립적으로 구현되었습니다. Netscape 구현은 항상 하나의 선택에 여러 개의 범위를 허용했으며, 예를 들어 사용자가 테이블의 한 열을 선택할 수 있도록 했습니다. 하지만 다중 범위 선택은 웹 개발자는 알지 못하고 Gecko 개발자조차 올바로 처리하지 못하는 불쾌한 코너 케이스가 되는 것으로 드러났습니다. 다른 브라우저 엔진은 이 기능을 구현하지 않았으며, 다양한 불호환 방식으로 선택을 한 범위로 고정(clamp)했습니다.

본 명세는 여러 범위를 허용했던 Gecko와 달리, 하나의 선택에는 최대 한 개의 범위만 허용하도록 비-Gecko 엔진의 동작을 따릅니다. 다만, API 설계는 본래 임의 개수의 범위를 위한 것으로 만들어져 있어 removeRange()removeAllRanges()가 함께 존재하는 점이나, 반드시 0이어야 하는 정수 인자를 받는 getRangeAt() 등의 특이점이 있습니다.

Selection 인터페이스의 모든 멤버는 이 객체가 나타내는(있는 경우) range 객체에 대한 연산을 기준으로 정의됩니다. 이러한 연산은 Range 인터페이스에 대해 정의된 대로 예외를 일으킬 수 있으며, 이로 인해 Selection 인터페이스의 멤버들도 위에 명시된 것 이외에 예외를 일으킬 수 있습니다.

4. 다른 인터페이스에 대한 확장

본 명세는 여기서 정의된 인터페이스에 진입점(entry point)을 제공하기 위해 여러 인터페이스를 확장합니다.

4.1 Document 인터페이스에 대한 확장

Document 인터페이스는 [HTML]에 정의되어 있습니다.

WebIDLpartial interface Document {
  Selection? getSelection();
};
getSelection() 메서드

이 메서드는 selectionthis와 연관되어 있고 this브라우징 컨텍스트가 있으면 해당 selection을 반환해야 하며, 그렇지 않으면 null을 반환해야 합니다.

4.2 Window 인터페이스에 대한 확장

Window 인터페이스는 [HTML]에 정의되어 있습니다.

WebIDLpartial interface Window {
  Selection? getSelection();
};
getSelection() 메서드

이 메서드는 getSelection()thisWindow.document 속성에서 호출하여 그 결과를 반환해야 합니다.

4.3 GlobalEventHandlers 인터페이스에 대한 확장

GlobalEventHandlers 인터페이스는 [HTML]에 정의되어 있습니다.

WebIDLpartial interface mixin GlobalEventHandlers {
  attribute EventHandler onselectstart;
  attribute EventHandler onselectionchange;
};
onselectstart

이 속성은 모든 HTML 요소, Document 객체, Window 객체가 지원하는 이벤트 핸들러 IDL 속성이어야 하며, selectstart 이벤트에 대응합니다.

onselectionchange

이 속성은 모든 HTML 요소, Document 객체, Window 객체가 지원하는 이벤트 핸들러 IDL 속성이어야 하며, selectionchange 이벤트에 대응합니다.

5. DOM 변경에 대한 대응

사용자 에이전트가 데이터를 대체하거나 부분 문자열CharacterData에 대해 처리할 때, 사용자 에이전트는 range를 해당 selectionnode document에서 CharacterData와 연관된 live range처럼 갱신해야 합니다.

사용자 에이전트가 Text 노드를 분할할 때, 사용자 에이전트는 range를 해당 selectionnode document에서 Text와 연관된 live range처럼 갱신해야 합니다.

사용자 에이전트가 normalize() 메서드의 단계를 실행할 때, 사용자 에이전트는 range를 해당 selectionnode document에서 this와 연관된 live range처럼 갱신해야 합니다.

사용자 에이전트가 노드 제거 또는 노드 삽입을 수행할 때, 사용자 에이전트는 range를 해당 selectionnode document에서 노드와 연관된 live range처럼 갱신해야 합니다.

6. 사용자 상호작용

사용자 에이전트는 사용자가 선택활성 문서와 연관된 것을 변경할 수 있도록 허용해야 합니다. 사용자가 선택을 수정하면, 사용자 에이전트는 적절한 범위시작을 가지는 새로운 범위를 생성하고 이 새로운 선택을 해당 새로운 범위와 연관시켜야 하며(기존 범위를 수정하지 않습니다), 선택방향정방향으로 설정해야 합니다. 단, 시작이전에 있거나 과 같으면 정방향으로, 역방향으로 설정해야 합니다. 만약 시작보다 이전이면 역방향으로, 플랫폼 관례로 인해 시작의 순서를 정할 수 없으면 무방향으로 설정해야 합니다.

사용자 에이전트는 어떤 사용자 동작(예: 편집 불가능한 영역 클릭)에 대해서도 이미 비어 있음이 아닌 selection비어 있음으로 만들면 안 됩니다.

참고

bug 15470을 참고하세요. IE9와 Opera Next 12.00 알파는 사용자가 어디든 클릭하면 이후 범위를 null로 재설정할 수 있도록 허용합니다; Firefox 12.0a1과 Chrome 17 개발자 버전은 그렇지 않습니다. Gecko/WebKit 방식을 따릅니다. getRangeAt(0)이 예외를 던질 가능성이 줄어들기 때문입니다.

6.1 selectstart 이벤트

사용자 에이전트가 사용자가 유발한 동작에 응답하여 selection에 새 newRange 범위를 연관시키려고 할 때, 사용자 에이전트는 selection이 이전에 비어 있음 이었거나, 이전에 연관된 범위가 collapsed였던 경우, selection 변경 전에 newRange경계점노드에서 selectstart라는 이름의 이벤트를(버블링되고 취소 가능) 발생시켜야 합니다.

이벤트가 취소된 경우, 사용자 에이전트는 selection을 변경하면 안 됩니다.

사용자 에이전트는 selection을 비어 있는 상태로 설정할 때 이벤트를 발생시키면 안 됩니다.

6.2 selectionchange 이벤트

selectionrange와 연결이 끊기거나, 새로운 range와 연관되거나, 연관된 range경계점이 사용자 또는 콘텐츠 스크립트에 의해 변형되는 경우, 사용자 에이전트는 해당 document에서 selectionchange 이벤트 예약을 해야 합니다.

input 혹은 textarea 요소에서 텍스트 선택이 제공되고, 그 선택에 대한 범위나 direction(방향)이 변화하면, 사용자 에이전트는 해당 요소에 대해 selectionchange 이벤트 예약을 해야 합니다.

6.2.1 selectionchange 이벤트 예약

노드 target에서 selectionchange 이벤트 예약을 실행하려면 다음 단계를 따릅니다:

  1. targethas scheduled selectionchange event가 true이면 이 단계를 중단합니다.
  2. 태스크 큐에 추가 (user interaction task source)하여 selectionchange 이벤트 발생target에서 시행합니다.

6.2.2 selectionchange 이벤트 발생

노드 target에서 selectionchange 이벤트 발생을 실행하려면 다음 단계를 따릅니다:

  1. targethas scheduled selectionchange event를 false로 설정합니다.
  2. target이 요소이면, selectionchange라는 이름의 이벤트(버블링되고 취소 불가)를 발생시킵니다.
  3. 그렇지 않고 target이 document이면, selectionchange라는 이름의 이벤트(버블링되지 않고 취소 불가)를 발생시킵니다.

7. 적합성

규범적이지 않은 섹션과 마찬가지로, 이 명세의 모든 작성 가이드라인, 도표, 예제, 참고사항 또한 규범적이지 않습니다. 이 명세의 그 외 모든 사항은 규범적입니다.

이 명세는 다음 한 가지 제품에 적용되는 적합성 기준을 정의합니다: 이 명세가 담고 있는 인터페이스를 구현하는 user agent.

8. 보안 및 개인정보 보호 고려사항

이 표준에는 알려진 보안 고려사항이 없습니다.

사용자의 보조 기술 사용 노출로 인한 잠재적 프라이버시 위험을 완화하기 위해, 예를 들어 user agent는 사용자가 문서의 selection을 수정하도록 선택할 때, selectstart 또는 selectionchange 이벤트와 일반적으로 연관되는 마우스 및 키보드 이벤트를 에뮬레이션하도록 선택할 수 있습니다.

A. 감사

많은 감사의 말씀을 전합니다

B. 참고문헌

B.1 규범적 참조

[css-writing-modes-4]
CSS Writing Modes Level 4. Elika Etemad; Koji Ishii. W3C. 2019년 7월 30일. W3C Candidate Recommendation. URL: https://www.w3.org/TR/css-writing-modes-4/
[dom]
DOM 표준. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[HTML]
HTML 표준. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[infra]
Infra 표준. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
[url]
URL 표준. Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/
[WEBIDL]
Web IDL 표준. Edgar Chen; Timothy Gu. WHATWG. Living Standard. URL: https://webidl.spec.whatwg.org/