選択 API

W3C ワーキングドラフト

この文書の詳細
This version:
https://www.w3.org/TR/2025/WD-selection-api-20250105/
Latest published version:
https://www.w3.org/TR/selection-api/
Latest editor's draft:
https://w3c.github.io/selection-api/
History:
https://www.w3.org/standards/history/selection-api/
コミット履歴
Test suite:
https://wpt.fyi/results/selection/
Editor:
(Apple Inc.)
Feedback:
GitHub w3c/selection-api (プルリクエスト, 新しい issue, 未解決の issue)

概要

この文書は、Selection API および選択に関連する機能の仕様の予備草案です。これは HTML specification のいくつかの古いセクションと、古い DOM Range specification の選択に関する部分を置き換えるものです。

この文書は選択のための API を定義しており、ユーザーや作成者が文書の一部を選択したり、コピー、貼り付け、その他の編集操作のための関心点を指定したりできるようにします。

この文書の状態

このセクションは、本書の公開時点での状態を説明します。現行の W3C 出版物の一覧およびこの技術報告書の最新の改訂は、W3C technical reports index(https://www.w3.org/TR/)で確認できます。

本文書は作業中です。

この文書はWeb Editing Working Groupによって、Recommendation track を用いてWorking Draftとして公開されました。

Working Draft としての公開は、W3C およびそのメンバーによる承認を意味するものではありません。

本文書は草案であり、いつでも更新、置換、または他の文書により廃止される可能性があります。本稿を作業中以外のものとして引用することは適切ではありません。

この文書は、W3C Patent Policy の下で運営されるグループによって作成されました。 W3C は、グループの成果物に関連して行われた 特許開示の公開リスト を維持しています;そのページには特許を開示するための手順も記載されています。個人が自身が本質的請求(Essential Claim(s))を含むと考える特許について実際に知識を有する場合は、W3C 特許方針の第6節 に従って情報を開示しなければなりません。

この文書は、2023年11月03日付の W3C プロセス文書 に準拠して管理されています。

1. 背景

このセクションは規範的ではありません。

IE9 と Firefox 6.0a2 は、選択内の任意の範囲を許可しており、これは元々この仕様書が述べていた内容に従っています。しかし、これにより著者・実装者・仕様書の作成者が対処しなければならない不都合なコーナーケースが発生し、実際にはあまり理にかなっていません。Chrome 14 dev と Opera 11.11 は、空の要素内に選択が入らないようにするなど、選択を積極的に正規化していますが、これも著者の柔軟性を奪うという理由から良くない考え方とされています。

そこで私は、ある程度の単純化を可能にしつつも著者をあまり制限しない妥協案として仕様を変更しました。 ディスカッション を参照してください。基本的には、要素ノードやテキストノード以外の 境界点 を含む範囲や、Document から派生しない境界点を選択に含めようとすると、いくつかの場面で例外を投げる形になります。

しかし、これにより getRangeAt() は参照ではなくコピーを返す必要が生じました。また、コーナーケースで妙な故障が発生しやすくなります。特に重要なのは、DOM 変更が発生した際(たとえば、境界点のノードが親から取り除かれ、新しい境界点が非テキスト/非要素ノード内に配置される場合など)、さまざまな問題が発生する可能性があることです。さらに、従来の仕様は2つの主要な実装に合致するという利点がありましたが、新しい挙動はどの実装にも一致しませんでした。そこで元に戻しました。

バグ 15470 を参照。 IE9、Firefox 12.0a1、Chrome 17 dev、Opera Next 12.00 alpha では、範囲は初期状態で null です。

2. 定義

document はそれぞれ ブラウジングコンテキスト を持つ場合、 一意な selection が関連付けられます。

これは HTML 仕様の要件です。IE9 と Opera Next 12.00 alpha はこれに従うようですが、Firefox 12.0a1 と Chrome 17 dev はそうではないようです。Mozilla バグWebKit バグ を参照。

この selection は、document 内のすべてのコンテンツ(ネストされた document を除く)や、その 編集ホスト を含めて、共有されなければなりません。

selection は、1つの range と関連付けできます。 rangeselection に関連付けられていない場合、 選択状態は です。選択状態は初期状態で でなければなりません。

documentselection は、その document に紐づいたシングルトンオブジェクトであり、 Document.open() が呼ばれると新しいオブジェクトに置き換えられます。バグ 15470 を参照。 IE9 と Opera Next 12.00 alpha は、クリックにより後から範囲を null にできますが、Firefox 12.0a1 と Chrome 17 dev はできません。Gecko/WebKit の動作に従います。なぜなら、getRangeAt(0) が例外を投げる可能性が減少するからです。

selectionrange と関連付けられると、 仕様で別途要求されない限り、そのまま同じ range と紐づき続けなければなりません。

たとえば、DOM が範囲の境界点を変更するような形で変化した場合、またはスクリプトが範囲の境界点を変更した場合でも、 同じ range オブジェクトが引き続き selection に紐づく必要があります。ただし、ユーザーが selection を変更したりスクリプトが addRange() を呼んだ場合は、 selection は新しい range オブジェクトと関連付け直されなければなりません。

selectionrange が null でなく、かつ 折りたたまれている 場合は、キャレットの位置はその range境界点 でなければなりません。折りたたまれていない場合、本仕様はキャレットの位置を定義しません。ユーザーエージェントは、キャレットを選択の開始・終了・その他どこに表示するかを、プラットフォームの慣習に則って決定すべきです。

selection には directionforwardsbackwardsdirectionless)があります。ユーザーが selection を、 境界点 のいずれかをまず指定してから(例:一点をクリックし、他方へドラッグする)、もう一方を指定した場合、最初に指定した 境界点 が二番目より であれば、その selection の初期状態は backwards でなければなりません。最初が であれば forwards。 それ以外の場合は directionless とします。

