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.
|
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)
|
##### `cacheBust` (Boolean, default true)
|
||||||
|
|
||||||
When set to true,
|
When set to true,
|
||||||
|
|||||||
72
index.js
72
index.js
@@ -13,7 +13,6 @@ var defaultSwitches = require("./lib/switches")
|
|||||||
|
|
||||||
|
|
||||||
var Pjax = function(options) {
|
var Pjax = function(options) {
|
||||||
this.firstrun = true
|
|
||||||
this.state = {
|
this.state = {
|
||||||
numPendingSwitches: 0,
|
numPendingSwitches: 0,
|
||||||
href: null,
|
href: null,
|
||||||
@@ -35,6 +34,7 @@ var Pjax = function(options) {
|
|||||||
opt.title = st.state.title
|
opt.title = st.state.title
|
||||||
opt.history = false
|
opt.history = false
|
||||||
opt.requestOptions = {};
|
opt.requestOptions = {};
|
||||||
|
opt.scrollPos = st.state.scrollPos
|
||||||
if (st.state.uid < this.lastUid) {
|
if (st.state.uid < this.lastUid) {
|
||||||
opt.backward = true
|
opt.backward = true
|
||||||
}
|
}
|
||||||
@@ -160,9 +160,21 @@ Pjax.prototype = {
|
|||||||
return
|
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.
|
// Clear out any focused controls before inserting new page contents.
|
||||||
document.activeElement.blur()
|
document.activeElement.blur()
|
||||||
|
|
||||||
|
var oldHref = href
|
||||||
if (request.responseURL) {
|
if (request.responseURL) {
|
||||||
if (href !== request.responseURL) {
|
if (href !== request.responseURL) {
|
||||||
href = request.responseURL
|
href = request.responseURL
|
||||||
@@ -174,6 +186,17 @@ Pjax.prototype = {
|
|||||||
else if (request.getResponseHeader("X-XHR-Redirected-To")) {
|
else if (request.getResponseHeader("X-XHR-Redirected-To")) {
|
||||||
href = 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.href = href
|
||||||
this.state.options = clone(options)
|
this.state.options = clone(options)
|
||||||
|
|
||||||
@@ -218,13 +241,13 @@ Pjax.prototype = {
|
|||||||
var state = this.state
|
var state = this.state
|
||||||
|
|
||||||
if (state.options.history) {
|
if (state.options.history) {
|
||||||
if (this.firstrun) {
|
if (!window.history.state) {
|
||||||
this.lastUid = this.maxUid = newUid()
|
this.lastUid = this.maxUid = newUid()
|
||||||
this.firstrun = false
|
|
||||||
window.history.replaceState({
|
window.history.replaceState({
|
||||||
url: window.location.href,
|
url: window.location.href,
|
||||||
title: document.title,
|
title: document.title,
|
||||||
uid: this.maxUid
|
uid: this.maxUid,
|
||||||
|
scrollPos: [0, 0]
|
||||||
},
|
},
|
||||||
document.title)
|
document.title)
|
||||||
}
|
}
|
||||||
@@ -235,7 +258,8 @@ Pjax.prototype = {
|
|||||||
window.history.pushState({
|
window.history.pushState({
|
||||||
url: state.href,
|
url: state.href,
|
||||||
title: state.options.title,
|
title: state.options.title,
|
||||||
uid: this.maxUid
|
uid: this.maxUid,
|
||||||
|
scrollPos: [0, 0]
|
||||||
},
|
},
|
||||||
state.options.title,
|
state.options.title,
|
||||||
state.href)
|
state.href)
|
||||||
@@ -250,15 +274,41 @@ Pjax.prototype = {
|
|||||||
|
|
||||||
state.options.analytics()
|
state.options.analytics()
|
||||||
|
|
||||||
// Scroll page to top on new page load
|
if (state.options.history) {
|
||||||
if (state.options.scrollTo !== false) {
|
// First parse url and check for hash to override scroll
|
||||||
if (state.options.scrollTo.length > 1) {
|
var a = document.createElement("a")
|
||||||
window.scrollTo(state.options.scrollTo[0], state.options.scrollTo[1])
|
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 {
|
else if (state.options.scrollTo !== false) {
|
||||||
window.scrollTo(0, state.options.scrollTo)
|
// 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 = {
|
this.state = {
|
||||||
numPendingSwitches: 0,
|
numPendingSwitches: 0,
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ module.exports = function(options) {
|
|||||||
this.options.cacheBust = (typeof this.options.cacheBust === "undefined") ? true : this.options.cacheBust
|
this.options.cacheBust = (typeof this.options.cacheBust === "undefined") ? true : this.options.cacheBust
|
||||||
this.options.debug = this.options.debug || false
|
this.options.debug = this.options.debug || false
|
||||||
this.options.timeout = this.options.timeout || 0
|
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
|
// we can’t replace body.outerHTML or head.outerHTML
|
||||||
// it create a bug where new body or new head are created in the dom
|
// 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.scrollTo, 0);
|
||||||
t.deepEqual(body1.options.cacheBust, true);
|
t.deepEqual(body1.options.cacheBust, true);
|
||||||
t.deepEqual(body1.options.debug, false);
|
t.deepEqual(body1.options.debug, false);
|
||||||
|
t.deepEqual(body1.options.scrollRestoration, true)
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user