So I'm using the HTML5 history management for adding the ability to navigate back and forward within a website with AJAX loaded subcontent.
Now I would like to store javascript functions within the state object, to callback at the state popping. More or less like the following code:
$(window).bind("popstate", function(event) {
var state = event.originalEvent.state;
if (!state) {
return;
}
state.callback(state.argument);
}
function beforeLoad() {
var resourceId = "xyz";
var func;
if (case1) {
func = switchPageToMode1;
} else { // case 2
func = swithPageToMode2;
}
func(resourceId); // run the function
window.history.pushState({ callback: func, resourceId: resourceId }, "newTitle", "newURL"); // and push it to history
}
function switchPageToMode1(resourceId) {
alterPageLayoutSomeWay();
loadResource(resourceId);
}
function swithPageToMode2(resourceId) {
alterPageLayoutSomeOtherWay();
loadResource(resourceId);
}
function loadResource(resourceId) {
...
}
All right. So what I'm trying to do is storing a reference to a javascript function. But when pushing the state (the actual window.history.pushState call) the browser files a complaint, namely Error: "DATA_CLONE_ERR: DOM Exception 25"
Anybody knows what I'm doing wrong? Is it at all possible to store function calls within the state?
No, it's not possible, not directly anyway. According to MDC the "state object," i.e. the first argument to pushState
, "can be anything that can be serialized." Unfortunately, you can't serialize a function. The WHATWG spec says basically the same thing but in many more words, the gist of which is that functions are explicitly disallowed in the state object.
The solution would be to store either a string you can eval
or the name of the function in the state object, e.g.:
$(window).bind("popstate", function(event) {
var state = event.originalEvent.state;
if ( !state ) { return; }
window[ state.callback ]( state.argument ); // <-- look here
}
function beforeLoad() {
var resourceId = "xyz",
func
;
if ( case1 ) {
func = "switchPageToMode1"; // <-- string, not function
} else {
// case 2
func = "swithPageToMode2";
}
window[ func ]( resourceId ); // <-- same here
window.history.pushState(
{ callback : func,
argument : resourceId
},
"newTitle", "newURL"
);
}
Of course that's assuming switchPageToMode1
and -2
are in the global context (i.e. window
), which isn't the best practice. If not they'll have to be accessible somehow from the global context, e.g. [window.]MyAppGlobal.switchPageToMode1
, in which case you would call MyAppGlobal[ func ]( argument )
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With