reptile7's JavaScript blog
Monday, April 28, 2008
 
The Script Tips #92-93 Script, Part 3
Blog Entry #111

We continue today our analysis of the pop-up tables script of HTML Goodies' JavaScript Script Tips #92-93. In this post, we'll turn our attention to the script's pop-up tables; as noted two entries ago, Joe for his part discusses the pop-up tables in a not-at-HTML Goodies "Post the Tables" article.

Culled from the script's document body, here's the pop-up table code:

<div style="position:relative">
<script language="javascript">
    for (var j = 0; j < Titles.length; ++j)
    {
        name = Titles[j];
        document.write(
        "<div style=\"position:absolute;top:5px;width:350px\">\n" +
        "    <table id=\"" + name + "\"" +
        " cellpadding=1 cellspacing=4 border=2" +
        " bgColor=" + bgColor + "\n style=" +
        "\"display:none; position:absolute; left:200px\">");
        document.write(
            "<tr bgColor=" + bgColor + ">");
        document.write(
            "  <th bgColor=" + fgColor + " align=center>" +
            " <font color=" + bgColor + ">Language</font>");
        document.write(
            "  <th bgColor=" + fgColor + " align=center>" +
            " <font color=" + bgColor + ">Years Used</font>");
        document.write
            ("  <th bgColor=" + fgColor + " align=center>" +
             " <font color=" + bgColor + ">Last Used</font>");
        for (var i = 0; i < Text[j].length; i = i + nCols)
        {
            if (Text[j][i + 3] == 0)
            {
                document.write(
                "  <tr><td>" + Text[j][i] + 
                "\n    <td align=\"center\">" + Text[j][i+1] + 
                "\n    <td>" + Text[j][i+2] + "\n  </tr>");
            }
            else
            {
                document.write(
                "  <tr><td><b>" + Text[j][i] + 
                "</b>\n    <td align=\"center\"><b>" + Text[j][i+1] + 
                "</b>\n    <td><b>" + Text[j][i+2] + "</b>\n  </tr>");
            }
        }
        document.write("</table>");
        document.write("</div>");
    }
</script>
</div>

Table position

Between the document body's "Pop-up table sample" heading and the initial display table, which we deconstructed in the previous entry, is a div element holding a script element that codes a set of ten div elements in which the pop-up tables are assembled respectively. The outer div element

<div style="position:relative;"> ... </div>

is given a position: relative style but is not given values for the CSS left and top properties; consequently, the outer div - let's give it an id="div1" identifier - is located at its "normal flow" position even as it contains no renderable content (we'll see in a moment that the pop-up tables are external to div1). The div1 div has an effective width value of 100%, spanning the width of the browser window; more specifically, per Section 10.3.3 of the CSS 2.1 Specification, the width of the div1 div is equal to that of its containing block, which is established by the body element.

In contrast, the inner div elements, which we'll give a class='div2' identifier, are absolutely positioned and have a specific width:

document.write("<div style=\"position:absolute;top:5px;width:350px;\" class='div2'> ... </div>");

The containing block for the div2 divs is established by the div1 div by virtue of the latter's relative positioning (the W3C addresses this situation in the second example of this CSS 2.1 Specification section); if the div1 div were not positioned, then the div2 containing block would be the "initial containing block", i.e., the div2 divs would be positioned relative to the upper left-hand corner of the document content area (a.k.a. the "canvas origin"). So, the div2 divs are set 5 pixels below the div1 div; because the div1 div contains no renderable content, and because an absolutely positioned element is removed from the normal flow entirely (it has no impact on later [elements]), this means in practice that the div2 divs lie outside the div1 div and slightly below the top of the initial display table - this can be verified via giving differently colored 1px borders to the div1 div, the div2 divs, and the initial display table.

The pop-up tables are also absolutely positioned:

var bgColor = "Yellow"; // bgColor is declared in the document head's script element.
name = Titles[j];
document.write("<table id=\"" + name + "\" cellpadding='1' cellspacing='4' border='2' " +
"bgcolor=" + bgColor + " style=\"display:none; position:absolute; left:200px;\"> ... </table>");


The containing block for each pop-up table is established by its div2 div parent by virtue of the latter's absolute positioning; the left edge of each table is pushed 200 pixels to the right of the left edge of its div2 parent, whereas the top edge of each table coincides with the top edge of its div2 parent. If we give the initial display table and its cells a border: 1px solid black style, then the top edge of each pop-up table will coincide with the top border of the right-hand cell of the first row of the initial display table:

Absolute position of a pop-up table

The script's nested-div positioning scheme works OK with MSIE 5.1.6 (but not with Netscape 7.02 - we'll look at Netscape's execution of the script in the next post) on my computer but is nonetheless more complex than it needs to be; specifically, I find that the div2 divs can be removed and that the div1 div is suitable for positioning the pop-up tables:

#div1 { position: relative; }
#div1 table { display: none; position: absolute; left: 200px; top: 5px; }

Writing the tables

Like the initial display table, the pop-up tables are created by a pair of nested for loops.

Each iteration of a 10-iteration outer loop

for (var j = 0; j < Titles.length; ++j) { ... }

codes a div2 div and the pop-up table it contains.

Structurally, each pop-up table begins with a row of headers: "Language", "Years Used", and "Last Used". The header rows are written by the outer loop:

var fgColor = "Black"; // fgColor is declared in the document head's script element.
document.write("<tr bgColor=" + bgColor + ">");
document.write("<th bgColor=" + fgColor + " align=center>" + "<font color=" + bgColor + ">Language</font>");
document.write("<th bgColor=" + fgColor + " align=center>" + "<font color=" + bgColor + ">Years Used</font>");
document.write("<th bgColor=" + fgColor + " align=center>" + "<font color=" + bgColor + ">Last Used</font>");

/* The </tr> and </th> tags are omitted in the script; they are optional in HTML but required for XHTML-compliance. */

Below the header row are (depending on the table) 2-10 rows whose cell data is taken from a corresponding child array of the Text two-dimensional array in the document head; these rows are written by the inner loop:

for (var i = 0; i < Text[j].length; i = i + nCols) {

if (Text[j][i + 3] == 0) // For non-bolded rows
document.write("<tr><td>" + Text[j][i] + "<td align=\"center\">" + Text[j][i + 1] + "<td>" + Text[j][i + 2] + "</tr>");

else // For bolded rows
document.write("<tr><td><b>" + Text[j][i] + "</b><td align=\"center\"><b>" + Text[j][i + 1] + "</b><td><b>" + Text[j][i + 2] + "</b></tr>"); }

Presentationally (besides the positional aspects covered above):

(1) Regarding their 'border model', the pop-up tables are equipped with cellpadding='1', cellspacing='4', and border='2' attributes, none of which is deprecated.

(2) (a) The tables are given a yellow background color via the bgColor variable. The background color of the table cells in the rows below the header rows is also yellow because these cells and their tr element parents have a "transparent" background and thus the table background color shows through - see the "Table layers and transparency" section of the CSS 2.1 Specification for a fuller treatment of table element backgrounds as a function of table structure.
(b) The cells in the header rows are given a 'complementary'* color scheme - yellow text on a black background - via the bgColor and fgColor variables. (*The below-the-header-rows cell text color is the same as the browser's default text color (as set in the browser's "Preferences" file), which should be black for most users; it is not specfically set to black by the script.)
All color-related attributes were deprecated by HTML 4.0.

(3) An align="center" attribute is applied to the text in the cells under the "Years Used" header (i.e., in the middle column) and also to the header-row cell text; actually, there's no point in centering the "Years Used" and "Last Used" headers, which effectively set the maximum cell widths for their respective columns for all ten pop-up tables. The align attribute has been deprecated for most of the elements that could carry it (e.g., img, p, h#) but is, curiously, still legit for 'internal' table elements: tr, td/th, etc.

(4) Finally, the bolding or non-bolding of pop-up table rows is discussed in the "To bold or not to bold" section below.

Hmmm...do we need to go through a sample "here's what happens" for a pop-up table, now that we have the 2-D array thing under our belts? Let's briefly look at the Testing pop-up table,

The 'Testing' pop-up table ,

which is assembled by the outer loop's second (j = 1) iteration and whose td cells are respectively populated with the elements of the Text[1] child array:

//       Language     Years Last Used   Bold //       -----------  ----- ---------   ----     Text[1] = new Array(  "QA Partner (4Test)", 6, "Current", 1,  "DTM",                3, 1986,      0,  "WinRunner",        1/4, 1997,      0);

As noted earlier, the table's header row is written by the outer loop and the other rows are written by the inner loop. Here's a quick rundown on the inner loop action:

(1) First iteration: (i = 0): the Text[1][3] == 0 if condition returns false, so the else block bolds and then loads QA Partner (4Test) (Text[1][0]), 6 (Text[1][1]), and Current (Text[1][2]) into the cells of the second table row.

(2) Second iteration: (i = 4): the Text[1][7] == 0 if condition returns true, so the if block loads DTM (Text[1][4]), 3 (Text[1][5]), and 1986 (Text[1][6]) into the cells of the third table row but does not bold them.

(3) Third iteration: (i = 8): the Text[1][11] == 0 if condition returns true, so the if block loads WinRunner (Text[1][8]), 1/4 (Text[1][9], which is rendered as 0.25), and 1997 (Text[1][10]) into the cells of the fourth table row but does not bold them.

To bold or not to bold

As shown above, some of the pop-up table rows are bolded and some of them aren't. If there's a pattern to this bolding business, I don't see it; it doesn't seem to depend on the "Years Used" value, the "Last Used" value, or any combination thereof - for example, the Statistical pop-up table contains a bolded SAS | 8 | 1990 row whereas the Graphical pop-up table contains a non-bolded SAS/GRAPH | 8 | 1990 row. Given that the b element is a presentational element, and that the various CSS font properties apply to all elements and are inherited, a better row styling approach would be to
(a) subtract the else block's <b> and </b> tags and
(b) equip its tr element(s) with a class='lowerRow' identifier;
the lowerRow rows could then be given a font-weight: bold style or another style or no style at all, as desired.

Similarly, the b element of the initial display table's inner for loop

if (Text[i][j + 3] == 1) document.write("<b>" + Text[i][j] + "</b>");

can be replaced with a span element

if (Text[i][j + 3] == 1) document.write("<span class='languageStyle'>" + Text[i][j] + "</span>");

for maximum right-hand cell styling flexibility.

We're not quite done with the pop-up tables yet. In the following entry, we'll revisit in greater detail the script's eShow( ) and eHide( ) functions that respectively display and vanish the pop-up tables; we'll also discuss the script's problems with Netscape and how to fix them.

reptile7

Comments: Post a Comment

<< Home

Powered by Blogger

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