Skip to content
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions dom.bs
Original file line number Diff line number Diff line change
Expand Up @@ -9892,6 +9892,126 @@ and {{Range/getBoundingClientRect()}} methods are defined in other specification
[[CSSOM-VIEW]]


<h3 id=interface-formcontrolrange>Interface {{FormControlRange}}</h3>

<pre class=idl>
[Exposed=Window]
interface FormControlRange : AbstractRange {
constructor();

undefined setFormControlRange((HTMLInputElement or HTMLTextAreaElement) element,
Comment thread
stephanieyzhang marked this conversation as resolved.
Outdated
unsigned long startOffset,
unsigned long endOffset);

DOMRectList getClientRects();
DOMRect getBoundingClientRect();
stringifier;
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why OpaqueRange offsets are readonly? Or there isn't any method to update them?

Copy link
Copy Markdown
Author

@stephanieyzhang stephanieyzhang Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The offsets are readonly since they're inherited from AbstractRange. Currently the HTML PR defines createValueRange(start, end) on the element for creation. We haven't yet added an API for updating, so that's an open question. Some options could be an element-side API (e.g. updateValueRange(range, start, end)) to keep OpaqueRange generic, or setters directly on OpaqueRange.

Would appreciate your thoughts @annevk @smaug----

Comment thread
stephanieyzhang marked this conversation as resolved.
</pre>

<p>Objects implementing the {{FormControlRange}} interface are known as
<dfn export id=concept-live-form-control-range>live FormControlRanges</dfn>.</p>
Comment thread
stephanieyzhang marked this conversation as resolved.
Outdated

<dl class=domintro>
<dt><code><var ignore>formControlRange</var> = new
<a constructor lt="FormControlRange()">FormControlRange()</a></code>
<dd>Returns a new <a>live FormControlRange</a> that tracks text offsets in a text control’s
Comment thread
stephanieyzhang marked this conversation as resolved.
Outdated
value as it changes.</dd>

<dt><code><var ignore>formControlRange</var> .
{{FormControlRange/setFormControlRange()}} (<var ignore>element</var>,
<var ignore>startOffset</var>, <var ignore>endOffset</var>)</code>
<dd>Sets the endpoints to <code>[start, end)</code> within <var>element</var>’s
Comment thread
stephanieyzhang marked this conversation as resolved.
Outdated
<i>value string</i>. Throws {{NotSupportedError}} for unsupported elements and
{{IndexSizeError}} for out-of-bounds offsets.</dd>
</dl>

<p>A {{FormControlRange}} is a range whose <a>boundary points</a> are defined in the
host text control’s <i>value string</i> rather than in the <a>node tree</a>. Its
<a for=range>start node</a> and <a for=range>end node</a> are always the host
<code>&lt;input&gt;</code> or <code>&lt;textarea&gt;</code>, and its offsets are indices into that
string.</p>

<p>A {{FormControlRange}} has associated state:</p>
<ul>
<li><dfn export for=FormControlRange id=formcontrolrange-control>control</dfn>
(null or an {{HTMLInputElement}}/{{HTMLTextAreaElement}})</li>
<li><dfn export for=FormControlRange id=formcontrolrange-start>start offset</dfn>
(a non-negative integer)</li>
<li><dfn export for=FormControlRange id=formcontrolrange-end>end offset</dfn>
(a non-negative integer)</li>
</ul>

<p>The {{AbstractRange/startContainer}} and {{AbstractRange/endContainer}} getters of a
Comment thread
stephanieyzhang marked this conversation as resolved.
Outdated
{{FormControlRange}} return its <a for=FormControlRange>control</a>. The
{{AbstractRange/startOffset}} and {{AbstractRange/endOffset}} getters return its
<a for=FormControlRange>start offset</a> and <a for=FormControlRange>end offset</a>.
{{AbstractRange/collapsed}} is true if and only if the two offsets are equal.</p>

<p>An {{Element}} <var>el</var> supports form control ranges if it is an {{HTMLTextAreaElement}},
Comment thread
stephanieyzhang marked this conversation as resolved.
Outdated
or an {{HTMLInputElement}} whose type
<a href="https://html.spec.whatwg.org/multipage/input.html#do-not-apply">supports the selection APIs</a>:
"<code>text</code>", "<code>search</code>", "<code>tel</code>", "<code>url</code>", or
"<code>password</code>".</p>

<p>For a supported host element <var>el</var>, its <i>value string</i> is the same string exposed by
Comment thread
stephanieyzhang marked this conversation as resolved.
Outdated
its IDL attribute {{HTMLTextAreaElement/value}}/{{HTMLInputElement/value}}. Offsets for
{{FormControlRange}} are indices into this string in the inclusive range
[0, <code>value.length</code>], matching
{{HTMLTextAreaElement/selectionStart}}/{{HTMLTextAreaElement/selectionEnd}} and
{{HTMLInputElement/selectionStart}}/{{HTMLInputElement/selectionEnd}} units.</p>

<p>The <dfn constructor for=FormControlRange lt="FormControlRange()">
Comment thread
stephanieyzhang marked this conversation as resolved.
Outdated
<code>new FormControlRange()</code></dfn> constructor steps are to set <a>this</a>’s
<a for=FormControlRange>control</a> to null and its
<a for=FormControlRange>start offset</a> and <a for=FormControlRange>end offset</a> to 0.</p>

<p>The <dfn method for=FormControlRange>
<code>setFormControlRange(<var>element</var>, <var>start</var>, <var>end</var>)</code></dfn>
method steps are:</p>

<ol>
<li>If <var>element</var> does not support form control ranges, then <a>throw</a> a
Comment thread
stephanieyzhang marked this conversation as resolved.
Outdated
"{{NotSupportedError!!exception}}" {{DOMException}}.</li>
<li>Let <var>len</var> be the length of <var>element</var>’s <i>value string</i>.</li>
<li>If <var>start</var> &gt; <var>len</var> or <var>end</var> &gt; <var>len</var>, then
<a>throw</a> an "{{IndexSizeError!!exception}}" {{DOMException}}.</li>
<li>If <var>start</var> &gt; <var>end</var>, then set <var>end</var> to <var>start</var>.</li>
<li>Set <a for=FormControlRange>control</a> to <var>element</var>,
Comment thread
stephanieyzhang marked this conversation as resolved.
Outdated
<a for=FormControlRange>start offset</a> to <var>start</var>, and
Comment thread
stephanieyzhang marked this conversation as resolved.
Outdated
<a for=FormControlRange>end offset</a> to <var>end</var>.</li>
Comment thread
stephanieyzhang marked this conversation as resolved.
Outdated
</ol>

<p>A {{FormControlRange}} is <em>live</em>: when the control’s value string changes, the range’s
Comment thread
stephanieyzhang marked this conversation as resolved.
Outdated
{{AbstractRange/startOffset}} and {{AbstractRange/endOffset}} are updated automatically
to preserve the same logical content. These behaviors mirror {{Range}} boundary adjustments
in the DOM, but are applied to the UTF-16 code units of a form control’s value.</p>

<ul>
Comment thread
stephanieyzhang marked this conversation as resolved.
<li>Edits before the range: Offsets shift by the net length change.</li>
<li>Edits after the range: Offsets remain unchanged.</li>
<li>Edits overlapping the range: If a boundary falls inside text that was removed,
move it to the start of the change. If the edit also inserted new text, remap the boundary
into the inserted span at the closest corresponding offset, not exceeding its end.</li>
<li>Insertion at the start boundary: A non-{{AbstractRange/collapsed}} range expands
to include the new text. A collapsed range (caret) moves after the insertion.</li>
<li>Insertion at the end boundary: A non-collapsed range does not expand to include
the new text. A collapsed range moves after the insertion.</li>
<li>Clamping and collapse: Offsets are clamped to the current value length. If the
{{AbstractRange/startOffset}} would exceed the {{AbstractRange/endOffset}}, set the end to the
start.</li>
</ul>

<p>The <dfn export for=FormControlRange id=dom-formcontrolrange-stringifier>stringification behavior</dfn> must run these steps:</p>

<ol>
<li><p>If <a for=FormControlRange>control</a> is null, then return the empty string.</p>
Comment thread
stephanieyzhang marked this conversation as resolved.
Outdated
<li><p>Let <var>value</var> be <a for=FormControlRange>control</a>'s <i>value string</i>.</p>
Comment thread
stephanieyzhang marked this conversation as resolved.
Outdated
<li><p>Let <var>start</var> be <a for=FormControlRange>start offset</a>, and let <var>end</var> be min(<a for=FormControlRange>end offset</a>, <var>value</var>.<code>length</code>).</p>
Comment thread
stephanieyzhang marked this conversation as resolved.
Outdated
Comment thread
stephanieyzhang marked this conversation as resolved.
Outdated
<li><p>If <var>start</var> ≥ <var>end</var>, then return the empty string.</p>
<li><p>Return the substring of <var>value</var> from <var>start</var> to <var>end</var>.</p>
</ol>


<h2 id="traversal">Traversal</h2>

Expand Down