Skip to content

Commit

Permalink
[css-highlight-api-1] Add highlightsFromPoint() to CSS.highlights #7513
Browse files Browse the repository at this point in the history
… (#11507)

* add spec for highlightsFromPoint
  • Loading branch information
ffiori authored Jan 25, 2025
1 parent ef8d1f6 commit b394536
Showing 1 changed file with 105 additions and 2 deletions.
107 changes: 105 additions & 2 deletions css-highlight-api-1/Overview.bs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ spec:css-color-4; type:property; text:color
spec:css-pseudo-4; type:dfn; text:highlight overlay
spec:dom; type:dfn; text:range
spec:css-values-4; type:dfn; text:identifier
spec:dom; type:dfn; for:Element; text:shadow root
spec:dom; type:dfn; text:event
spec:css21; type:dfn; text:viewport
</pre>

<style>
Expand All @@ -73,7 +76,7 @@ Introduction</h2>
''::selection'',
''::inactive-selection'',
''::spelling-error'',
and '''::grammar-error'''.
and ''::grammar-error''.
This is useful in a variety of scenarios,
including editing frameworks that wish to implement their own selection,
find-on-page over virtualized documents,
Expand Down Expand Up @@ -233,7 +236,7 @@ Registering Custom Highlights</h3>
};

[Exposed=Window]
interface HighlightRegistry {
partial interface HighlightRegistry {
maplike<DOMString, Highlight>;
};
</xmp>
Expand Down Expand Up @@ -579,6 +582,103 @@ Range Updating and Invalidation</h3>
is not <a spec=dom for="StaticRange">valid</a>,
the user agent must ignore that [=range=].

<h2 id="interactions">
Interacting with Custom Highlights</h2>

The {{highlightsFromPoint}}(<var>x</var>, <var>y</var>, <var>options</var>) method allows developers to build scenarios
involving user interaction with [=custom highlights=]. The method returns a [=sequence=] containing the [=custom highlights=]
at a given <var>x</var>, <var>y</var> coordinate. The [=custom highlights=] are listed in this [=sequence=] in
descending [=priority=] order.
By default, [=custom highlights=] in a [=shadow tree=] are not returned, but the developer has the possibility to pass in
an optional <var>options</var> [=dictionary=] with a <var>shadowRoots</var> property containing a [=sequence=] of {{ShadowRoot}}
objects. [=custom highlights|Highlights=] contained within a [=shadow tree=] provided in this way will be returned.

<div class=example id=highlights-from-point-ex>
The following example shows a way to use {{highlightsFromPoint}} to interact with mouse click [=event|events=].

<xmp highlight=html>
<style>
:root::highlight(foo) {
background-color:yellow;
}
:root::highlight(bar) {
color:red;
}
</style>
<body>abc
<script>
document.addEventListener('click', (event) => {
const mouseX = event.clientX;
const mouseY = event.clientY;
console.log(CSS.highlights.highlightsFromPoint(mouseX, mouseY));
});

let textNode = document.body.firstChild;
let r1 = new Range();
r1.setStart(textNode, 0);
r1.setEnd(textNode, 2);
let r2 = new Range();
r2.setStart(textNode, 1);
r2.setEnd(textNode, 2);

let h1 = new Highlight(r1);
let h2 = new Highlight(r2);
h1.priority = 1;
h2.priority = 2;

CSS.highlights.set("foo", h1);
CSS.highlights.set("bar", h2);
</script>
</xmp>

The code above will display the following styled text, note that "b" is affected by both [=custom highlight|highlights=]
<var>h1</var> and <var>h2</var>, whereas "a" is only affected by <var>h1</var>:

<div class=sample-out style="color:black">
<span style="background:yellow;">a</span><span style="background:yellow;color:red;">b</span><span>c</span>
</div>

In this example there's an [=event listener=] set on click [=event|events=] that logs the [=custom highlights=]
present at the point where the click was made.
The following [=sequence|sequences=] are some examples of what will be printed to console after a click:
* <code>[ <var>h1</var> ]</code>, if the user clicks on character "a".
* <code>[ <var>h2</var>, <var>h1</var> ]</code>, if the user clicks on character "b",
as <var>h2</var> has higher priority than <var>h1</var>.
* <code>[]</code>, if the user clicks on character "c".
</div>

The method {{highlightsFromPoint}} is defined as part of the {{HighlightRegistry}} interface as follows:

<pre class=idl>
partial interface HighlightRegistry {
sequence&lt;Highlight> highlightsFromPoint(float x, float y, optional <span>HighlightsFromPointOptions</span> options = {});
};

dictionary <dfn dictionary>HighlightsFromPointOptions</dfn> {
sequence&lt;ShadowRoot> <dfn dict-member for="HighlightsFromPointOptions">shadowRoots</dfn> = [];
};
</pre>

The <dfn method for="HighlightRegistry">highlightsFromPoint(<var>x</var>, <var>y</var>, <var>options</var>)</dfn>
method must return the result of running these steps:

1. If any of the following are true, return the empty [=sequence=]:
* <var>x</var> is negative
* <var>y</var> is negative
* <var>x</var> is greater than the <a>viewport</a> width excluding the size of a rendered scroll bar (if any)
* <var>y</var> is greater than the <a>viewport</a> height excluding the size of a rendered scroll bar (if any)
1. Otherwise, return a [=sequence=] of [=custom highlights=] given by ordering the highlights contained in this {{HighlightRegistry}} in descending order of [=priority=],
excluding the highlights without at least one [=range=] <var>range</var> that satisfies the following constraints:
1. The coordinates <var>x</var>,<var>y</var> fall inside at least one of the {{DOMRect}}s returned by calling {{Range/getClientRects()}} on <var>range</var>.

Note: The specifics of hit testing are out of scope of this
specification and therefore the exact details of
{{highlightsFromPoint()}} are therefore too. Hit testing
will hopefully be defined in a future revision of CSS or HTML.

1. The <var>range</var>'s {{commonAncestorContainer}} is not in a [=shadow tree=] or is in a [=shadow tree=] whose
[=shadow root=] is [=list/contains|contained by=] by <var>options</var>.<var>shadowRoots</var>.

<h2 id=events>
Event Handling</h2>

Expand Down Expand Up @@ -629,6 +729,9 @@ Changes since the <a href="https://www.w3.org/TR/2020/WD-css-highlight-api-1-202
In addition to various editorial improvements and minor tweaks,
the main changes are:

* Added a {{HighlightRegistry/highlightsFromPoint}} method to
{{HighlightRegistry}}.
(See <a href="https://github.com/w3c/csswg-drafts/pull/7513">Issue 7513</a>)
* Specified that highlight repainting has to be done asynchronously.
(See <a href="https://github.com/w3c/csswg-drafts/pull/6987">Issue 6987</a>)
* Clarify that UAs cannot specify paired default highlight colors for custom highlights.
Expand Down

0 comments on commit b394536

Please sign in to comment.