selectionrange がスクリプトで変更された場合(例:selectNode(node) など)、 selectiondirection は保持されなければなりません。

selectionanchorfocus も持ちます。selectionrange が null のときは、 anchorfocus のいずれも null です。 directionforwards なら、anchorrangestartfocusend です。 それ以外は focusstartanchorend です。

selectionanchor および focus は必ずしも document tree 内にある必要はありません。 同じ documentshadow tree 内にあっても構いません。

documentinput 要素、textarea 要素 には、boolean型の has scheduled selectionchange event があり、 その初期値は false です。

3. Selection インターフェース

Selection インターフェースは、各 document に関連付けられている 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

この属性は、anchornodethis から返す必要があります。あるいは、anchor が null であるか、または anchordocument tree に存在しない場合は null を返します。

anchorOffset

この属性は、anchoroffsetthis から返す必要があります。あるいは、anchor が null であるか、または anchordocument tree に存在しない場合は 0 を返します。

focusNode

この属性は、focusnodethis から返す必要があります。あるいは、focus が null であるか、または focusdocument tree に存在しない場合は null を返します。

focusOffset

この属性は、focusoffsetthis から返す必要があります。あるいは、focus が null であるか、または focusdocument tree に存在しない場合は 0 を返します。

isCollapsed

この属性は、anchorfocus が同一である場合に限り true を返さなければなりません(両方が null の場合を含む)。それ以外の場合は false を返します。

rangeCount

この属性は、thisempty であるか、または focus または anchor のいずれかが document tree に存在しない場合は 0 を返し、そうでない場合は 1 を返さなければなりません。

type

この属性は、thisempty であるか、または focus または anchor のいずれかが document tree に存在しない場合は "None" を返す必要があります。rangecollapsed である場合は "Caret"、それ以外の場合は "Range" を返します。

direction

この属性は、thisempty であるか、またはこの選択が directionless である場合は "none" を返さなければなりません。選択の方向が forwards の場合は "forward"、選択の方向が backwards の場合は "backward" を返します。

getRangeAt() method

IndexSizeError 例外を、index0 でない場合、または thisempty である場合、あるいは focus または anchor のいずれかが document tree に存在しない場合に投げなければなりません。そうでなければ、このオブジェクトの range への参照(コピーではなく)を返す必要があります。

Note

したがって、このメソッドを続けて呼び出しても、途中でこのオブジェクトの range が取り除かれていなければ同じ range オブジェクトが返されます。特に、getSelection().getRangeAt(0) === getSelection().getRangeAt(0) は、選択が empty でない場合に true と評価されます。

addRange() method

このメソッドは次の手順に従わなければなりません:

  1. もし range の境界点の root が、documentthis に関連付けられているもの)でなければ、これらの手順を中止します。
  2. もし rangeCount0 でない場合、これらの手順を中止します。
  3. this の range を、強い参照(コピーを作らない)によって range に設定します。
