add support for route state #1480

This commit is contained in:
Leo Horie 2016-12-17 21:50:04 -05:00
parent 75e83ea565
commit de07a54881
10 changed files with 367 additions and 196 deletions

View file

@ -13,7 +13,7 @@ module.exports = function(options) {
var search = ""
var hash = ""
var past = [], future = []
var past = [{url: getURL(), isNew: true, state: null, title: null}], future = []
function getURL() {
if (protocol === "file:") return protocol + "//" + pathname + search + hash
@ -42,7 +42,7 @@ module.exports = function(options) {
if (typeof $window.onhashchange === "function") $window.onhashchange({type: "hashchange"})
}
function popstate() {
if (typeof $window.onpopstate === "function") $window.onpopstate({type: "popstate"})
if (typeof $window.onpopstate === "function") $window.onpopstate({type: "popstate", state: $window.history.state})
}
function unload() {
if (typeof $window.onunload === "function") $window.onunload({type: "unload"})
@ -135,20 +135,22 @@ module.exports = function(options) {
},
}
$window.history = {
pushState: function(data, title, url) {
past.push({url: getURL(), isNew: false})
pushState: function(state, title, url) {
past.push({url: getURL(), isNew: false, state: state, title: title})
future = []
setURL(url)
},
replaceState: function(data, title, url) {
future = []
replaceState: function(state, title, url) {
var entry = past[past.length - 1]
entry.state = state
entry.title = title
setURL(url)
},
back: function() {
var entry = past.pop()
if (entry != null) {
if (past.length > 1) {
var entry = past.pop()
if (entry.isNew) unload()
future.push({url: getURL(), isNew: false})
future.push({url: getURL(), isNew: false, state: entry.state, title: entry.title})
setURL(entry.url)
if (!entry.isNew) popstate()
}
@ -157,11 +159,14 @@ module.exports = function(options) {
var entry = future.pop()
if (entry != null) {
if (entry.isNew) unload()
past.push({url: getURL(), isNew: false})
past.push({url: getURL(), isNew: false, state: entry.state, title: entry.title})
setURL(entry.url)
if (!entry.isNew) popstate()
}
},
get state() {
return past.length === 0 ? null : past[past.length - 1].state
},
}
$window.onpopstate = null,
$window.onhashchange = null,

View file

@ -417,6 +417,71 @@ o.spec("pushStateMock", function() {
$window.history.pushState(null, null, "b")
$window.history.back()
})
o("replaceState does not break forward history", function() {
$window.onpopstate = o.spy()
$window.history.pushState(null, null, "b")
$window.history.back()
o($window.onpopstate.callCount).equals(1)
o($window.location.href).equals("http://localhost/")
$window.history.replaceState(null, null, "a")
o($window.location.href).equals("http://localhost/a")
$window.history.forward()
o($window.onpopstate.callCount).equals(2)
o($window.location.href).equals("http://localhost/b")
})
o("pushstate retains state", function() {
$window.onpopstate = o.spy()
$window.history.pushState({a: 1}, null, "#a")
$window.history.pushState({b: 2}, null, "#b")
o($window.onpopstate.callCount).equals(0)
$window.history.back()
o($window.onpopstate.callCount).equals(1)
o($window.onpopstate.args[0].type).equals("popstate")
o($window.onpopstate.args[0].state).deepEquals({a: 1})
$window.history.back()
o($window.onpopstate.callCount).equals(2)
o($window.onpopstate.args[0].type).equals("popstate")
o($window.onpopstate.args[0].state).equals(null)
$window.history.forward()
o($window.onpopstate.callCount).equals(3)
o($window.onpopstate.args[0].type).equals("popstate")
o($window.onpopstate.args[0].state).deepEquals({a: 1})
$window.history.forward()
o($window.onpopstate.callCount).equals(4)
o($window.onpopstate.args[0].type).equals("popstate")
o($window.onpopstate.args[0].state).deepEquals({b: 2})
})
o("replacestate replaces state", function() {
$window.onpopstate = o.spy(pop)
$window.history.replaceState({a: 1}, null, "a")
o($window.history.state).deepEquals({a: 1})
$window.history.pushState(null, null, "a")
$window.history.back()
function pop(e) {
o(e.state).deepEquals({a: 1})
o($window.history.state).deepEquals({a: 1})
}
})
})
o.spec("onhashchance", function() {
o("onhashchange triggers on location.href change", function() {