You have no doubt seen a lot of timeline navigation systems if you have looked at the files of others, flash templates, or maybe you've even created them in your own files. I used one myself to illustrate button disabling in one of my other tutorials. Typically there will be a labeled frame for each "screen," and buttons that trigger "gotoAndStop" commands on the main timeline. Each destination frame will then also have a keyframe in the actions layer with the actions for that frame.

While this works, it has at least a few fairly serious problems. The first is that whenever flash's playhead is told to gotoAndStop on one of these labeled keyframes, any code on that frame will run, even if it's run previously. That is, any code that's not enclosed in a function will run automatically when the playhead hits that frame. This means that if you navigate away and come back again you will find that the frame has reset itself. This may or may not be what you want, but to have any control over it requires jumping through some serious hoops (for example, one way is making sure you visit a given frame only once, and then after that, never navigate to that frame again, but rather to the following frame).

The second problem is that functions and variables defined in earlier frames are still active in later frames. They are all still active unless they are specifically turned off. This becomes problematic when some of those functions might be listeners that have been added to buttons. If you aren't careful, you can have the user navigating to another frame where the listener is still active, but the button it was added to is gone. A very common problem is attempting to add an event listener to a button that isn't there, which results in a null object reference error. That means that you have to keep buttons around on all frames, and control their access with their "visible" property. Worse still are ENTER_FRAME events that may be running when the user switches frames. It's very easy for an ENTER_FRAME handler function to refer to screen objects that aren't there any more when the frame changes. More null object errors! It is therefore very important to remove listeners that were defined on a given frame when you navigate to another frame.

These two problems both contribute to and are compounded by a third problem: it cannot be known in advance which frame a user is likely to navigate to, or from. Of course, ideally you would like an interface that can be navigated in any order. But the more frames and screens you create, the worse the upkeep gets. For example, on a certain frame, you might have a button, or several buttons, that potentially navigate you away from there.  Let's suppose that frame has an ENTER_FRAME event running. You would have to make sure that every possible exit from that frame removed that listener first. This makes for a lot of repetitive code!

Alternatively, you might decide to just remove that listener on your other (destination) frames. Again, more repetitive code. In fact, since on a given frame you don't have any way of knowing which frame was being navigated from (that is, short of dreaming up some elaborate custom system), you don't even know if that ENTER_FRAME listener is still in force or not. Believe me, while these problems can all be overcome, they are overcome by jumping through even more hoops, and the upkeep gets to be a nightmare. Every time you want to add something to your file, you have to consider the potential implications of all that frame switching all over again.

Here's a typical timeline navigation system:



Have I painted a dismal enough picture yet? Frame switching, turning event listeners on and off, controlling visibility of buttons so that they are always around (to avoid that dreaded error #1009 null object reference). Pretty soon all you are doing is keeping house instead of really innovating and being creative.

The problem that's at the heart of all these other problems is that keyframes on a timeline do not have their own scope, however much it might seem like they should. A "scope" is a section of memory where variables live, where each variable must have a unique name. If two variables have the same name and you don't get error messages when the code runs, then you know they are in different scopes. If you try using the same variable twice in the same timeline (except for local variables inside functions, of course), you will get an error message. Keyframes are not their own scope, the timeline is the scope.

Well, I'm sure I've probably outlined the problem enough. For the rest of this article we will explore a much better way to structure a flash application.

"Frames as screens" is out. "MovieClips as screens" is in. And OOP is in, too! Read on!