reptile7's JavaScript blog
Friday, September 19, 2014
It Fades and Spins
Blog Entry #335

The law of diminishing returns is rapidly setting in with respect to the Java Goodies Scripts that Display Text sector: most of the remaining scripts are simply too trivial to cover. We will work through one last sector offering, that being the "Text Fader 1.3" script*, which was written by Emmanuel C. Halos in August 1998.
(*Two previous versions of the script - "Text Fader" and "Fade Out" - also appear in the sector, but we won't be discussing them.)

The Text Fader 1.3 script creates a 'movie' in which text strings
(1) fade out of a black background to the foreground or
(2) fade from the foreground into the background or
(3) fade from one foreground color to another foreground color.
The script demo does not work with any of the OS X browsers on my iMac although it might work for you if you're using IE on a PC.

The Text Fader 1.3 script does not have a separate Grab the Script page: you'll have to extract the script from the source of the demo page.

Starting HTML/CSS

Each movie string will be housed in one of two div elements.

#fadeMe01 { position: absolute; visibility: visible; width: 410px; }
#fadeMe02 { position: absolute; visibility: visible; width: 400px; }
<div id="fadeMe01"></div>
<div id="fadeMe02"></div>

• The fadeMe01 and fadeMe02 divs are absolutely positioned but are not offset** in any way. As they are also the first two elements of the document body, the divs are both initially placed in the upper-left-hand corner of the viewport.
(**Because the initial top and left values are auto and not 0, each div has an 8px margin-top and margin-left.)

• The visibility declarations can be removed as the initial visibility value is visible.

The black background color is set by the body element start-tag.

<body bgcolor="#000000" text="#cccccc" link="#ffffff" vlink="#ffffff" onload="layout( );">

The deprecated bgcolor, text, link, and vlink attributes should be traded in for corresponding style rules:

body { background-color: black; color: #cccccc; }
a:link, a:visited { color: white; }

A script element in the document head holds the script's JavaScript, which we'll get to in just a bit. Meanwhile, the divs are followed by a noscript element.

<noscript>Silly! You'll need to have JavaScript enabled and you must have <a href="">Internet Explorer 4</a> or <a href="">Netscape Navigator 4</a> or <a href="">WebTV</a>(?) for this script to work.</noscript>

Leaving aside the (in)advisability of nagging at users without JavaScript support, I should point out that the content model of the noscript element differs in the Strict and Transitional DTDs, namely, it's (%block;)+ in the former and (%flow;)* in the latter, and consequently the above noscript will pass a transitional validation but throw an error in a strict validation, so you may want to wrap the noscript text in a div or p element. BTW, the and links are dead. (Like Netscape, WebTV is kaput - read about it here.)

Starting JavaScript

User agents of yesteryear

As intimated by the noscript text, the current versions of IE and Netscape in 1998 were IE 4.x and Netscape 4.x, respectively; the script defines style, layers, and both variables that will screen for these browsers.

<script type="text/javascript"> ...
var style = document.all;
var layers = document.layers;
var both = layers || style;

In the SheepShaver environment, I find that the script works flawlessly with Netscape 4.61, is slightly buggy with IE 4.5, and works flawlessly with IE 5.1.7 once I remove the quirks mode → strict mode-inducing

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "">

document type declaration at the top of the document.

Only IE 4+ and Opera 5-9.2 will go through a document.all gate, whereas only Netscape 4.x will go through a document.layers gate: thank goodness such tests have been obsoleted by the W3C DOM.

Radix ricochet

Each movie string has
(1) a starting color whose R/G/B components go from hexadecimal to decimal to hexadecimal numbers
(2) an ending color whose R/G/B components go from hexadecimal to decimal numbers
in the course of the script. To facilitate these base 16 ↔ base 10 interconversions, the script creates a convert database of two-digit hexadecimal number strings running from "00" to "FF" inclusive.

var convert = new Array( );
var hexbase = new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F");
var value = 0;

for (x = 0; x < 16; x++) for (y = 0; y < 16; y++) { convert[value] = hexbase[x] + hexbase[y]; value++; }

An empty array and an ordinal array of hexadecimal digits are created and given the identifiers convert and hexbase, respectively. A value variable will serve as the index for the convert array and is initialized to 0. Subsequently a two-dimensional loop statement builds the convert database in sequence from the hexbase values:

convert[0] = "00", convert[1] = "01", ... convert[15] = "0F", convert[16] = "10", ...
convert[50] = "32", ... convert[100] = "64", ... convert[200] = "C8", ... convert[255] = "FF"

We'll see later that this code, too, is unnecessary.


The idme and rgb variable declarations at the beginning of the script element

var idme = 908601; var rgb;

can be thrown out as these variables find no use in the script.

Subroutine it

Over and above its smattering of top-level code, the script element contains eight functions, in source order:
(1) stopClock( )
(2) moveLayer( )
(3) hexToDec( )
(4) writeOn( )
(5) changeColor( )
(6) fadeText( )
(7) getMid( )
(8) layout( )

The action kicks off with the layout( ) function, which fires when the page loads (<body onload="layout( );">, vide supra).

The center of attention

The layout( ) function first calls the getMid( ) function.

function layout( ) { getMid( ); ... }

The getMid( ) function locates the (midX, midY) midpoint of the viewport.

function getMid( ) { tvAgent = navigator.userAgent; if (layers) { maxX = window.innerWidth; maxY = window.innerHeight; } if (style) { maxX = document.body.clientWidth; maxY = document.body.clientHeight; } if (tvAgent.indexOf("WebTV") != -1) { maxX = 544; maxY = 378; } midX = maxX / 2; midY = maxY / 2; }

For modern browsers the getMid( ) function can be recast as:

function getMid( ) { maxX = window.innerWidth ? window.innerWidth : document.body.clientWidth; maxY = window.innerHeight ? window.innerHeight : document.body.clientHeight; midX = maxX / 2; midY = maxY / 2; }
/* The ?: conditional operator is documented here. */

We've tussled with this sort of thing before - here's the skinny (go here for a more detailed discussion):
The document.body.clientWidth/document.body.clientHeight property pair gets the viewport dimensions for IE 6+ as long as the browser is running in quirks mode; window.innerWidth/window.innerHeight does the job for everyone else. The innerWidth/innerHeight measurements would include the width of a vertical scrollbar and/or the height of a horizontal scrollbar if they were present.

The layout( ) function next calls the moveLayer( ) function

moveLayer("fadeMe01", midY - 50, midX - 200);

and passes thereto fadeMe01, midY-50, and midX-200. The moveLayer( ) function moves the fadeMe01 div to the center of the viewport (not the exact center, but close enough for our purpose).

if (layers) { layerRef = "document.layers"; styleRef = ""; }
if (style) { layerRef = "document.all"; styleRef = ".style"; }

function moveLayer(obj, topx, leftx) { if (both) { eval(layerRef + "['" + obj + "']" + styleRef + ".top = topx"); eval(layerRef + "['" + obj + "']" + styleRef + ".left = leftx"); } }

This seriously ugly code can be replaced with:

function moveLayer(obj, topx, leftx) { document.getElementById(obj) = topx + "px"; document.getElementById(obj).style.left = leftx + "px"; }

We're ready to put a string in the fadeMe01 div and get the fading under way - we'll do that in the following entry.

Comments: Post a Comment

<< Home

Powered by Blogger

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