Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance scrolling behavior #111

Merged
merged 4 commits into from
Jan 23, 2018
Merged

Enhance scrolling behavior #111

merged 4 commits into from
Jan 23, 2018

Conversation

BehindTheMath
Copy link
Collaborator

@BehindTheMath BehindTheMath commented Jan 22, 2018

Save scroll position when navigating away from a page, and restore
it when navigating back to that page.

Fixes #30.
When the URL contains a hash, try to find the corresponding
element, and if found, scroll to its position.

Based on darylteo/pjax@4893a2a

Fixes #22.
Copy link
Owner

@MoOx MoOx left a comment

Choose a reason for hiding this comment

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

Wow, nice improvement!

index.js Outdated
window.history.replaceState({
url: window.location.href,
title: document.title,
uid: this.maxUid
uid: this.maxUid,
scrollPos: 0
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you need to reset scrollPos to be [0, 0] rather than just 0, so that you're always storing the same type of data against this key.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good point.

index.js Outdated
@@ -235,7 +246,8 @@ Pjax.prototype = {
window.history.pushState({
url: state.href,
title: state.options.title,
uid: this.maxUid
uid: this.maxUid,
scrollPos: 0
Copy link
Collaborator

Choose a reason for hiding this comment

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

This also should be [0, 0], per my other comment

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good point.

index.js Outdated
}
}
else {
window.scrollTo(state.options.scrollPos[0], state.options.scrollPos[1])
Copy link
Collaborator

Choose a reason for hiding this comment

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

This will only run if state.options.history is falsy, which I don't think is what you intended?

Perhaps something like

else if (state.options.scrollTo !== false) {
  // Update window scroll position
  if (Array.isArray(state.options.scrollTo)) {
    window.scrollTo(state.options.scrollTo[0], state.options.scrollTo[1])
  }
  else if (typeof state.options.scrollTo === "number") {
    window.scrollTo(0, state.options.scrollTo)
  }
  else {
    window.scrollTo(state.options.scrollPos[0], state.options.scrollPos[1])
  }
}

instead?

This would require the default value of this.options.scrollTo to change to true as well -- currently it's set to 0 if one is not provided by the user, meaning that the window will always be scrolled back to the top. If we didn't want to break backwards compatibility, then we could accept 'auto' as a value for the option to trigger scroll restoration, but it's probably a behavior that users would expect and prefer to happen -- what do you think?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, I believe my code is correct. options.history is true when we're navigating to a page, and false when the initiator was popstate. This is because you don't want to call pushState() when you're in middle of a popstate event.

So we only want to use the scroll position stored in history when we're responding to a popstate event, in which case options.history is false. Otherwise, when it's true, we want to either use the hash, or scrollTo.

See earlier in #46, where we decided the default when clicking a link should be to scroll to the top.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh dear, that's a comprehension fail on my part, sorry! You are correct.

One thing that would be good to change though is to only restore the scroll position on popstate if this.options.scrollTo is not false -- another thing from #46 was a decision to let developers to decide on what is the best UX for their app, so we should make sure that this scroll restoration can be opted out of, don't you think? This matches the current behaviour when switching.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

options.scrollTo is only documented as taking a number value. From the README:

scrollTo (Integer, default to 0)

I'm not even sure why the check for options.scrollTo !== false exists at all.

I think we should add a scrollRestoration option instead, similar to the HTML spec (see #40).

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, I wondered why it hadn't been documented.

Adding a scrollRestoration option sounds fine though.

@BehindTheMath
Copy link
Collaborator Author

@robinnorth Are we good to merge this?

Copy link
Collaborator

@robinnorth robinnorth left a comment

Choose a reason for hiding this comment

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

LGTM. Nice one!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants