JavaScript Animation in Navigator 4.0 and MSIE 4.0
How to outsmart your browser

by Adam Stock

WHY DO ANIMATIONS RUN DIFFERENTLY IN NAVIGATOR AND EXPLORER?
Anyone who has tried to write a non-trivial program in JavaScript has encountered numerous differences between the Netscape Navigator (Navigator 4.0) and Microsoft Internet Explorer 4.0 (MSIE 4.0) implementations. Writing animation that runs the same way under both browsers is a considerable challenge because each browser implements painting to the screen differently. Specifically, Navigator 4.0 guarantees that all paint events will get executed whereas MSIE 4.0 may 'drop events' for efficiency.

In MSIE 4.0 drawing images to the screen is implemented as a 'buffered queue' which runs in a lower priority thread than the main execution thread. In other words, every call that causes bits to be painted to the screen, such as changing the 'src' tag of an image, gets executed in a separate thread that gets executed when the main execution thread halts. This behavior contrasts with the Netscape Navigator implementation where painting to the screen is logically part of the main execution context.

In addition, MSIE 4.0 implements a look-ahead scheme in its buffering of painting calls for 'efficiency'. The look-ahead scheme notes where the same image is being repainted in its buffer and only paints the 'last' image in the chain.

A SIMPLE EXAMPLE
Since most programmers use JavaScript to implement simple 'rollovers' for buttons, this isn't a problem. If your rollover were to be fancier, such as flashing the button by cycling through four images, the difference would immediately become apparent. In Navigator 4.0 the images would cycle completely. In MSIE 4.0 the user would only see the last image.

Logically your code would follow this sequence:

Navigator 4.0 would execute the commands in this order. What the user would see is this:

MSIE 4.0 sends each draw event to a lower priority thread: MSIE 4.0 then 'notices' that the queued paint events in its painting thread are all drawing to the same image. For efficiency, it reduces the painting thread to the following: What the user sees it this: This behavior is illustrated in this simple image replacement example.

JAVASCRIPT ANIMATIONS: A REAL WORLD EXAMPLE
Although this rollover example is trivial, this implementation difference represents a significant challenge to anyone trying to program an animation sequence in JavaScript. In the following 'Towers of Hanoi' program (Hanoi1), pressing the 'Solve It' is supposed to show the user how to solve the puzzle by animating the puzzle pieces and solving the puzzle. Under Navigator, the animation works fine. Under MSIE 4.0, the user only sees the first and the final frames of the animation.

The biggest challenge in solving this problem is that JavaScript does not provide the kind of thread controls, semaphore or other system level calls to directly control this problem. Instead we need to 'outsmart' the MSIE 4.0 JavaScript implementation through use of the 'setTimeout' command. The only control that JavaScript gives the programmer to create threads.

THREADED IMAGE REPLACEMENT -- A PARTIAL SOLUTION
Since each execution thread has an associated drawing thread, a partial solution is to simply put each draw event into a 'setTimeout' command. Obviously the look-ahead scheme used only works within a given paint thread so we can ensure that every paint event gets executed by MSIE 4.0 and will be drawn to the screen.

The drawback to this approach is that all the drawing threads get executed in rapid succession after the main execution finishes. The animation plays very quickly which, in most instances, is not acceptable. In fact, on faster computers, the same dropping of events may happen at the operating system level causing you not to see rapid flashes!

This behavior is illustrated in this threaded image replacement example.

QUEUED, THREADED IMAGE REPLACEMENT -- A FULL SOLUTION
A full solution which both ensures that every draw event or 'frame' of an animation gets played, and ensures that the frames are played at a controlled speed, is an animation queue. An animation queue is simply a list of drawing calls that are queued and played (each in its own thread) at timed intervals. This solution works exactly the same way in both Navigator 4.0 and MSIE 4.0.

This behavior is illustrated in this queued, threaded image replacement example.

The 'Towers of Hanoi' program (Hanoi2) implements the 'Solve It' button using the animation queue technique.

© 1998 Adam Stock. All rights reserved.