Merge pull request #111 from MoOx/fix/scroll
Enhance scrolling behavior - Save scroll position with history - Scroll to element position when URL contains a hash - Add scrollRestoration option
This commit was merged in pull request #111.
This commit is contained in:
@@ -377,6 +377,10 @@ It's called every time a page is switched, even for history buttons.
|
||||
|
||||
Value (in px) to scrollTo when a page is switched.
|
||||
|
||||
##### `scrollRestoration` (Boolean, default true)
|
||||
|
||||
When set to true, attempt to restore the scroll position when navigating backwards or forwards.
|
||||
|
||||
##### `cacheBust` (Boolean, default true)
|
||||
|
||||
When set to true,
|
||||
|
||||
72
index.js
72
index.js
@@ -13,7 +13,6 @@ var defaultSwitches = require("./lib/switches")
|
||||
|
||||
|
||||
var Pjax = function(options) {
|
||||
this.firstrun = true
|
||||
this.state = {
|
||||
numPendingSwitches: 0,
|
||||
href: null,
|
||||
@@ -35,6 +34,7 @@ var Pjax = function(options) {
|
||||
opt.title = st.state.title
|
||||
opt.history = false
|
||||
opt.requestOptions = {};
|
||||
opt.scrollPos = st.state.scrollPos
|
||||
if (st.state.uid < this.lastUid) {
|
||||
opt.backward = true
|
||||
}
|
||||
@@ -160,9 +160,21 @@ Pjax.prototype = {
|
||||
return
|
||||
}
|
||||
|
||||
// push scroll position to history
|
||||
var currentState = window.history.state || {}
|
||||
window.history.replaceState({
|
||||
url: currentState.url || window.location.href,
|
||||
title: currentState.title || document.title,
|
||||
uid: currentState.uid || newUid(),
|
||||
scrollPos: [document.documentElement.scrollLeft || document.body.scrollLeft,
|
||||
document.documentElement.scrollTop || document.body.scrollTop]
|
||||
},
|
||||
document.title, window.location)
|
||||
|
||||
// Clear out any focused controls before inserting new page contents.
|
||||
document.activeElement.blur()
|
||||
|
||||
var oldHref = href
|
||||
if (request.responseURL) {
|
||||
if (href !== request.responseURL) {
|
||||
href = request.responseURL
|
||||
@@ -174,6 +186,17 @@ Pjax.prototype = {
|
||||
else if (request.getResponseHeader("X-XHR-Redirected-To")) {
|
||||
href = request.getResponseHeader("X-XHR-Redirected-To")
|
||||
}
|
||||
|
||||
// Add back the hash if it was removed
|
||||
var a = document.createElement("a")
|
||||
a.href = oldHref
|
||||
var oldHash = a.hash
|
||||
a.href = href
|
||||
if (oldHash && !a.hash) {
|
||||
a.hash = oldHash
|
||||
href = a.href
|
||||
}
|
||||
|
||||
this.state.href = href
|
||||
this.state.options = clone(options)
|
||||
|
||||
@@ -218,13 +241,13 @@ Pjax.prototype = {
|
||||
var state = this.state
|
||||
|
||||
if (state.options.history) {
|
||||
if (this.firstrun) {
|
||||
if (!window.history.state) {
|
||||
this.lastUid = this.maxUid = newUid()
|
||||
this.firstrun = false
|
||||
window.history.replaceState({
|
||||
url: window.location.href,
|
||||
title: document.title,
|
||||
uid: this.maxUid
|
||||
uid: this.maxUid,
|
||||
scrollPos: [0, 0]
|
||||
},
|
||||
document.title)
|
||||
}
|
||||
@@ -235,7 +258,8 @@ Pjax.prototype = {
|
||||
window.history.pushState({
|
||||
url: state.href,
|
||||
title: state.options.title,
|
||||
uid: this.maxUid
|
||||
uid: this.maxUid,
|
||||
scrollPos: [0, 0]
|
||||
},
|
||||
state.options.title,
|
||||
state.href)
|
||||
@@ -250,15 +274,41 @@ Pjax.prototype = {
|
||||
|
||||
state.options.analytics()
|
||||
|
||||
// Scroll page to top on new page load
|
||||
if (state.options.scrollTo !== false) {
|
||||
if (state.options.scrollTo.length > 1) {
|
||||
window.scrollTo(state.options.scrollTo[0], state.options.scrollTo[1])
|
||||
if (state.options.history) {
|
||||
// First parse url and check for hash to override scroll
|
||||
var a = document.createElement("a")
|
||||
a.href = this.state.href
|
||||
if (a.hash) {
|
||||
var name = a.hash.slice(1)
|
||||
name = decodeURIComponent(name)
|
||||
|
||||
var curtop = 0
|
||||
var target = document.getElementById(name) || document.getElementsByName(name)[0]
|
||||
if (target) {
|
||||
// http://stackoverflow.com/questions/8111094/cross-browser-javascript-function-to-find-actual-position-of-an-element-in-page
|
||||
if (target.offsetParent) {
|
||||
do {
|
||||
curtop += target.offsetTop
|
||||
|
||||
target = target.offsetParent
|
||||
} while (target)
|
||||
}
|
||||
}
|
||||
window.scrollTo(0, curtop);
|
||||
}
|
||||
else {
|
||||
window.scrollTo(0, state.options.scrollTo)
|
||||
else if (state.options.scrollTo !== false) {
|
||||
// Scroll page to top on new page load
|
||||
if (state.options.scrollTo.length > 1) {
|
||||
window.scrollTo(state.options.scrollTo[0], state.options.scrollTo[1])
|
||||
}
|
||||
else {
|
||||
window.scrollTo(0, state.options.scrollTo)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (state.options.scrollRestoration && state.options.scrollPos) {
|
||||
window.scrollTo(state.options.scrollPos[0], state.options.scrollPos[1])
|
||||
}
|
||||
|
||||
this.state = {
|
||||
numPendingSwitches: 0,
|
||||
|
||||
@@ -24,6 +24,7 @@ module.exports = function(options) {
|
||||
this.options.cacheBust = (typeof this.options.cacheBust === "undefined") ? true : this.options.cacheBust
|
||||
this.options.debug = this.options.debug || false
|
||||
this.options.timeout = this.options.timeout || 0
|
||||
this.options.scrollRestoration = (typeof this.options.scrollRestoration !== "undefined") ? this.options.scrollRestoration : true
|
||||
|
||||
// we can’t replace body.outerHTML or head.outerHTML
|
||||
// it create a bug where new body or new head are created in the dom
|
||||
|
||||
@@ -53,6 +53,7 @@ tape("test parse initalization options function", function(t) {
|
||||
t.deepEqual(body1.options.scrollTo, 0);
|
||||
t.deepEqual(body1.options.cacheBust, true);
|
||||
t.deepEqual(body1.options.debug, false);
|
||||
t.deepEqual(body1.options.scrollRestoration, true)
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user