reptile7's JavaScript blog
Friday, April 18, 2008
 
The Script Tips #92-93 Script, Part 2
Blog Entry #110

Today we begin in earnest a deconstruction of the pop-up tables script of HTML Goodies' JavaScript Script Tips #92-93. The script's table that displays initially and its pop-up tables are coded by separate script elements in the script document body. This post will focus on the initial display table


and its code:

<table border="0" cellspacing="4">
<script language="javascript">
  for (var i = 0; i < Titles.length; ++i) {
    document.write("<tr>\n<td><p align=\"right\">");
    document.write(Titles[i] + ":</p>");
    document.write("</td>\n<td><a onmouseover=\"eShow(&quot;" + Titles[i] + "&quot;)\"");
    document.write("onmouseout=\"eHide(&quot;" + Titles[i] + "&quot;)\">");
    document.write("<font color=\"#0000ff\" size=\"3\" face=\"Arial\">");
    for (var j = 0; j < Text[i].length; j = j + nCols) {
      if (j > 0) { document.write(", "); }
      if (Text[i][j + 3] == 1) { document.write("<b>" + Text[i][j] + "</b>"); }
      else { document.write(Text[i][j]); } }
    document.write("\n</font></a></td></tr>"); }
</script></table>

The border="0" and cellspacing="4" attributes of the initial display table are both presentational attributes, but neither of them is deprecated, so there's no harm in letting them be. Having said this, I've given the above table and its cells a border: 1px solid black style to illuminate the table's structure.

As you can see, the table has ten rows and two cells per row. The text content of the table's cells is taken from the Titles and Text arrays in the document head via a pair of nested for loops (strictly speaking, only the inner loop is 'nested').

Each table row is written by an iteration of the outer loop:

for (var i = 0; i < Titles.length; ++i) {
document.write("<tr> ... </tr>"); }

Here's the Titles array whose length serves as the upper boundary of the loop:

Titles = [ "General Programming",    "Testing",    "Windows",    "Assembly",    "Data Base",    "Statistical",    "Graphical",    "Text",    "Spreadsheet",    "Command" ];

As far as I am aware, this is the first time we've encountered an array literal in HTML Goodies' JavaScript materials. As Joe notes in Script Tip #92, JavaScript automatically indexes the elements of an array literal, i.e., General Programming is Titles[0], Testing is Titles[1], etc.

So, what all do we have in these table rows? First, each row begins with a \n new line, which is unnecessary and can be removed. (In fact, all of the script's \n's can be thrown out. The \n's would serve a purpose if we were using the script to print out the table's markup, but that's not what we're doing.) Next we come to the first table cell:

document.write("<td><p align=\"right\">" + Titles[i] + ":</p></td>");

For each row, the loop writes to this cell a Titles element that serves as a header for the table cell to its right; consequently, the first cell should be coded as a th element. (The browsers on my computer bold the text in a th element; if this would bother you, then you could give the th element(s) a font-weight: normal style.)

The Titles: text is wrapped in a p element bearing a deprecated align="right" attribute; my preference here is to ditch the p element

document.write("<th class='myHeader'>" + Titles[i] + "</th>");

and instead style the th elements with:

.myHeader { text-align: right; }

We now move on to the much more complicated second, right-hand cells of the table rows. The immediate child of each of these cells is an anchor element that doesn't link to anything (there's no href attribute) but merely serves as a carrier for the onmouseover and onmouseout commands that respectively display and vanish the pop-up tables:

document.write("<td><a onmouseover=\"eShow(&quot;" + Titles[i] + "&quot;)\"");
document.write("onmouseout=\"eHide(&quot;" + Titles[i] + "&quot;)\"> ... </a></td>");

We'll have more to say about the onmouseover/onmouseout commands and their unusual quote formatting at a later point.

In turn, the anchor element contains a font element that holds the cell's text; regarding the script's execution by MSIE, for which the script was originally written, the anchor element is unnecessary as MSIE allows the use of the onmouseover and onmouseout event handlers with the font element. For that matter, you can put the onmouseover/onmouseout attributes in the second cell td start-tag if you prefer; the script effect will be a bit different: the pop-up tables will pop up if the mouse cursor is anywhere (and not just over the text) in the right-hand cells.

As you know, HTML 4.0 deprecated the font element and all of its attributes. (Perhaps unsurprisingly, the HTML 4 Index of Attributes shows that the font element is one of the few elements for which the W3C nixes the use of onmouseover and onmouseout.) We can replace the table font element

document.write("<font color=\"#0000ff\" size=\"3\" face=\"Arial\"> ... </font>");

with a span element

document.write("<span class='mySpan'> ... </span>");

and the following style rule set:

.mySpan { color: blue; font-size: 16px; font-family: Arial, sans-serif; }

The above rule set can alternatively be applied to the second cell td element, in which case the span element would be unnecessary; on the other hand, a span element is as good a carrier as any for the onmouseover/onmouseout commands. The span element was introduced by HTML 4.0, and I find it a bit odd that the script doesn't contain any span elements, given that the script begins with a document type declaration having a -//W3C//DTD HTML 4.0 Transitional//EN public identifier.

The font element content is written by the inner for loop:

for (var j = 0; j < Text[i].length; j = j + nCols) {
if (j > 0) document.write(", ");
if (Text[i][j + 3] == 1) document.write("<b>" + Text[i][j] + "</b>");
else document.write(Text[i][j]); }

The inner loop is executed ten times as determined by the Titles.length upper boundary of the outer loop. However, each run of the inner loop has a different number of iterations because its upper boundary is Text[i].length, the number of elements of the ith child array of the Text two-dimensional array, which differs for each value of i.

The inner loop counter variable, j, is initially set to 0 and increases in multiples of 4 - j = 0, 4, 8, 12, ... - according to the loop's j = j + nCols increment-expression. The nCols variable is set to 4 in the document head and represents the number of columns in each Text child array (not the number of columns in the pop-up tables, as stated incorrectly in Script Tip #92).

Perhaps we should discuss the Text 2-D array a bit before going any further. The Text array comprises ten child arrays. Each Text child array provides data for
(a) a right-hand cell of the initial display table and
(b) a pop-up table
that pertain to a given Titles header. Consider the Text[7] array, which pertains to the Text (Titles[7]) header:

//       Language     Years Last Used   Bold //       -----------  ----- ---------   ----     Text[7] = new Array(  "Word", 10, "Current", 1,  "WordPerfect", 15, 1988,      1,  "TPU",          8, 1987,      0,  "EEL",          5, 1971,      0,  "SNOBOL",       5, 1971,      1,  "Postscript",   1, 1995,      0);

As exemplified above, the elements of each Text child array are arranged into four columns. The elements of the first three columns will respectively fill the td cells of the three columns of a corresponding pop-up table. The fourth column provides Boolean 1 or 0 values for respectively bolding or not bolding the elements of a given array row; for example, regarding Text[7], WordPerfect, 15, and 1988 will be bolded, whereas TPU, 8, and 1987 will not be bolded. (Why bolded or not bolded? We'll discuss this in the next post when we take up the pop-up tables.)

The elements of the "Language" column are also loaded into a right-hand cell of the initial display table. Getting back to our deconstruction of the initial display table and its font element, the inner for loop's j = 4n values map onto the "Language" elements: for Text[7], j = 0 maps onto Word, j = 4 maps onto WordPerfect, j = 8 maps onto TPU, etc., as we'll see below.

So let's write the second cell of the eighth row of the initial display table using the inner for loop and the Text[7] array. Here's what happens:

(1) For the loop's first iteration (j = 0):
(a) if (0 > 0) document.write(", ");
The if condition returns false and the browser moves to...
(b) if (Text[7][3] == 1) document.write("<b>" + Text[7][0] + "</b>");
// Text[i][j + 3] generally references the fourth columns of the Text child arrays.
Text[7][3], Text[7]'s fourth-in-source-order element, is indeed 1 and the if condition returns true, so Text[7][0], Word (Text[7]'s first-in-source-order element), is bolded and written to the page, giving us (after the font element attributes are applied): Word.

(2) For the loop's second iteration (j = 4):
(a) if (4 > 0) document.write(", ");
The if condition returns true, so a two-character comma-space string is appended to Word.
(b) if (Text[7][7] == 1) document.write("<b>" + Text[7][4] + "</b>");
Text[7][7] is 1 and the if condition returns true, so Text[7][4], WordPerfect, is bolded and written to the page, giving us: Word, WordPerfect.

(3) For the loop's third iteration (j = 8):
(a) if (8 > 0) document.write(", ") tacks on another comma-space string.
(b) if (Text[7][11] == 1) document.write("<b>" + Text[7][8] + "</b>");
Text[7][11] is 0 and the if condition now returns false, so the browser moves to...
(c) else document.write(Text[7][8]);
Text[7][8], TPU, is written to the page (but not bolded), giving us: Word, WordPerfect, TPU.

(4) For the loop's fourth iteration (j = 12):
(a) if (12 > 0) document.write(", ") tacks on another comma-space string.
(b) if (Text[7][15] == 1) document.write("<b>" + Text[7][12] + "</b>");
Text[7][15] is 0 and the if condition returns false, so the browser moves to...
(c) else document.write(Text[7][12]);
Text[7][12], EEL, is written to the page (but not bolded), giving us: Word, WordPerfect, TPU, EEL.

(5) For the loop's fifth iteration (j = 16):
(a) if (16 > 0) document.write(", ") tacks on another comma-space string.
(b) if (Text[7][19] == 1) document.write("<b>" + Text[7][16] + "</b>");
Text[7][19] is 1 and the if condition returns true, so Text[7][16], SNOBOL, is bolded and written to the page, giving us: Word, WordPerfect, TPU, EEL, SNOBOL.

(6) For the loop's sixth iteration (j = 20):
(a) if (20 > 0) document.write(", ") tacks on another comma-space string.
(b) if (Text[7][23] == 1) document.write("<b>" + Text[7][20] + "</b>");
Text[7][23] is 0 and the if condition returns false, so the browser moves to...
(c) else document.write(Text[7][20]);
Text[7][20], Postscript, is written to the page (but not bolded), giving us: Word, WordPerfect, TPU, EEL, SNOBOL, Postscript.

I trust you can handle the other table rows at this point. For the time being, that'll do it for the initial display table - we'll take on the pop-up tables in the following entry.

reptile7

Comments: Post a Comment

<< Home

Powered by Blogger

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