Note

range を参照で追加するため、後続の getRangeAt(0) 呼び出しは同一のオブジェクトを返し、スクリプトが range に対して行った変更は、それが取り除かれたり置換されたりするまで selection に反映されなければなりません。具体的には、次のコードを実行すると selectionb を含むようになります(a ではなく): 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

このメソッドは、もし thisempty にするために、その rangerange と等しい場合は関連付けを解除して this を empty にしなければなりません。そうでない場合は NotFoundError を投げます。

removeAllRanges() method

このメソッドは、this が関連付けられた range を持っている場合、その関連付けを解除して this を empty にしなければなりません。

empty() method

このメソッドは removeAllRanges() のエイリアスであり、同一の動作をしなければなりません。

getComposedRanges() method
  1. もし thisempty であれば、空の配列を返します。
  2. それ以外の場合、startNoderange に関連付けられた開始ノードとし、startOffset をその 開始オフセット とします。
  3. もし startNode がノードであり、かつその rootshadow root であり、かつその root が options["shadowRoots"] のいずれかの shadow-including inclusive ancestor でない限り、次の手順を繰り返します:
    1. startOffsetstartNode の root の index に設定します。
    2. startNode をその root の host の親に設定します。
  4. endNoderange に関連付けられた終了ノードとし、endOffset をその 終了オフセット とします。
  5. もし endNode がノードであり、その rootshadow root であり、かつその root が options["shadowRoots"] のいずれかの shadow-including inclusive ancestor でない限り、次の手順を繰り返します:
    1. endOffsetendNode の root の index プラス 1 に設定します。
    2. endNode をその root の host の親に設定します。
  6. 開始ノードが startNode、開始オフセットが startOffset、終了ノードが endNode、終了オフセットが endOffset の新しい StaticRange を含む配列を返します。
collapse() method

このメソッドは次の手順に従わなければなりません:

  1. もし node が null であれば、このメソッドは removeAllRanges() と同一に振る舞い、これらの手順を中止します。
  2. もし nodeDocumentType であれば、InvalidNodeTypeError を投げてこれらの手順を中止します。
  3. もし offsetnodelength より大きければ、IndexSizeError を投げてこれらの手順を中止します。
  4. もし documentshadow-including inclusive ancestor でない場合、これらの手順を中止します。
  5. それ以外の場合、newRange を新しい range とします。
  6. 開始点を設定 し、newRange の開始および終了を (node, offset) に設定します。
  7. thisrangenewRange に設定します。
setPosition() method

このメソッドは collapse() のエイリアスであり、同一の動作をしなければなりません。

collapseToStart() method

このメソッドは、もし InvalidStateError を投げるべき条件(すなわちこのオブジェクトが empty である場合)でなければ、新しい range を作成し、その開始と終了の両方をこのオブジェクトの range の開始位置に設定し、作成した range を this の range に設定しなければなりません。

Note

collapseToStart/End について、IE9 は既存の range を変更しますが、Firefox 9.0a2 と Chrome 15 dev は新しい range に置き換えます。仕様は多数派に従い、新しい range に置き換えて古い Range オブジェクトを変更しないようにしています。

collapseToEnd() method

このメソッドは、もし InvalidStateError を投げるべき条件(すなわち this が empty である場合)でなければ、新しい range を作成し、その開始と終了の両方をこのオブジェクトの range の終了位置に設定し、作成した range を this の range に設定しなければなりません。

extend() method

このメソッドは次の手順に従わなければなりません:

  1. もし documentthis に関連付けられているもの)が shadow-including inclusive ancestor でない場合、これらの手順を中止します。
  2. もし thisempty であれば、InvalidStateError を投げてこれらの手順を中止します。
  3. oldAnchoroldFocus を this の anchor および focus とし、newFocus を境界点 (node, offset) とします。
  4. newRange を新しい range とします。
  5. もし noderoot が this の range の root と同じでない場合、newRange の開始と終了を newFocus に設定 します。
  6. そうでなく、もし oldAnchorbefore または newFocus と等しい場合、newRange の開始を oldAnchor に設定 し、その終了を newFocus に設定します。
  7. それ以外の場合、newRange の開始を newFocus に設定 し、その終了を oldAnchor に設定します。
  8. thisrangenewRange に設定します。
  9. もし newFocusoldAnchor より before であれば、thisdirectionbackwards に設定します。そうでなければ forwards に設定します。
