There's lot's of things
that make me happy. In my professional life, it's getting stuff done,
helping other people or learning something new. Recently I learnt
something which was probably widely known but I'd managed to miss all
these years. I'm so inspired that I'm going to share it with you all.
A lot of transactional
websites crumble when you dare to do something as reckless as use the
back button or open more than one window on the site. The underlying
reason is that the developer is storing data relating to the
transaction – i.e. specific to a navigation event in a single
window - in the session – which is common to all the windows. A
very poor way to mitigate the problem is to break the browser
functionality by disabling the back button or interaction via a
second window. I must admit to having used this in the past to
mitigate the effects of problems elsewhere in the code (alright, if
you must know – I bastardized Brooke Bryan's back button detector,
and as for the new window....well the history length is zero)
But how
should I be solving the problem?
The obvious
solution is to embed all the half-baked ingredients of a transaction
in each html page sent to the browser and send the updated data model
back to the server on navigation. This can work surprisingly well as
long as the data on the browser is cleared down between sessions. But
with increasingly complex datasets, this becomes rather innefficient,
particularly on slow connections. Further there are times when we
want the transaction state to reflect the session state: consider a
shopping basket – if a user fills a shoppng basket then ends their
session we might want to retain the data about what they put in their
shopping basket – but we might also want to release any stock
reserved by the act of adding it to the basket. Often the situation
arises where we end up with (what should be) the same data held in
more than one place (browser and server). At some point the
representations of the truth will diverge – and at that point it
all goes rather pear shaped.
A while back
I created a wee bit of code for point and click form building – PfP
Studio. Key to the utility of this was the ability to treat a
collection of widgets (a form) as a widget itself. And the easiest
way to achieve that was to support multiple windows. When I first
wrote this, I decided that the best way to handle the problem was to
add partitioned areas to the session – one for each window. This
depended on the goodwill of the user to open a new window via the
functionality in the app rather than the browser chrome: each window
had to carry a identifier (the “workspace”) across navigation
events. Effectively I was rolling my own session handling with transids
This has a
number of issues – the PHP sites warns about leaking authentication
tokens but there's also a lot of overhead when you start having to
deal with javascript triggerred navigation, and PRGs.
Then the
other day I discovered that the browser window.name property was
writeable in all
major
browsers! Hallelujah! Yes, it still means that you need to do some
work to populate links and forms, but it's a lot simpler than my
previous efforts – particularly with a javascript heavy site.
Any
new window (unless it has been explicitly given a name in an href
link or via window.open) has an empty string as the name – hence
you simply set a random value if it's empty – and the value
persists even if you press the back button.
While I think I've explained what I'm trying to say, a real example never goes amiss:
if (''==window.name) {
var t=new Date();
window.name=t.getMilliseconds()+Math.random();
}
While I think I've explained what I'm trying to say, a real example never goes amiss:
if (''==window.name) {
var t=new Date();
window.name=t.getMilliseconds()+Math.random();
}