Reputation: 737
I am trying to store the state of a page in the hash. This works in IE and FF but in Chrome it does not seem to do anything
$(document).ready(function()
{
window.onbeforeunload = savePageState;
});
function savePageState()
{
var currentTab = _tabbing.getCurrentTab();
var mapState = _mapAdapter.getMapState();
window.location.hash =
'reload=' + currentTab +
'&mapType=' + mapState.MapType.getName() +
'&lat=' + mapState.Latitude +
'&long=' + mapState.Longitude +
'&zoom=' + mapState.ZoomLevel;
return;
}
Is there a quirk in Chrome that prevents me from updating the hash? Is there a better way to go about saving the pages state? Its only for the back button that it needs to be saved.
Upvotes: 3
Views: 2573
Reputation: 737
While BBQ was nice, it did not entirely solve my problem. For it to work in Chrome / Safari, you need to update the hash before the onbeforeunload event. Part of the requirement however made it so that was the only real time that I could save the state of the page.
I came up with a solution, using both of the other answers here, using pushState and BBQ. I thought I would post it incase anyone else has the same issue I did.
function BackButtonState(saveStateCallback, pageLoadCallback)
{
var executePopStateCounter = null;
var myData = {};
var browserCanPushState = history.pushState ? true : false;
window.onbeforeunload = saveStateCallback;
if (browserCanPushState)
{
//The version of safari this was tested on (5.0.3) uses an outdated version of
//Webkit that has a bug where popstate is not called on the first page load.
//This is a hacky work around until the problem is fixed.
var agt = navigator.userAgent.toLowerCase();
if (agt.indexOf("safari") != -1)
{
executePopStateCounter = setTimeout(pageLoadCallback, 500);
};
window.onpopstate = function(popEvent)
{
clearTimeout(executePopStateCounter);
if (popEvent.state != null)
{
myData = popEvent.state;
}
pageLoadCallback();
}
}
else
{
$(document).ready(pageLoadCallback);
}
this.savePageState = function(state)
{
if (browserCanPushState)
{
history.pushState(state, 'BackButtonState');
}
else
{
$.bbq.pushState(state);
}
}
this.getState = function(item)
{
if (browserCanPushState)
{
return myData[item];
}
else
{
return $.bbq.getState(item);
}
}
this.deserializeSortList = function(sortArrays)
{
var sortList = [];
$.each(sortArrays, function(index, pair)
{
sortList.push([parseInt(pair[0]), parseInt(pair[1])]);
});
return sortList;
}
}
To use this, you do something like:
function saveState()
{
var myData = { bananas: 'are tasty' };
_backButton.saveState(myData);
}
function pageSetup()
{
//Do normal $(document).ready() stuff here
var myOpinionOnFruit = _backButton.getState('bananas');
}
var _backButton = new BackButtonState(saveState, pageSetup);
This is not guarenteed to be bug free, and I am unhappy with the hack I had to do for Safari. I just wanted to post this before I forgot.
Upvotes: 1
Reputation: 144912
I'd recomend that you use the jQuery BBQ plugin, which manages the hash for you.
$.bbq.pushState({
reload: currentTab,
mapType: mapState.MapType.getName(),
lat: mapState.Latitude,
long: mapState.Longitude,
zoom: mapState.ZoomLevel
});
BBQ handles merging the hash, so it will not overwrite other parameters. For example, #fun=yes
becomes #fun=yes&reload=tab&...
Next, you can listen for changes to the hash:
$(window).bind('hashchange', function(e) {
var params = e.getState();
doStuff(params.lat, params.long);
});
Upvotes: 3