Note

2011年1月頃にリバースエンジニアリングされた実装に基づきます。IE はサポートしておらず、Firefox(2000年以前に実装)と WebKit(2007年に実装)に依拠しています。Opera の実装は互換性がないため主に無視しています。Firefox 12.0a1 は既存の range を変更するようです。IE9 は extend() をサポートしておらず、Chrome 17 dev や Opera Next 12.00 alpha が変更または置換するかは判別できません(getRangeAt() がコピーを返すため)。それでも仕様は collapse() と一貫させるために Gecko の挙動とは異なる決定をしています。

setBaseAndExtent() method

このメソッドは次の手順に従わなければなりません:

  1. もし anchorOffsetanchorNodelength より大きい、または focusOffsetfocusNodelength より大きい場合、IndexSizeError を投げてこれらの手順を中止します。
  2. もし documentshadow-including inclusive ancestor でない場合、これらの手順を中止します。
  3. anchor を境界点 (anchorNode, anchorOffset)、focus を境界点 (focusNode, focusOffset) とします。
  4. newRange を新しい range とします。
  5. もし anchorbefore focus であれば、newRange の開始を anchor、終了を focus に設定 します。そうでなければ開始を focus、終了を anchor に設定します。
  6. thisrangenewRange に設定します。
  7. もし focusanchor より before であれば、thisdirectionbackwards に設定します。そうでなければ forwards に設定します。
selectAllChildren() method

このメソッドは次の手順に従わなければなりません:

  1. もし nodeDocumentType であれば、InvalidNodeTypeError を投げてこれらの手順を中止します。
  2. もし noderoot が、documentthis に関連付けられているもの)でない場合、これらの手順を中止します。
  3. newRange を新しい range とし、childCountnode の子の数として定義します。
  4. newRange の開始を (node, 0) に設定します。
  5. newRange の終了を (node, childCount) に設定します。
  6. thisrangenewRange に設定します。
  7. thisdirectionforwards に設定します。
Note

主に Firefox 9.0a2 に基づきます。引数に Document を渡すと終了オフセットが子の数ではなく 1 になるバグがありました。また、実装が DOMException と RangeException の統合に先行していたため、RangeException を投げます。

IE9 も類似の振る舞いですが不具合があります。ノードがデタッチされているか display:none の場合に "Unspecified error." を投げたり、デタッチされたコメントに対して "Invalid argument." を投げたりします。コメントを渡すとテキストノードとは異なりコメント全体を選択するようです。

Chrome 16 dev は Selection 実装に従った動作をします。表示されていないものは選択しないため、多くの場合誤っています。Opera 11.50 はテストでは何もしませんでした。

