reptile7's JavaScript blog
Wednesday, August 15, 2007
 
Paint It Non-Black
Blog Entry #85

Deconstructing the Script Tips #65-67 Script's effect

We return now to the color creation script of HTML Goodies' JavaScript Script Tips #65-67. For the following discussion, let's assume that the user is browsing with MSIE4+. Here are our initial conditions:
• The background color of the first table row's cell is set to black (#000000).
• The Red, Green, and Blue selection lists all read 000 (in the menu string, the final 000 option element is equipped with a minimized selected attribute).
• The value in the text box at the end of the second table row is set to #000000.
Imagine it's nighttime, and you're in a room with the shades pulled down and the lights off. Pitch black. This is the starting point for additive color.

document.write("<select onchange='mix( );' size='1'>" + menu + "</select>");
<!-- name='red'|'green'|'blue' -->

Let there be light! The user chooses or does not choose an option from the Red, Green, and Blue menus. Each selection calls the script's mix( ) function via an onchange event handler.

function mix( ) {
if (document.all) {

The mix( ) function first tests if the browser supports the all collection (and we wouldn't have gotten this far if it didn't) - check.

document.all("box").style.background = "#" + document.ColorMix.red.options[document.ColorMix.red.selectedIndex].value +
document.ColorMix.green.options[document.ColorMix.green.selectedIndex].value
+ document.ColorMix.blue.options[document.ColorMix.blue.selectedIndex].value;

In much the same way that document.forms[ ] and document.images[ ] are arrays of a document's forms and images, respectively, the document all collection is an array of all of the elements in a document, including the html, head, and body elements and all elements in between. Like a document's forms and images, a document's all array elements can be indexed either with ordinal numbers (0, 1, 2, ...) or associatively with strings. In the left side of the statement above, document.all("box") references the document element whose id or name attribute value is box, i.e., the first table row's td element. As to why the Microsoft people decided to enclose the all index in parentheses and not in square brackets, well, your guess is as good as mine.

(An aside: the all collection is not only associated with the document object but can be used by any element that contains other elements. For example, consider a form named myForm comprising five radio buttons named myRadio: we can reference the third-in-source-order radio button with: document.myForm.all("myRadio", 2).)

The right side of the statement concatenates #, the value of the selected Red option, the value of the selected Green option, and the value of the selected Blue option. The resulting #RRGGBB string is then assigned to the value of the CSS background property of the box table cell.

Comments
• The options[ ] property of the select object, the selectedIndex property of the select object, and the value property of the option object were all introduced in the URL menu scripts of Script Tips #38-40, which we covered in Blog Entry #66.
• MSIE was the first browser to implement a style scripting object; MSDN's style object page is here.
The "shorthand" background property can be used to write individually or collectively CSS's various background properties (background-color, background-image, etc.).

document.ColorMix.code.value = "#" + document.ColorMix.red.options[document.ColorMix.red.selectedIndex].value + document.ColorMix.green.options[document.ColorMix.green.selectedIndex].value + document.ColorMix.blue.options[document.ColorMix.blue.selectedIndex].value;

Similarly, this statement assigns the #RRGGBB string to the value of the value property of the code control - i.e., the text box at the end of the second table row - in the ColorMix form.

Example: The user selects Red: 200, Green: 150, and Blue: 100. The mix( ) function combines the values of these options to give the hex code #c89664, which is loaded into the code text box and displays as a milk-chocolate color in the box table cell.

else {
alert("Sorry, your browser does not support the programming needed to run this script."); } }

As noted in the previous post, the script's initial display, and thus the ability to call the mix( ) function, has been 'conditioned out' for non-MSIE4+ users, who thus never see this alert( ) message, which is intended for them. Pretty sloppy design for an outfit calling itself "the Silicon Valley Garage".

The Script Tip #68 Script

The cross-browser Script Tip #68 Script can be accessed here and is demonstrated here. Here's how it differs from the Script Tips #65-67 Script:

(1) Joe first ditches (a) the two if (document.all) declarations and the { and } characters that delimit the if 'bodies' and (b) the else code in the mix( ) function - so far, so good. Strangely and quite unnecessarily, he then surrounds the menu option string and table/ColorMix document.write( ) commands with an always-true

var zork = 1;
if (zork == 1) { ... }

conditional; this silly code can and should be removed.

(2) The mix( ) function is moved to the end of the script. In Script Tip #68, Joe 'explains':
You have to flip the script upside down for NN [Netscape Navigator] to run it. You see, in order for NN to run hierarchy statements, the elements must already be loaded into the browser memory. In the case of the MSIE-only script, the commands came first and then the table was built. It's opposite here. First you have to build the table, then you can post the function.
Actually, both MSIE and Netscape will throw runtime errors if they encounter unfunctionized hierarchy statements containing identifiers for elements that appear subsequently in the source, BUT the statements in question here are in a function that is only called after the script document has loaded, and consequently the mix( ) move is unnecessary. Joe's to run hierarchy statements, the elements must already be loaded into the browser memory comment is correct as far as it goes, but merely loading into memory such statements in a function isn't 'running' them, and thus it's OK if they precede the element(s) they reference.

(3) Joe removes the box table cell and equips the body element start-tag with a bgcolor="000000" attribute. Next, he replaces the document.all("box").style.background expression on the left side of mix( )'s first assignment statement with document.bgColor so that the statement writes the document background color - fair enough, given Netscape's capabilities at the time the script was written.

A cross-browser Script Tips #65-67 Script

With some minor modifications, however, we can get the Script Tips #65-67 Script to work for Netscape 6+ and other current browsers exactly as it does for MSIE, as follows:

(1) As for the Script Tip #68 Script, let's first subtract the if (document.all) { } 'containers' and also mix( )'s else code.

(2) It has probably occurred to you that a document.all("elementID") expression is functionally equivalent to a document.getElementById("elementID") expression. Accordingly, in the mix( ) function we then replace document.all("box").style.background with document.getElementById("box").style.background.

And that'll do it, folks. Try it out:


(FYI: getElementById( ) is not at all a new method but was introduced in the DOM Level 1 HTML Specification, which 'went live' as a W3C Recommendation on 1 October 1998, but apparently the Script Tips #65-67 Script predates this.)

We'll wrap up our discussion of the Script Tips #65-68 Scripts in the next entry - we'll spiff up the code a bit and also look at a loop-based generation of the menu option string.

reptile7

Comments: Post a Comment

<< Home

Powered by Blogger

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