reptile7's JavaScript blog
Sunday, December 16, 2012
Voyage to the Bottom of the Viewport
Blog Entry #273

In response to reader requests, Lissa modified Altan d.o.o.'s original falling snow script so that its images "fall" from the bottom to the top of the viewport instead of from top to bottom: the resulting code is the third script offered by Section 1 of the JavaScript subsector of Lissa Explains It All. A .zipped bubbleinstructions.txt file containing the script plus some commentary can be downloaded here.

Lissa provides an up.html demo page that illustrates the script with a set of bubble images. Interestingly, Lissa adds to her demo two fish marquees that 'swim' across the viewport as the bubbles rise; the marquee code does not appear in the bubbleinstructions.txt file. The marquee part of the demo was IE only at the time the script was written - Netscape's support for the marquee element only goes back as far as Netscape 7 - although the bubbles part could be run by both IE and Netscape.

In this post we'll detail the differences between Altan's original script and Lissa's modified script and also examine the added marquee code, with a demo to follow.

The differences

Not so important

The modified script replaces the original script's var snowflake = "snow.gif"; image with a snow array of three images.

var snow = new Array( );
snow[0] = "yourfilename1.gif";
snow[1] = "yourfilename2.gif";
snow[2] = "yourfilename3.gif";

For her demo, Lissa fills the array with bubble1.gif, bubble2.gif, and bubble3.gif images.

Lissa ups the no "snow number" to 30

var no = 30; // Snow number - no is 15 in the original script.

and uses a 30-iteration for loop to write 10 sets of the snow images to the page. (It's not necessary for no to be an even multiple of snow.length, although I myself would have done it that way.)

var i, j = 0;
for (i = 0; i < no; ++i) { ...
    document.write("<div id='dot" + i + "' style='position:absolute;z-index:" + i + "visibility:visible;top:15px;left:15px;width:1;'><img src='" + snow[j] + "' border='0'></div>");
    if (j == (snow.length - 1)) { j = 0; } else { j += 1; } }

The snow images are written in a snow[0]-snow[1]-snow[2] cycle per the value of a j index, which is initialized to 0 and is incremented or reset by the if...else statement at the end of the loop.

The width:1; div style is new, but I have no idea what it's doing there. This declaration is ignored in strict mode because the width value doesn't have a unit identifier; it causes the divs to collapse to 1px-thick vertical lines in quirks mode, but this isn't a problem because the snow images horizontally overflow the divs and are rendered normally. Throw it out.


In the modified script's snowIE( )/snowNS( ) functions, the sty[i] vertical step is iteratively subtracted from the yp[i] top offset.

for (i = 0; i < no; ++i) { yp[i] -= sty[i]; ... } // sty[i] is added to yp[i] in the original script.

For the functions' image renewal code, the modified script lets each image rise to a top value of -50px before renewing the image and then drops the image to a top value of doc_heightpx for its next rise.

for (i = 0; i < no; ++i) { ...
    if (yp[i] < -50) {
        yp[i] = doc_height; ... } }
/* yp[i] maxes out at doc_height-50 and is reset to 0 in the original script. */

(These renewal boundaries are a bit overkill IMO - for the 24px-by-24px bubble images of Lissa's demo, I would trigger renewal at yp[i] < 0 and restart the images at yp[i] = doc_height - 24 - but to each her own.)

Marquee madness

In the up.html document body the rising bubbles script is followed by the marquee code below:

<marquee behavior="scroll" direction="right" scrollamount="2">
<image src="chimage.php?image=mfish1.gif" width="75" height="50" alt="fish" border="0"></a>
<marquee behavior="scroll" direction="left" scrollamount="2">
<image src="chimage.php?image=mfish2.gif" width="75" height="50" alt="fish" border="0"></a>

(The </a> tags following the image elements do not have corresponding start-tags and should be removed - we shouldn't be putting a link in a marquee anyway.)

The first marquee should show two right-facing fish - a leading large fish and a trailing small fish - slowly swimming rightward across the viewport. About 55px beneath the first marquee the second marquee should show a left-facing large fish slowly swimming leftward across the viewport. Upon testing the up.html page with Opera 7.50, a browser that gets through the var ie4up = (document.all) ? 1 : 0; gate, I find that the rising bubbles action is A-OK but there are empty placeholders where the marquee images should be.

Note that the image elements are named image and not img - Lissa didn't 'write' this code with (shudder) an HTML editor, did she? But curiously enough, every GUI browser on my computer, in both the OS X and SheepShaver environments, accepts image in place of img, so that's not the culprit.

As you might expect, the image src URLs are where the problem lies. These URLs seem to point to a PHP script that presumably loads mfish1.gif and mfish2.gif images into their respective placeholders. However,,, and all route me to the Lissa Explains It All home page - whatever chimage.php was, it's gone.

As the bubble images are located in the hostname directory, I decided to see if and would respectively lead me to the mfish1.gif and mfish2.gif images. Yes! Success!

But do we want to be using marquees in the first place? Per Blog Entry #163 (see The W3C and the marquee element subsection), HTML5 has obsoleted the marquee element, its widespread support notwithstanding. (Actually, the version of Safari on my computer - Safari 5.0.6 - strangely refuses to run the two marquees simultaneously; unrelatedly, it has also dropped support for the alternate marquee behavior.) Fortunately, a JavaScript equivalent is at hand...

left it

For the next section's demo, I
(a) give the mfish1.gif img element an id="fish0" and the mfish2.gif img element an id="fish1" and
(b) position:absolute; the elements, and then
(c) use the script below to move the images across the viewport.

var fish0 = document.getElementById("fish0");
var fish1 = document.getElementById("fish1");
var leftnumber0, leftnumber1; = "-75px"; = "115px"; = doc_width + "px";
window.onload = function ( ) { window.setInterval("moveFish( );", 80); }

function moveFish( ) {
    leftnumber0 = parseInt(, 10);
    leftnumber1 = parseInt(, 10);
    if (leftnumber0 < doc_width) = (leftnumber0 + 2) + "px";
    else = "-75px";
    if (leftnumber1 > -75) = (leftnumber1 - 2) + "px";
    else = doc_width + "px"; }

(Both mfish1.gif and mfish2.gif have a width of 75px - that's what the 75 is about.)

The above script is based on the code samples in HTML Goodies' "How to Create a JavaScript Animation" tutorial, which we covered in Blog Entries #209 and #210. The offset is initialized to -75px and the offset is initialized to doc_widthpx; a moveFish( ) function increments the former offset so as to shift the fish0 fish rightward and decrements the latter offset so as to shift the fish1 fish leftward. Pretty straightforward.


February 2017 Update: For the restored demo below, the fish left offsets range from "0px" to doc_width2 - 75 + "px" so as to prevent the generation of a horizontal scrollbar when the fish are at the left/right edges of the div - check the page source for the full coding.

So here's what you should see at the up.html page (some slight variations between the displays notwithstanding):


There's one more up.html code difference that we haven't discussed yet. The up.html document head contains a script whose purpose is to cancel right-click events - we'll go through this script in detail in the following entry.

Comments: Post a Comment

<< Home

Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)