新しい range は既存のものを置換し、変異させません。これは IE9 と Firefox 12.0a1 に一致します。(Chrome 17 dev と Opera Next 12.00 alpha は 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. もし thisselection が empty であれば、これらの手順を中止します。
  5. effectiveDirectionbackwards にします。
  6. もし direction が "forward" と ASCII 大文字小文字を区別しない一致であれば、effectiveDirectionforwards に設定します。
  7. もし direction が "right" と一致し、かつ this の選択の inline base directionltr であれば、effectiveDirectionforwards に設定します。
  8. もし direction が "left" と一致し、かつ this の選択の inline base directionrtl であれば、effectiveDirectionforwards に設定します。
  9. thisselectiondirectioneffectiveDirection に設定します。
  10. もし alter が "extend" と一致する場合、thisselectionfocus を、ユーザーが granularity で選択を拡張するように要求したかのような位置に設定します。
  11. それ以外の場合、thisselectionfocusanchor を、ユーザーが granularity で選択を移動するように要求したかのような位置に設定します。
Note

各 granularity ごとに選択を拡張または移動するということが具体的に何を意味するのか、より正確に定義する必要があります。

deleteFromDocument() method

このメソッドは、もし thisempty でなく、かつ focusanchor の両方が document tree に存在する場合、deleteContents() を this の range に対して呼び出さなければなりません。そうでない場合は何もしません。

Note

これは range を置換するのではなく実際に変異させる唯一のメソッドです。IE9 と Firefox 12.0a1 に一致します。(Chrome 17 dev と Opera Next 12.00 alpha は getRangeAt() がコピーを返すためテスト不可。)

containsNode() method

もし thisempty であるか、または noderoot がこの this に関連付けられたドキュメントでない場合、このメソッドは false を返さなければなりません。

そうでない場合、もし allowPartialContainmentfalse であれば、このメソッドは、(1) 自身の rangestartnode 内の最初の境界点と等しいかそれより前であり、かつ (2) 自身の range の endnode 内の最後の境界点と等しいかそれより後である場合に限り true を返さなければなりません(視覚的に等価である場合を含む)。

もし allowPartialContainmenttrue であれば、このメソッドは、(1) 自身の range の startnode 内の最後の境界点と等しいかそれより前であり、かつ (2) 自身の range の endnode 内の最初の境界点と等しいかそれより後である場合に限り true を返さなければなりません(視覚的に等価である場合を含む)。

stringifier

文字列化は、この this に関連付けられた range のレンダリングされたテキストの連結を返さなければなりません。

選択が textarea または input 要素内にある場合は、その value の選択された部分文字列を返さなければなりません。

また、Geckoの nsISelection.idl も参照してください。この仕様にはまだすべての内容が含まれているわけではなく、特に selectionLanguageChange() や containsNode() がありません。これらは、Rangeの定義で表現する方法が分からなかったため、欠落しています。

元々、SelectionインターフェースはNetscapeの機能でした。最初の実装はGecko(Firefox)に受け継がれ、後に他のブラウザーエンジンによって独立して実装されました。Netscapeの実装では、単一選択内で常に複数の範囲を許可していました。例えば、ユーザーが表の列を選択できるようにするためです。しかし、マルチレンジ選択はウェブ開発者が把握しておらず、Geckoの開発者でさえ正しく処理することはほとんどありませんでした。他のブラウザーエンジンはその機能を実装せず、さまざまな非互換な方法で選択を単一範囲に制限していました。

この仕様は、選択を最大で一つの範囲に制限する点でGecko以外のエンジンに従っていますが、APIは元々任意個数の範囲の選択を想定して設計されています。これが removeRange()removeAllRanges() が併存していたり、常にゼロでなければならない整数引数を取る getRangeAt() メソッドがあったりするなどの奇妙さの理由です。

Selection インターフェースのすべてのメンバーは、そのオブジェクトによって表される(存在すれば)range オブジェクトに対する操作の観点から定義されています。これらの操作は、Range インターフェースで定義されるように例外を投げることがあります。したがって、Selection インターフェースのメンバーも、上記で明示的に記述された場合に加え、例外をスローする可能性があります。

4. 他のインターフェースへの拡張

この仕様は、ここで定義されるインターフェースへのエントリーポイントを提供するために、いくつかのインターフェースを拡張します。

4.1 Document インターフェースへの拡張

Document インターフェースは [HTML] で定義されています。

WebIDLpartial interface Document {
  Selection? getSelection();
};
getSelection() メソッド

このメソッドは、selectionthis に関連付けられた ブラウジングコンテキスト がある場合は返し、それ以外の場合は null を返さなければなりません。

4.2 Window インターフェースへの拡張

Window インターフェースは [HTML] で定義されています。

WebIDLpartial interface Window {
  Selection? getSelection();
};
getSelection() メソッド

このメソッドは、getSelection()thisWindowdocument 属性で呼び出し、その結果を返さなければなりません。

4.3 GlobalEventHandlers インターフェースへの拡張

GlobalEventHandlers インターフェースは [HTML] で定義されています。

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

この属性は、すべてのイベントハンドラIDL属性selectstart イベントに対して、すべての HTML 要素Document オブジェクト、および Window オブジェクトでサポートされるためのものです。

onselectionchange

この属性は、すべてのイベントハンドラIDL属性selectionchange イベントに対して、すべての HTML 要素Document オブジェクト、および Window オブジェクトでサポートされるためのものです。

5. DOM 変更への対応

ユーザーエージェントが データを置換 または 部分文字列CharacterData に対して行う場合、ユーザーエージェントは、その CharacterDataノードドキュメントselection に関連付けられた rangelive range として更新しなければなりません。

ユーザーエージェントが Text ノード を分割する場合、ユーザーエージェントは、 Textノードドキュメントselection に関連付けられた rangelive range として更新しなければなりません。

ユーザーエージェントが normalize() メソッドの手順を実行する場合、ユーザーエージェントは ノードドキュメントselection に関連付けられた rangelive range として更新しなければなりません。

ユーザーエージェントが ノードを削除 または 挿入 する場合、ユーザーエージェントは、その ノードノードドキュメントselection に関連付けられた rangelive range として更新しなければなりません。

6. ユーザー操作

ユーザーエージェントは、selectionアクティブドキュメントに関連付けられたもの)を ユーザーが変更できるようにすべきです。ユーザーが selection を何らかの方法で変更した場合、ユーザーエージェントは range開始終了 を適切に設定した新しい range を作成し、この selection にこの新しい range を関連付けなければなりません(既存の range を変更しないこと)、また、開始が終了より あるいは等しい場合は selectiondirectionforwards に、終了が開始より の場合は backwards に、開始と終了がプラットフォームの慣習により順序付けできない場合は directionless に設定しなければなりません。

