Skip to content
This repository was archived by the owner on Jan 11, 2023. It is now read-only.

Add noscroll option to goto, document sapper-noscroll on links #1320

Merged
merged 9 commits into from
Aug 7, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions runtime/src/app/goto/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { history, select_target, navigate, cid } from '../app';

export default function goto(href: string, opts = { replaceState: false }) {
export default function goto(href: string, opts = { noscroll: false, replaceState: false }) {
const target = select_target(new URL(href, document.baseURI));

if (target) {
history[opts.replaceState ? 'replaceState' : 'pushState']({ id: cid }, '', href);
return navigate(target, null).then(() => {});
return navigate(target, null, opts.noscroll).then(() => {});
}

location.href = href;
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/app/start/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ function handle_click(event: MouseEvent) {

const target = select_target(url);
if (target) {
const noscroll = a.hasAttribute('sapper-noscroll');
const noscroll = a.hasAttribute('sapper:noscroll');
navigate(target, null, noscroll, url.hash);
event.preventDefault();
history.pushState({ id: cid }, '', url.href);
Expand Down
4 changes: 3 additions & 1 deletion site/content/docs/03-client-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ sapper.start({
### goto(href, options?)

* `href` — the page to go to
* `options` — can include a `replaceState` property, which determines whether to use `history.pushState` (the default) or `history.replaceState`. Not required
* `options` — not required
* `replaceState` (`boolean`, default `false`) — determines whether to use `history.pushState` (the default) or `history.replaceState`.
* `noscroll` (`boolean`, default `false`) — prevent scroll to top after navigation.

Programmatically navigates to the given `href`. If the destination is a Sapper route, Sapper will handle the navigation, otherwise the page will be reloaded with the new `href`. In other words, the behaviour is as though the user clicked on a link with this `href`.

Expand Down
12 changes: 12 additions & 0 deletions site/content/docs/08-link-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,15 @@ Adding a `rel=external` attribute to a link...
```

...will trigger a browser navigation when the link is clicked.

### sapper:noscroll

When navigating to internal links, Sapper will change the scroll position to 0,0 so that the user is at the very top left of the page. When a hash is defined, it will scroll to the element with a matching ID.

In certain cases, you may wish to disable this behaviour. Adding a `sapper:noscroll` attribute to a link...

```html
<a href='path' sapper:noscroll>Path</a>
```

...will prevent scrolling after the link is clicked.
20 changes: 20 additions & 0 deletions test/apps/scroll/src/routes/search-form.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script>
import { goto } from "@sapper/app";

function preserveScroll() {
goto("/a-third-tall-page", { noscroll: true });
}

function scroll() {
goto("/a-third-tall-page");
}
</script>

<h1>A search form</h1>

<div style="height: 9999px" />

<div id="search">
<button id="scroll" on:click={scroll}>Don't preserve scroll</button>
<button id="preserve" on:click={preserveScroll}>Preserve scroll</button>
</div>
28 changes: 27 additions & 1 deletion test/apps/scroll/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,33 @@ describe('scroll', function() {
const secondScrollY = await r.page.evaluate(() => window.scrollY);

assert.equal(firstScrollY, secondScrollY);
});
});

it('scrolls to the top when navigating with goto', async () => {
await r.load(`/search-form#search`);
await r.sapper.start();

let initialScrollY = await r.page.evaluate(() => window.scrollY);
assert.ok(initialScrollY > 0, String(initialScrollY));

await r.page.click(`button#scroll`);

let scrollY = await r.page.evaluate(() => window.scrollY);
assert.ok(scrollY === 0, String(scrollY));
});

it('preserves scroll when noscroll: true is passed to goto', async () => {
await r.load(`/search-form#search`);
await r.sapper.start();

let initialScrollY = await r.page.evaluate(() => window.scrollY);
assert.ok(initialScrollY > 0, String(initialScrollY));

await r.page.click(`button#preserve`);

let scrollY = await r.page.evaluate(() => window.scrollY);
assert.ok(scrollY === initialScrollY, String(scrollY));
});

it('survives the tests with no server errors', () => {
assert.deepEqual(r.errors, []);
Expand Down