reptile7's JavaScript blog
Monday, August 30, 2010
 
Out on the Scrolls
Blog Entry #189

In today's post, we will go through HTML Goodies' "So, You Want A Scrolling JavaScript, Huh?" tutorial and its scrolling text script.

"Not another scrolling text script! Can't we just use the marquee element? Please? Huh? Please??"

No. And I'll send you to the principal's office if you ask that again. Now, where were we? "So, You Want A Scrolling JavaScript, Huh?" presents the second of two scrolling text scripts offered by HTML Goodies' Beyond HTML : JavaScript sector, the first being that presented by the sector's "So, You Want A JavaScript Ticker Tape, Huh?" tutorial, which we recently discussed in Blog Entries #186 and #187. Design-wise, the "Scrolling JavaScript" script is closer to the "JavaScript Ticker Tape" script than to the scrolling text script of HTML Goodies' JavaScript Script Tips #35-37, which we checked over in Blog Entry #65, in that it
(a) uses a secondary index to delimit the space and text zones of its scroll, and
(b) does not append space characters to the text zone as the text zone is whittled down to its last character.

The "Scrolling JavaScript" script does sport a unique feature, however; instead of working with a preset space zone (cf. the tt_space variable in the "JavaScript Ticker Tape" script), the script creates a decrementing-length space zone on the fly via a for loop.

The "Scrolling JavaScript" script is posted at a java.txt page; be sure to unescape the &lt; and &gt; character entity references that bookend the script element start-tag to < and >, respectively, before using it.

The discussion below begins with an analysis of the "Scrolling JavaScript" script. Subsequently, we'll clean the script up a bit and then roll out a cross-browser demo.

Scroll mechanics

As for the "JavaScript Ticker Tape" script, Joe offers no deconstruction for the "Scrolling JavaScript" script - there's some discussion vis-à-vis the script's practical implementation, but that's it - and thus it falls to us to explicate the script's mechanism of action. Fortunately, the "Scrolling JavaScript" script is a more straightforward and less cluttered affair than is its "JavaScript Ticker Tape" counterpart. The "Scrolling JavaScript" script's script element comprises a single function, scrollit_r2l( ), which Joe chose to trigger with an onload event handler:

<body background="#######" onload="timerONE = window.setTimeout('scrollit_r2l(10);', 100);">

When the script document has loaded, scrollit_r2l( ) is called after a 100-ms delay and is also passed the number 10, which is assigned to a seed variable.

function scrollit_r2l(seed) { ... }

seed is the secondary index mentioned earlier; seed is analogous to the tt_c variable in the "JavaScript Ticker Tape" script but runs in reverse, as detailed below. Before putting seed to work, scrollit_r2l( ) declares a series of variables:

var m1 = " FIRST LINE OF TEXT HERE ";
var m2 = " SECOND LINE OF TEXT HERE ";
var m3 = " THIRD LINE OF TEXT HERE ";
var msg = m1 + m2 + m3;
var out = " ";
var c = 1;


