solving the browser Tab problem

Web Browser tabs and windows have been an issue for a long time now. They cause broken ViewMaps (used in @ViewScoped), FlashScope and lots other issues [1].

There is also a very ugly negative effect with using multiple browser tabs when using server side state saving in JSF: the last viewStates of a client is only stored per session and not per browser tab. Thus if a person clicks long enough in 1 browser tab (the default value is 20 for both Mojarra and MyFaces) then all your other open tabs will loose the view state. And this will cause a ViewExpiredException once you click around in one of those other browser tabs. This can only be solved if JSF natively supports multiple browser tabs and stores the view states per browser tab.

The problem is that providing a really working windowId handling is not exactly easy (as outlined in [1]).

Apache MyFaces CODI ClientSideWindowHandler

A solution which works perfectly fine on a technical level has been implemented by Jakob, Gerhard and me in Apache MyFaces CODI [2]. But it had the bad user effect that rendering the intermediate page (which checks for a valid site) and only then requests the real page did cause some ‘flickering’. It seems we have solved this problem now!

While I explained Dan Allen how we do the windowId handling in CODI currently, he came up with the idea of ‘taking a screenshot somehow and show it on the intermediate page’. One idea hit the other and today I tried to use html5 localStorage to store the head and body elements and dynamically apply them on the indermediate windowhandler.html page. Voila, works perfect so far. Of course, we need to test this with complex pages and pages which heavily uses javascript, but so far it works fine.

How it works

The site which contains a GET link needs to use some JavaScript which changes all <a href../> and add/delegate a
onclick="storeWindowTree(); return true;"

The storeWindowTree is pretty easy:

<script type="text/javascript">
// store the current body in the html5 localstorage
function storeWindowTree() {
localStorage.setItem(window.name, document.body.innerHTML);
}
</script>

So after we click on a link, we have the body of the current page in the html5 localStorage. (We should store the head too in the future).

On the windowhandler.html intermediate page we just do the following:


<script type="text/javascript" >
function getOldBody() {
var oldBody = null;
if (window.name.length != null) {
oldBody = localStorage.getItem(window.name);
}
return oldBody;
}

window.onload = function() {
var oldBody = getOldBody();

if (oldBody != null) {
document.body.innerHTML = oldBody;
localStorage.removeItem(window.name);
}…
do all the windowId stuff (works fine anyway)
window.location.reload();
}

easy, isn’t?

[1] http://myfaces.apache.org/orchestra/myfaces-orchestra-core/multiwindow.html
[2] https://cwiki.apache.org/confluence/display/EXTCDI/JSF+WindowHandler
// ]]>

Advertisements

About struberg
I'm an Apache Software Foundation member blogging about Java, µC, TheASF, OpenWebBeans, Maven, MyFaces, CODI, GIT, OpenJPA, TomEE, DeltaSpike, ...

One Response to solving the browser Tab problem

  1. I dugg some of you post as I cogitated they were invaluable very helpful

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: