Hack 94 Integrate the Back Button with Flash 
A long-standing complaint against
Flash's usability is that it didn't
work with the browser's Back button. Dispel this
myth—use the browser Back button to navigate back in a
non-timeline-based Flash site.
Part of the design
intent of Flash MX (and Flash Player 6) was to make Flash more
accessible. Among other things, Macromedia added support for
named anchors.
Most designers know
anchors by their
HTML-based implementation. An anchor is a link within a document
(usually) to another part of the same document. It is often used in
long text documents in which significant parts of the document scroll
outside the visible area of the browser window. Rather than having to
scroll up and down the page, an anchor allows users to jump to the
required section via an intrapage link. The anchor name is preceded
by a #, such as http://www.oreilly.com/index.html#faq.
In its implementation of anchors, Macromedia equated the HTML
document to the SWF's main timeline, so anchors
allow you to jump back and forth along _root using
the browser Back button (assuming an accessibility-enabled browser).
Naturally, within Flash, you can still use typical Flash navigation
(i.e., Flash buttons with gotoAndPlay( ) actions
as part of their onRelease( ) event handlers).
One major problem is that most Flash sites do not use frames on the
_root timeline as anchor points. When the user
clicks on a button, he doesn't jump to a frame on
_root because that approach makes the SWF
difficult to maintain and has a number of issues when you start using
bandwidth-heavy content. Instead, a Flash interface for a typical
commercial application uses an ActionScript-based system that employs
loadMovie( ) and nested movie clips or attaches
content directly to the main timeline.
The only way to hack around this is to have hidden HTML pages that
change in step with the Flash site; it is these hidden pages that
populate the browser history. When the hidden HTML pages change due
to the browser Back and Forward buttons, JavaScript is used to send
variable values to the Flash site telling it about the page changes,
and the Flash site is configured to catch and respond to these
changes.
You can't use JavaScript to simply read the browser
history and send it to Flash because it isn't
accessible to JavaScript (or anything else) for security reasons
(i.e., keeping your browsing preferences outside the reach of
advertisers).
Creating the HTML
By far the easiest way to set up your hidden HTML pages is to include
them in the same page as the Flash site using a frameset. Given that
many Flash users have the Macromedia Studio MX package, we will use
Dreamweaver
MX (you can enter the HTML listings shown in an editor of your
choice).
Dreamweaver MX has something close to the frameset we need as a
standard template, so select File New and select the Fixed
Bottom frameset as shown in Figure 11-19.

Our Flash HTML file will populate the top frame, and the hidden HTML
pages will be implemented as blank pages (containing only JavaScript)
in the lower frame.
Using this template (or similar), create the following HTML. The
lines I have changed from the Dreamweaver MX defaults—the
title, the two frame source files, and the noframes
content)—are highlighted in bold. Save the frameset as
frame.html.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/
TR/html4/
frameset.dtd">
<html>
<head>
<title>:: Flash with Browser History ::</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#FFFFFF">
<frameset rows="*,80" frameborder="NO" border="0" framespacing="0">
<frame src="flash.html" name="mainFrame">
<frame src="one.html" name="bottomFrame" scrolling="NO" noresize>
</frameset>
<noframes><body>
You should really get a more up-to-date browser before they phase out steam power.
</body></noframes>
</html>
Next up, our hidden pages. Create five blank HTML files named
one.html, two.html,
three.html, four.html, and
five.html, and save them in the same folder as
frame.html.
Modify the first file, one.html, as shown
(changes from Dreamweaver MX defaults are shown in bold):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>one</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#FFFFFF">
<script language='JavaScript'>
parent.mainFrame.flash.SetVariable('history', 1);
</script>
</body>
</html>
Note that the <title> tag should change for
each file, in this case one, and the line of
JavaScript should specify the file number, in this case 1, as the
second parameter passed to SetVariable( ). We
explicitly set the background color of the bottom frame pages, so
that they aren't noticeable if the user has a
different default background color set.
Modify the remaining four HTML files similarly. For example, here are
the changes to five.html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>five</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#FFFFFF">
<script language='JavaScript'>
parent.mainFrame.flash.SetVariable('history', 5);
</script>
</body>
</html>
Your frameset won't work just yet because it is
missing the flash.html section, so
let's create that next.
In Flash, create a new Flash Document with File New. Select
File Publish Settings and set these options under the HTML
tab of the Publish Settings dialog box: set the Horizontal and
Vertical options under Flash Alignment to Center, and set the Scale
option to No Scale, as shown in Figure 11-8
[Hack 90].
Save the Flash file as
flash.fla in the
same folder as the previously saved HTML files (but remember to
upload the SWF, not the FLA, if you decide to put the files online!).
Publish the file (File Publish) to create
flash.html and flash.swf.
Creating the Flash Content
We will create a simple embedded timeline to show the principle of
the hack.
Create a new movie clip symbol with five keyframes (it
doesn't matter what the symbol is named), as shown
in Figure 11-20, each of which shows a different page
of our Flash application, as shown in Figure 11-21.


Place the clip onto the Stage at frame 1 of the main timeline, and
give it the instance name content using the
Properties panel. Next, add a menu of five buttons with instance
names b1 (the 1 button) to b5
(the 5 button).
Finally, create a new layer above the current one, calling it
actions. Attach the following script to frame 1
of this new layer:
b1.onRelease = function( ) {
fillBottom("one.html");
content.gotoAndStop(1);
};
b2.onRelease = function( ) {
fillBottom("two.html");
content.gotoAndStop(2);
};
b3.onRelease = function( ) {
fillBottom("three.html");
content.gotoAndStop(3);
};
b4.onRelease = function( ) {
fillBottom("four.html");
content.gotoAndStop(4);
};
b5.onRelease = function( ) {
fillBottom("five.html");
content.gotoAndStop(5);
};
function setHistory( ) {
if (history == 1) {
hisEnabled = true;
content.onEnterFrame = function( ) {
if (history != 0) {
this.gotoAndStop(history);
history = 0;
}
};
}
clearInterval(startHistory);
}
function fillBottom(doc) {
if (hisEnabled) {
getURL(doc, "bottomFrame");
}
}
var history;
var hisEnabled = false;
startHistory = setInterval(setHistory, 500);
content.stop( );
When you click each of the buttons, not only does Flash jump to the
appropriate frame in the Flash timeline, but the function
fillBottom( ) jumps to a corresponding HTML page in
the lower frame of the final web page. Although the user
doesn't see these HTML pages (they contain no
visible content), the browser adds them to the browser history.
As the user clicks the browser Back and Forward buttons, the same
HTML pages are reloaded from the browser history, and the JavaScript
inside them changes a Flash variable, history, to
a value between 1 and 5, depending on the page.
The onEnterFrame( ) handler catches this change
and forces content to change its appearance in sync with the HTML
page change, thus propagating the browser history to the Flash movie.
Note that when you are using the Flash buttons for navigation, you
actually tell the movie clip content to jump to the required frame
twice, once from ActionScript and once from JavaScript. Rather than
remove the ActionScript jumps, it's better to leave
them in for redundancy; this ensures that the navigation still works,
even if JavaScript isn't available.
The ActionScript is written so that:
The navigation still works if JavaScript is not available in the
current browser (or the SWF is running in a Standalone Player). Flash
knows if JavaScript is not working via the if
(history==1) check within setHistory(
). If JavaScript is disabled, history
is undefined, and Flash addresses this by not setting up the
onEnterFrame( ) handler so that no checks on
browser history are made. A delay of 0.5 seconds is included before ActionScript starts talking
to JavaScript. The HTML doesn't seem to start
setting the Flash variable history until after a
short delay. The ActionScript therefore delays the creation of the
onEnterFrame( ) handler for 0.5 seconds using
setInterval( ).
Final Thoughts
If you set up a history by moving back and forward using the Flash
navigation buttons, you will see the browser Back and Forward buttons
become active. Clicking on either of the browser buttons allows you
to go back/forward through this history.
A lack of Back button functionality is one of the major usability
problems normally pinned on Flash. Someone tell Jakob
we've fixed it!
Of course, there are still a few issues here for advanced Flash
users, like the fact that you need to create (and maintain) a blank
HTML page for every Flash page you use, which can be a real pain and
which breaks one of the really cool things about Flash design (i.e.,
it isn't page based). This brings up an irony of
using the Back button in Flash. The question arises, where should the
user go back to in the current Flash application? In an HTML-based
site, each page represents the application state at a given time. But
in a Flash application, each
"scene" might span many frames and
contain animations or time-based media. For example, if the user
clicks the Back button to return to the previous scene, should the
Flash designer rewind and replay the animation, audio, and video in
the scene? Think carefully about your application's
state when deciding which pages to use to represent a point in time.
A possible enhancement to this hack is to generate the HTML pages in
the hidden frame dynamically via JavaScript. This way, the number of
pages you can add to the browser history is not hardcoded, allowing
for a more flexible solution for more complex Flash sites.
JavaScript-to-Flash communication is
not supported in all browsers, as discussed at http://www.macromedia.com/support/flash/ts/documents/java_script_comm.htm.
This hack works in Netscape and IE, but at least one user reported a
JavaScript error when using Mozilla 1.6. You can test various
browsers at Macromedia's JavaScript-to-Flash
communication example page, at http://www.macromedia.com/support/flash/ts/documents/java_script_comm/javascript_to_flash.html.
|