• As originally written, the script is set up to scroll three (presumably short) text messages, which are respectively assigned to m1, m2, and m3 variables, which in turn are concatenated and then assigned to an msg variable. This code can be configured at will: any number of messages (surrounded by any number of space characters) can be combined and assigned to msg (we won't see the individual m1/m2/m3 variables after this point); it is not true that [t]his script requires ... three lines to have something.

• The scroll output is appropriately given an out identifier; out is initialized to a single space character.

• The c variable will be used to build the scroll's space zone; c's declaration here is unnecessary and can be removed.

The rest of scrollit_r2l( ) consists of a series of conditionals that are separately operative depending on the value of seed. Here's the first of these conditionals:
if (seed > 100) {
	seed--;
	var cmd = "scrollit_r2l(" + seed + ")";
	timerTwo = window.setTimeout(cmd, 100); }
This conditional does nothing more than decrement seed to 100 and re-call scrollit_r2l( ) if seed is greater than 100. In fact, 100 is as high as seed gets in the script and therefore the above code can be thrown out; if you do so, be sure to also throw out the else keyword that begins the second scrollit_r2l( ) conditional, which is given below:
else if (seed <= 100 && seed > 0) {
	for (c = 0; c < seed; c++) {
		out += " "; }
	out += msg;
	seed--;
	var cmd = "scrollit_r2l(" + seed + ")";
	window.status = out;
	timerTwo = window.setTimeout(cmd, 100); }
In the first run of the scroll, this conditional is executed ten times. Here's what happens in the first of these iterations:

(1) With seed at 10, the for loop appends 10 spaces to out, thereby creating an 11-space space zone for the scroll (not counting the two spaces at the beginning of msg).
(2) The msg text zone is appended to out.
(3) out's value
FIRST LINE OF TEXT HERE SECOND LINE OF TEXT HERE THIRD LINE OF TEXT HERE
is written to the browser window's status bar (for some browsers but not others - vide infra).
(4) seed is decremented to 9.
(5) After a 100-ms delay, scrollit_r2l( ) is re-called and passed the new value of seed; upon re-calling scrollit_r2l( ), out is reset to a single space.

In the second of these iterations: the for loop creates a 10-space space zone; msg is appended to the space zone and the resulting string is outputted to the status bar; seed drops to 8; after a 100-ms delay, scrollit_r2l( ) is re-called and passed seed; out is reset to a single space.

This cycle continues until seed hits 0; in the subsequent scrollit_r2l( ) run, control passes to the next scrollit_r2l( ) conditional:
else if (seed <= 0) {
	if (-seed < msg.length) {
		out += msg.substring(-seed, msg.length);
		seed--;
		var cmd = "scrollit_r2l(" + seed + ")";
		window.status = out;
		timerTwo = window.setTimeout(cmd, 100); }
In each run of the scroll, this conditional is executed msg.length times. During these iterations, seed continues to fall, decrementing stepwise until it reaches -msg.length; as seed decrements, -seed, which rises, is used to delimit the left end of the scroll. Continuing to use Joe's dummy text for our msg value, here's what happens in the first iteration:

(1) With seed at 0, -seed is also 0 and msg.substring(0, msg.length); returns the intact msg string, which (2) is appended to out, which had been set to a single space in the wake of the seed > 0 conditional's last scrollit_r2l( ) call.
(3) out's value
FIRST LINE OF TEXT HERE SECOND LINE OF TEXT HERE THIRD LINE OF TEXT HERE
is written to the status bar.
(4) seed drops to -1; (5) after a 100-ms delay, scrollit_r2l( ) is re-called and passed seed; out is reset to a single space.

In the 10th iteration: seed begins at -9 and -seed at 9; msg.substring(9, msg.length); returns INE OF TEXT HERE SECOND LINE OF TEXT HERE THIRD LINE OF TEXT HERE ,
which is appended to the out space; out is sent to the status bar - note that the out output always begins with a space, even as the scroll's text zone is whittled down; seed drops to -10; after a 100-ms delay, scrollit_r2l( ) is re-called and passed seed; out is reset to a single space.

This cycle continues until seed hits -89; in the subsequent scrollit_r2l( ) run, control passes to the last scrollit_r2l( ) conditional:
else {
	window.status=" ";
	timerTwo = window.setTimeout("scrollit_r2l(100);", 75); } }
A single space is written to the status bar and then scrollit_r2l( ) is re-called and passed 100 after a 75-ms delay to begin the next scroll run. The beginning seed value for the second and subsequent scroll runs is 100 and the seed > 0 conditional for these runs will be executed 100 times (the conditional's for loop will generate a 101-space space zone, a 100-space space zone, a 99-space space zone, etc.).

Conditional retool

Here's how I would rewrite scrollit_r2l( )'s conditional code:
if (0 < seed) { 
	for (var c = 0; c < seed; c++) { out += " "; }
	out += msg; }
else if (-seed < msg.length) {
	out += msg.substring(-seed, msg.length); }
seed--;
window.status = out;
if (-seed == msg.length) {
	seed = 100;
	window.status = " "; }
window.setTimeout("scrollit_r2l( );", 100);
Comments

• For positive values of seed, the if (0 < seed) clause is operative, even as -seed will be less than msg.length for these values.

• In the original script, each scrollit_r2l( ) conditional ends with a delayed and parameterized call to scrollit_r2l( ). As shown above, this call can be 'factored out', i.e., written once at the end of scrollit_r2l( )*. We can unparameterize** the call if we globally initialize seed to 10

var seed = 10;

function scrollit_r2l( ) { ... }


and set seed to 100 in the last scrollit_r2l( ) conditional. Finally, I've thrown out the window.setTimeout( ) assignment to the timerTwo variable, of which no use is made in the script.

*The user will have to wait another 25 milliseconds in going from one scroll run to the next, but that's life.
**Admittedly, the var cmd = "scrollit_r2l(" + seed + ")"; statement is instructive in that it illustrates how to parameterize a window.setTimeout( ) command, but again, parameterization is unnecessary here.

• The seed--; and window.status = out; lines originally appear in both the second and third scrollit_r2l( ) conditionals; I've factored those guys out too.

• The last iteration of the -seed < msg.length conditional originally ends with a scrollit_r2l( ) call; the above code eliminates this call, which is redundant/unnecessary because the last scrollit_r2l( ) conditional itself sets window.status to a space.

Status detour

As in Script Tips #35 and #36, the "Scrolling JavaScript" script outputs its scroll to the browser window's status bar. However, the "Summary" section of Mozilla's current window.status page warns:
This property does not work in the default configurations of Firefox and some other browsers: setting window.status has no effect on the text displayed in the status bar. To allow scripts to change the status bar text, the user must set the dom.disable_window_status_change preference to false in the about:config [pane].
Joe runs the script at the tutorial page; in practice on my computer, I see his scroll when using Safari, Opera, or MSIE, but not when using a Mozilla-based browser (Firefox, Camino, Netscape 9) or Chrome.

Of course, we have other options for outputting a scroll. Directing out to a text box would be the classical thing to do, although my own preference is to load out into a div element per the "Format me" section of Blog Entry #187. So, for those of you who can't see Joe's scroll in the status bar at the tutorial page, here's a div-based version of what you're missing (OK, I've tidied Joe's messages up a bit):


There's not much to the next two Beyond HTML : JavaScript tutorials - "Print A Web Page Using JavaScript" and "So, You Want A Live Script, Huh?" - but each of them deserves some brief commentary, so maybe we can cover both of them in the following entry.

reptile7

Comments: Post a Comment

<< Home

Powered by Blogger

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