ユーザーエージェントは、ユーザーによるいかなる操作(例:編集不可領域のクリック)に対しても、もともと empty でなかった selectionempty にしてはなりません。

バグ15470 を参照。IE9 と Opera Next 12.00 alpha は、ユーザーがどこかをクリックすることで範囲を null にリセットできるが、Firefox 12.0a1 と Chrome 17 dev はそうではない。私は Gecko/WebKit の挙動に従います。なぜなら getRangeAt(0) が例外を投げる可能性が減るためです。

6.1 selectstart イベント

ユーザーエージェントがユーザーの操作に応答して selection に新しい範囲 newRange を関連付ける直前、境界点のノード(newRange開始点に対応する)で、selectstart という名前のイベント(バブルし、キャンセル可能)を発火しなければなりません。これは selection が以前 empty であったか、または以前の範囲が collapsed だった場合に限ります。

イベントがキャンセルされた場合、ユーザーエージェントは selection を変更してはなりません。

ユーザーエージェントが selection を empty に設定する場合、イベントは発火しません。

6.2 selectionchange イベント

selection がその range との関連付けを解除した場合、新しい range に関連付けられた場合、または関連付けられている range の boundary point がユーザーやコンテンツスクリプトによって変異された場合、ユーザーエージェントは selectionchange イベントをスケジュール しなければなりません。

input または textarea 要素内でテキスト選択が提供され、その選択が範囲または direction のいずれかで変化したとき、ユーザーエージェントはその要素で selectionchange イベントをスケジュール しなければなりません。

6.2.1 selectionchange イベントのスケジューリング

ノード targetselectionchange イベントをスケジュールする ための手順は以下の通りです:

  1. もし targethas scheduled selectionchange event が true なら、これらのステップを中止します。
  2. ユーザーインタラクションタスクソースでタスクをキューに追加 し、 selectionchange イベントを発火 します。

6.2.2 selectionchange イベントの発火

ノード targetselectionchange イベントを発火する 手順は以下の通りです:

  1. targethas scheduled selectionchange event を false に設定します。
  2. もし target が要素なら、selectionchange という名前のイベント(バブルし、キャンセル不可)を target で発火します。
  3. それ以外で target がドキュメントなら、selectionchange という名前のイベント(バブルせず、キャンセル不可)を target で発火します。

7. 適合性

非規範的と記載されたセクションだけでなく、本仕様書中のすべての執筆ガイドライン、図、例、および注記は規範的ではありません。それ以外のすべては規範的です。

この仕様書は、含まれるインターフェースを実装する ユーザーエージェント という単一製品に適用される適合基準を定義します。

8. セキュリティとプライバシーに関する考慮事項

この標準には既知のセキュリティ上の考慮事項はありません。

支援技術のユーザー利用を開示することによる潜在的なプライバシーリスクを軽減するため、たとえばユーザーエージェント は、ドキュメントの selection をユーザーが変更した場合、通常は selectstartselectionchange イベントに関連付けられるマウスやキーボードイベントをエミュレートすることを選択することがあります。

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 Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[HTML]
HTML Standard. 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 Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
[url]
URL Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/
[WEBIDL]
Web IDL Standard. Edgar Chen; Timothy Gu. WHATWG. Living Standard. URL: https://webidl.spec.whatwg.org/