Bug 1897956 - Text Fragments: Set text fragment as :target. r=farre,dom-core
This patch makes some adjustments to follow the spec more strictly by separating highlighting a text fragment (ie. adding the ranges to a `eTargetText` Selection) from scrolling to it. Scrolling to the text fragment now follows the steps given in [0] more closely, in particular now the closest common ancestor of the target range is being used as `:target` element. This change also sets the focus to the start of the first text fragment, as indicated by the spec. This resets the normal selection on the page. The wpt test in /css/css-pseudo/target-text-005.html is based on the idea of having a same-doc text fragment navigation with a selection. This test fails with this patch applied, because the selection is reset. It is currently unclear what behavior is correct here, thus the test is kept for now. [0]: https://wicg.github.io/scroll-to-text-fragment/#invoking-text-directives Differential Revision: https://phabricator.services.mozilla.com/D211025
This commit is contained in:
@@ -10736,11 +10736,12 @@ nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
|
||||
// `Document::ScrollToRef()` is (presumably) the second "async" call mentioned
|
||||
// in sec. 7.4.2.3.3 in the HTML spec, "Fragment navigations":
|
||||
// https://html.spec.whatwg.org/#scroll-to-fragid:~:text=This%20algorithm%20will%20be%20called%20twice
|
||||
const bool hasScrolledToTextFragment =
|
||||
presShell->HighlightAndGoToTextFragment(scroll);
|
||||
if (hasScrolledToTextFragment) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const RefPtr fragmentDirective = GetDocument()->FragmentDirective();
|
||||
const nsTArray<RefPtr<nsRange>> textDirectives =
|
||||
fragmentDirective->FindTextFragmentsInDocument();
|
||||
const bool hasTextDirectives = !textDirectives.IsEmpty();
|
||||
fragmentDirective->HighlightTextDirectives(textDirectives);
|
||||
|
||||
// If we have no new anchor, we do not want to scroll, unless there is a
|
||||
// current anchor and we are doing a history load. So return if we have no
|
||||
@@ -10753,12 +10754,12 @@ nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
|
||||
// Both the new and current URIs refer to the same page. We can now
|
||||
// browse to the hash stored in the new URI.
|
||||
|
||||
if (aNewHash.IsEmpty()) {
|
||||
if (aNewHash.IsEmpty() && !hasTextDirectives) {
|
||||
// 2. If fragment is the empty string, then return the special value top of
|
||||
// the document.
|
||||
//
|
||||
// Tell the shell it's at an anchor without scrolling.
|
||||
presShell->GoToAnchor(u""_ns, false);
|
||||
presShell->GoToAnchor(u""_ns, nullptr, false);
|
||||
|
||||
if (scroll) {
|
||||
// Scroll to the top of the page. Ignore the return value; failure to
|
||||
@@ -10773,7 +10774,10 @@ nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
|
||||
// 3. Let potentialIndicatedElement be the result of finding a potential
|
||||
// indicated element given document and fragment.
|
||||
NS_ConvertUTF8toUTF16 uStr(aNewHash);
|
||||
auto rv = presShell->GoToAnchor(uStr, scroll, ScrollFlags::ScrollSmoothAuto);
|
||||
RefPtr<nsRange> range =
|
||||
!textDirectives.IsEmpty() ? textDirectives[0] : nullptr;
|
||||
auto rv =
|
||||
presShell->GoToAnchor(uStr, range, scroll, ScrollFlags::ScrollSmoothAuto);
|
||||
|
||||
// 4. If potentialIndicatedElement is not null, then return
|
||||
// potentialIndicatedElement.
|
||||
@@ -10794,7 +10798,7 @@ nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
|
||||
if (fragmentBytes.IsEmpty()) {
|
||||
// When aNewHash contains "%00", the unescaped string may be empty, and
|
||||
// GoToAnchor asserts if we ask it to scroll to an empty ref.
|
||||
presShell->GoToAnchor(u""_ns, false);
|
||||
presShell->GoToAnchor(u""_ns, nullptr, false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -10811,7 +10815,8 @@ nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
|
||||
// there is no such anchor in the document, which is actually a success
|
||||
// condition for us (we want to update the session history with the new URI no
|
||||
// matter whether we actually scrolled somewhere).
|
||||
presShell->GoToAnchor(decodedFragment, scroll, ScrollFlags::ScrollSmoothAuto);
|
||||
presShell->GoToAnchor(decodedFragment, nullptr, scroll,
|
||||
ScrollFlags::ScrollSmoothAuto);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user