At work recently a bug came my way saying that if a user closed the browser mid way through a certain process it would corrupt the database and not allow the user to re-open that task.
Now obviously there are a few issues here:
- closing the browser did nothing to the database, it just meant that the flex application was not given the opportunity to clean up and the data on the server was left in a state that could not be re-loaded
- whatever calls a client makes to the server the database should never get corrupted and should always be in a re-loadable state!
Easy then, just pass the bug to the java team!
There has been a long standing nice to have task though that we prompt a user when they try to close the browser when they have unsaved data. This bug made it seem like a good idea to look into this.
I knew the basics behind this (use JavaScript to call a flex function) but have never actually done it. I also knew that there was a way of having the flex app inject the JavaScript into the HTML page. I did a bit of googleing and found these 2 bog posts:
- Prompting User on Close of Application: Flex Way
- Inject JavaScript code in html wrapper from Flex/ActionScript
And from what I learnt I came up with this:
- JavascriptInjection
(view source enabled)
The way this works is that when you try to close the browser the onbeforeunload event is fired. This calls the JavaScript function confirmClose which in turn calls the ActionScript function getCloseConfirmMessage. We allow JavaScript to call this function by calling
ExternalInterface.addCallback( "getCloseConfirmMessage", closeConfirmMessage )
within our flex app. This flex function either returns a message to display in the browser dialogue box (the reason why you can’t close the browser for example) or null if you are allowed to close the browser – in which case the browser just closes with no confirm box.
I really like the fact that all this code is inside the swf. I don’t have to make sure that I am deploying the correct html file along side my swf. Any html file will work.
The app I link to above is just an example of how to get it to work. In the real application I have put all of this in a parsley managed class. Parsley is used to dispatch a cancellable event. Any area of the app that has unsaved data for example can cancel the event and provide a message. This message is then returned to JavaScript to be displayed.
I have also added a function call that gets fired when the browser is actually closed. Again this fires a Parsley message and anything that is interested can use this to tidy up – for example close streams that the app is subscribed to.
Thanks to the 2 guys who wrote the 2 blog posts above.
What happens if the user has javascript disabled in their browser?
ReplyDeleteIn that case it's not going to work. This is still not foolproof - a user can kill the browser using task manager as well which won't give us this prompt.
ReplyDeleteIt will in most cases give the flex app the opportunity to warn the user about losing data and clean up open connections for example.
Great Work !
ReplyDelete