From ef92095a54fc9cc09ee08609d87ab27b1b4d11cc Mon Sep 17 00:00:00 2001 From: Sean Doyle Date: Thu, 25 Nov 2021 15:50:08 -0500 Subject: [PATCH] Treat same-page anchor Visit Closes https://github.com/hotwired/turbo/issues/400 Invoke `Visit.goToSamePageAnchor()` earlier in the `BrowserAdapter.visitStarted()` delegate method. If a `Visit` is to an anchor on the same page, invoke it at the same time a simulated request that's pre-populated from a `VisitResponse` instance in the hopes that the asynchronous Visit delegate callbacks won't be in competition with the same-page scrolling asynchrony. --- src/core/drive/visit.ts | 2 ++ src/core/native/browser_adapter.ts | 1 - src/tests/fixtures/visit.html | 6 ++++++ src/tests/functional/visit_tests.ts | 24 ++++++++++++++++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/core/drive/visit.ts b/src/core/drive/visit.ts index 9e900b89b..cc70d38fd 100644 --- a/src/core/drive/visit.ts +++ b/src/core/drive/visit.ts @@ -174,6 +174,8 @@ export class Visit implements FetchRequestDelegate { issueRequest() { if (this.hasPreloadedResponse()) { this.simulateRequest() + } else if (this.isSamePage) { + this.goToSamePageAnchor() } else if (this.shouldIssueRequest() && !this.request) { this.request = new FetchRequest(this, FetchMethod.get, this.location) this.request.perform() diff --git a/src/core/native/browser_adapter.ts b/src/core/native/browser_adapter.ts index d69a3e6f2..196a85a2d 100644 --- a/src/core/native/browser_adapter.ts +++ b/src/core/native/browser_adapter.ts @@ -24,7 +24,6 @@ export class BrowserAdapter implements Adapter { visit.loadCachedSnapshot() visit.issueRequest() visit.changeHistory() - visit.goToSamePageAnchor() } visitRequestStarted(visit: Visit) { diff --git a/src/tests/fixtures/visit.html b/src/tests/fixtures/visit.html index 08e0831ba..dc6e0fd54 100644 --- a/src/tests/fixtures/visit.html +++ b/src/tests/fixtures/visit.html @@ -5,6 +5,9 @@ Turbo +
@@ -12,6 +15,9 @@

Visit

Same-origin link

Same-origin link with ?key=value

Sample response

+

Same page link

+
+

Same page heading

diff --git a/src/tests/functional/visit_tests.ts b/src/tests/functional/visit_tests.ts index c80cccb75..5d0239300 100644 --- a/src/tests/functional/visit_tests.ts +++ b/src/tests/functional/visit_tests.ts @@ -120,6 +120,30 @@ export class VisitTests extends TurboDriveTestCase { this.assert.notOk(await this.hasSelector("some-cached-element")) } + async "can scroll to element after turbo:visit"() { + const id = "below-the-fold-heading" + await this.evaluate((id: string) => { + addEventListener("turbo:load", + () => document.getElementById(id)?.scrollIntoView(), + { once: true } + ) + }, id) + + this.assert(await this.isScrolledToTop, "starts unscrolled") + + await this.clickSelector("#same-page-link") + await this.nextEventNamed("turbo:load") + + this.assert(await this.isScrolledToSelector("#" + id), "scrolls after turbo:load") + + await this.clickSelector("#same-origin-link") + await this.nextEventNamed("turbo:load") + await this.goBack() + await this.nextEventNamed("turbo:load") + + this.assert(await this.isScrolledToSelector("#" + id), "scrolls after turbo:load") + } + async visitLocation(location: string) { this.remote.execute((location: string) => window.Turbo.visit(location), [location]) }