reptile7's JavaScript blog
Thursday, December 23, 2010
 
TV Was King, Fee
Blog Entry #200

We continue today our discussion of HTML Goodies' "How to Populate Fields from New Windows Using JavaScript" tutorial. In this post we'll get into the guts of the help.html page that assists the user with the controls of the myForm form on the forms.html page.

After an introductory <h1>Help</h1> heading, the help.html document body comprises a series of sections that respectively offer help - in each case, information plus an interface that will indirectly set a value - for the various myForm controls except the . Here's the first of these sections, which deals with the Input #1 text field:

<h2 id="input1">Input #1</h2>
<p>In the input field labeled "Input #1," please put any information you like. This is not a required field.</p>
<script type="text/javascript"><!--
document.write('<form onsubmit="return false;">');
document.write('<label>Fill in input #1: <input type="text" name="myInput" value="Text."></' + 'label>');
document.write('<input type="button" onclick="input(\'myForm\', \'input1\', this.form.myInput.value);" value="Update">');
document.write('</' + 'form>');
//--></script>


The section begins with an Input #1 heading that doubles as a destination anchor for the ? help icon link that precedes the Input #1 text label on the forms.html page. After that we have a brief paragraph that clarifies the Input #1 field for the user. The meat of the section is a script that writes to the page a form holding two controls:
(1) an implicitly labeled, name="myInput" text field for entering a value; and
(2) an push button that when clicked triggers an input( ) function, which we'll get to shortly.

The script's form has been given an onsubmit="return false;" event handler so that the form cannot be submitted[, which] prevents users from doing anything malicious. Malicious?

The form doesn't have a submit button, although we know from HTML Goodies' "Submit The Form Using Enter" tutorial that if the user enters someValue into the myInput field and hits the enter/return key, then the form will be submitted...but to what? The form doesn't have an action attribute, whose value therefore 'resolves' to the URL of the current document, as we learned from our study of the "JavaScript Form Processor" example in HTML Goodies' "How to Use a JavaScript Query String Parser" tutorial. Also unspecified is the form's method attribute, which defaults to get. Putting it all together, form submission would reload the help.html page and append a ?myInput=someValue string containing the form's data set to the page's URL - a bit of a nuisance, perhaps, but hardly malicious.
(That said, I never cease to be amazed at what the 'sociopathic element' in the programming community can come up with, and you are invited to correct me if I'm wrong about this.)

We'll see in due course that the form container can be thrown out. Let's now look at the input( ) function called by the button:

function input(formName, obj, val) {
    opener.document.forms[formName].elements[obj].value = val;
    self.close( ); }


As shown above, the onclick input( ) function call passes three parameters to input( ):
(1) myForm;
(2) input1, the actual name of the Input #1 field; and
(3) this.form.myInput.value, the value that the user enters into the myInput field.
Via the input( ) declaration, these parameters are respectively given formName, obj, and val identifiers, which are plugged into a opener.document.forms[formName].elements[obj].value = val;* statement that loads the val value into the obj field. With the Input #1 field now "populated", a self.close( ); command subsequently closes help.html's window so the user can move on to the Input #2 field.

(*Ten Seventeen years down the line, Netscape's JavaScript 1.3 Client-Side Reference, now deemed "obsolete" by Mozilla, remains a good source of information on client-side objects and their properties/methods, and that's whose documentation I'm going to link to in this regard.)

The author's deconstruction of the input( ) assignment statement on the tutorial's second page includes the following cryptic comment:
By referring to forms[formName].elements[elementName] we can avoid using the eval( ) function. Using the eval( ) function would require more processing time than is necessary.
The eval( ) function is used to access values, and I don't see how it would be relevant to opener.document.forms[formName].elements[obj].value, as we are writing that expression's value and not reading it. However, we could indeed (but shouldn't) use eval( ) on the right side of the statement if we were to pass myInput as our arguments[2] to input( ) and then recast input( ) as:

function input(formName, obj, fieldName) {
    opener.document.forms[formName].elements[obj].value = eval("document.forms[0]." + fieldName + ".value");
    self.close( ); }


Mozilla rails against this type of construction as something that should be avoided whenever possible here.

The second and seventh help.html sections, which respectively assist the user with the Input #2 text field and the Input #7 textarea field, are very similar to the first help.html section. For the user's input, the second section writes out a name="myOtherInput" text field and the seventh section writes out a name="myTextarea" textarea field; each of these controls is again labeled, placed in an unsubmittable form, and paired with an button that calls and passes appropriate parameters to the input( ) function.

The remaining help.html sections use links for their interface elements.

• The third section provides the user with Option A, Option B, and Option C links

document.write('[Select an option: <a href="#" onclick="select(\'myForm\', \'input3\', 1); return false;">Option A<'
+ '/a>, <a href="#" onclick="select(\'myForm\', \'input3\', 2); return false;">Option B<'
+ '/a>, <a href="#" onclick="select(\'myForm\', \'input3\', 3); return false;">Option C<' + '/a>]');


that when clicked call a select( ) function

function select(formName, obj, idx) {
    opener.document.forms[formName].elements[obj].selectedIndex = idx;
    self.close( ); }


that sets the selectedIndex of the Input #3 selection list to a specified index: 1, 2, or 3 for choosing the list's Option A, Option B, or Option C, respectively. (Note that the list's first-in-source-order option reads ——Select one—— and has an underlying value of -1.)

• The fourth and fifth sections respectively provide the user with Choose input #4 and Choose input #5 links

document.write('[<a href="#" onclick="checkRadio(\'myForm\', \'inputRadio\', 0); return false;">Choose input #4<' + '/a>]');
...
document.write('[<a href="#" onclick="checkRadio(\'myForm\', \'inputRadio\', 1); return false;">Choose input #5<' + '/a>]');


that when clicked call a checkRadio( ) function

function checkRadio(formName, obj, choice) {
    opener.document.forms[formName].elements[obj][choice].checked = true;
    self.close( ); }


that checks the Input #4 or Input #5 radio button by setting its checked property to true. checkRadio( ) accesses these radio buttons by plugging 0 and 1 choice indexes into an opener.document.forms[formName].elements[obj][choice] expression. Netscape briefly discusses here the referencing of radio button sets and individual radio buttons.

• The sixth section differs from the others in that its output depends on the true/false return of a condition; specifically, this section provides the user with a Deselect input #6 or Choose input #6 link if the Input #6 checkbox is checked or not, respectively:

if (opener.document.myForm.inputCheck.checked) {
    document.write('[<a href="#" onclick="check(\'myForm\', \'inputCheck\', false);'
    + ' return false;">Deselect input #6<' + '/a>]'); }
else {
    document.write ('[<a href="#" onclick="check(\'myForm\', \'inputCheck\', true);'
    + ' return false;">Choose input #6<' + '/a>]'); }


Clicking the former or latter link triggers a check( ) function

function check(formName, obj, choice) {
    opener.document.forms[formName].elements[obj].checked = choice;
    self.close( ); }


that unchecks or checks the Input #6 checkbox by setting its checked property to false or true, respectively.

As noted earlier, no help section is provided for myForm's , but there's nothing stopping you from adding one if you'd like to do that:

function submitForm( ) {
    opener.document.myForm.submit( );
    self.close( ); }
...
<h2 id="input8">Submit Button</h2>
<p>Clicking this button will submit the form to our processing agent and direct you to a "Thank You!" page.</p>
<script type="text/javascript"><!--
document.write('<button type="button" onclick="submitForm( );">Submit the Form</button>');
//--></script>


Towards a cleaner help.html

As explained by the author, the section interface elements are written scriptically so as to not bother sans-JavaScript users with ineffectual fields and links, but be that as it may, when I first read through the help.html file, I thought, "Hmmm...commingling of HTML and JavaScript, the use of document.write( ) commands to output HTML, all that quote escaping...man, what ugly code this is." There must be some way to clean this thing up, huh? The least we could do is to externalize the interface scripts. Towards this end, we could functionize each interface

function writeText1( ) {
    document.write('<form onsubmit="return false;">');
    document.write('<label>Fill in input #1: <input type="text" name="myInput" value="Text."></label>');
    document.write('<input type="button" onclick="input(\'myForm\', \'input1\', this.form.myInput.value);" value="Update">');
    document.write('</form>'); }


and put those functions in an external controlScript.js file whose content would be retrieved by the help.html document head

<head>
<title>Help Window</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<script type="text/javascript" src="controlScript.js"></script>
</head>


allowing us to simplify each help section accordingly.

<h2 id="input1">Input #1</h2>
<p>In the input field labeled "Input #1," please put any information you like. This is not a required field.</p>
<script type="text/javascript">writeText1( );</script>


Validation note

You've probably noticed that the form/label/anchor element end-tags written by the help.html document.write( ) commands are all split after the </ end-tag open ("ETAGO") delimiter:

document.write('</' + 'form>');

The preceding formulation is one way (but not the W3C's recommended way) of dealing with the problem described in this section of the HTML 4.01 Specification. Without getting into the details, not splitting or otherwise escaping these tags should prematurely terminate the script elements that are writing them, which in practice doesn't happen with a typical browser but definitely happens with a validator, and that's (presumably) why the author did it. In any case, externalizing the document.write( ) commands obviates the need to split/escape the end-tags in their parameter strings.

We can do better than simply moving the original help.html user interfaces to another file, however. In the next entry, I'll discuss two other approaches to cleaning up the help.html code, plus we may get into the validation thing a bit more given that the forms.html and help.html documents both begin with a document type declaration.

reptile7

Sunday, December 12, 2010
 
Getoverture II
Blog Entry #199

In the previous post we introduced HTML Goodies' "How to Populate Fields from New Windows Using JavaScript" tutorial and we are ready to get our analysis thereof under way. We kick things off with an overview of the forms.html opener document.

forms.html

Structure

The forms.html document body comprises a name="myForm" form that holds a respectfully diverse collection of controls: two text fields, a four-option selection list, a pair of radio buttons, a checkbox, a textarea field, and a submit button.

[An image of the forms.html form]

Implicitly associated with each control element is a label element parent. Excluding that for the submit button, each label element contains (in addition to its associated control) an Input #[1-7] text label preceded by a square-bracketed question mark, [?], that will serve as a help icon and link us to the help.html remote control document. Here's the label/control code for the second text field:

<label>[<a href="help.html#input2" onclick="openWin(this.href); return false;" title="Help on filling out input #2.">?</a>]
Input #2 <input type="text" value="Value #2" name="input2"></label>


Finally, the form display is framed by a fieldset element and given a Dummy Form caption by a legend element.

Presentation

Let's temporarily turn to the style.css file that styles the forms.html page. The style.css style sheet is imported into forms.html by, appropriately, an @import rule:

<style type="text/css"><!-- @import "style.css"; --></style>

The forms.html label elements and textarea element are given block-level renderings via display:block; declarations. (Interactive or not, labels are extrinsic to a form's data set and consequently are not controls, although for the purpose of layout classification, the HTML 4.01 Strict and Transitional DTDs both put the label element in the %formctrl; group of elements, which is a subset of the %inline; group of elements.)

Interestingly, the forms.html document body is centered by (a) giving it a width that is less than the viewport width and (b) setting its margin-left and margin-right properties to auto:

body { width: 50%; margin: 10px auto; /* ...other declarations... */ }
/* Note that margin: 10px auto; is equivalent to: margin-top: 10px; margin-right: auto; margin-bottom: 10px; margin-left: auto; */


I've never seen this done before, but it makes sense, as it's the same approach we used to center a form in Blog Entry #93.

Setting a width for the body element effectively sets widths for the myForm form and its fieldset frame, as the form and fieldset elements are both block-level elements with effective widths of 100%. The label elements are centered within the fieldset (their "containing block") à la the body element. By default, label elements are "non-replaced inline elements" (see the "Applies to:" field of the aforelinked width property definition) and thus cannot ordinarily be given widths, but we've made them block-level elements here, so we're OK.

And for my fellow nitpickers:

(1) In choosing a typeface for the fieldset caption, the author initially sets the legend font-family to georgia, a serif font, and then switches to sans-serif for a generic backup. Why? Your guess is as good as mine.

(2) The input, select, textarea selector has two color declarations: the latter declaration, color:#3af*, "wins", i.e., is operative.
*color:#3af is equivalent to color:#33aaff.

Behavior

The style.css style sheet contains the following onmouseover-type rules:

a:hover { border-bottom: solid 1px #f90; }
label:hover { color: #39f; border-left: solid 5px #3af; padding-left: 10px; }


Mousing over each link (? help icon) changes its border-bottom color from #39f to #f90; more noticeably, mousing over each label changes its text color from #39a (this value is inherited from the body element) to #39f. More significantly, mousing over each label renders a thick, bluish border-left that highlights the label for the user:

[The Input #1 label and its border-left highlight]

Moreover, mousing over each link pops up a Help on filling out input #[1-7] tooltip via the link's title attribute.

The main behavioral aspect of the forms.html document, however, is the onclick="openWin(this.href); return false;" event handler that graces each help icon link, e.g.:

<a href="help.html#input1" onclick="openWin(this.href); return false;" title="Help on filling out input #1.">?</a>

For JavaScript-enabled users, clicking each link triggers the openWin( ) function in the forms.html document head and passes thereto this.href, the link's destination URL, which is given a page identifier by the openWin( ) declaration:

function openWin(page) {
var w = window.open(page, "", "menubar=no,history=no,resizable=yes,scrollbars=yes,toolbar=no,width=400,height=400"); }


openWin( ) opens a 400px-by-400px secondary window holding the page resource. FYI: Neither Mozilla nor Microsoft lists a history feature in its window.open( ) documentation.

For JavaScript-disabled users or users without JavaScript support ("sans-JavaScript users"), clicking each link loads the page resource into the current window via the link's href attribute - the return false; statement of the onclick event handler prevents this from happening for JavaScript-enabled users.

Each link's href value points to a help.html fragment that will assist the user with the link's associated control by providing
(a) information about the control, and
(b) one or more interface elements allowing the user to indirectly interact with the control.

help.html

We move now to the help.html remote control document. The entire help.html source is reproduced on the tutorial's first page, and a deconstruction for that source fills out the rest of the tutorial - a deconstruction that is a bit rough in places but is basically on target.

As implied by the last paragraph of the preceding section, the help.html document can be structurally subdivided into seven sections, one for each input-type control of the myForm form. Each section contains three parts:
(1) an Input #[1-7] h2 heading that also serves as a target anchor via its id attribute;
(2) a p element that gives information about the control; and
(3) a JavaScript script that writes out an interface via which the user can set a value for the control.

On the rendered help.html page, sans-JavaScript users see the (1) and (2) parts but not the (3) parts. Here's what JavaScript-enabled users get for part (3):

• For the Input #[1-2] text fields, the script interface comprises a labeled text field and an push button; analogously, a labeled, smaller-than-its-forms.html-counterpart textarea field and button compose the interface for the Input #7 textarea field. The user enters a value into a text field or the textarea field and then clicks the button, which triggers a function that transfers the entered value to the corresponding field in the opener document.

• For the Input #3 selection list, the script interface comprises a set of three links - Option A, Option B, and Option C - that correspond respectively to the Option A, Option B, and Option C options of the selection list. Clicking each link triggers a function that changes the selection list's current selection to that specified by the link.

• For the Input #[4-5] radio buttons, the script interface comprises a Choose input #[4-5] link that when clicked triggers a function that checks the appropriate radio button.

• For the Input #6 checkbox, the script interface depends on whether the checkbox is checked or unchecked. If the checkbox is unchecked, as is the case when forms.html first loads, then the help.html#input6 fragment displays a Choose input #6 link, whereas if the checkbox is checked, then the help.html#input6 fragment displays a Deselect input #6 link; clicking the former or latter link triggers a function that checks or unchecks the checkbox, respectively.
(N.B. This interface is not visible at the isolated help.html page as it is written by a conditional that throws an error in the absence of an opener document.)

We'll take a detailed look at - and hopefully improve - the help.html script interfaces and the functions they call in the next entry.

reptile7

Thursday, December 02, 2010
 
Quick Takes
Blog Entry #198

For a while there we were working through the tutorials in HTML Goodies' Beyond HTML : JavaScript sector in reverse order. We had reached "So, You Want A Background JavaScript, Huh?" before jumping up to tackle "A Quick Tutorial on JavaScript Variable Passing"; given below are brief descriptions of the next several tutorials we would encounter if we were to continue in sequence from "So, You Want A Background JavaScript, Huh?".

"Java vs. JavaScript: Similarities and Differences"

Authored by Joe Burns, "Java vs. JavaScript: Similarities and Differences" was one of the very first Beyond HTML : JavaScript tutorials: it appears in the Internet Archive's first (10 February 1999) snapshot of the sector. Per its title, "Java vs. JavaScript" takes a stab at comparing and contrasting Java and JavaScript, a topic you could probably write a small book on; it is a descriptive piece that unfortunately contains no code - Joe could have at least included some sample applet element HTML.

Two other complaints:

(1) The tutorial incorrectly states that both Java and JavaScript use the class data structure to create new objects: true for the former, false for the latter.

(2) If Joe is going to use the word "standalone" to describe a Java application, then he should briefly discuss running Java on the command line, but he doesn't. Relatedly, Joe says, Java applets run independent of the HTML document that is calling for them; this is true in the sense that the browser reads a page's HTML whereas it hands any applets off to a plug-in, but as <object>-type elements go, applets are really not so "independent": unlike embedded images and (iframe) documents, applets cannot be rendered outside of a document context - you can't double-click an applet .class file on the desktop and run it like a C executable, for example.

Mozilla compares JavaScript and Java in the Core JavaScript 1.5 Guide here.

"From DHTML to DOM Scripting [Part 1]" and Part 2

Authored by Christian Heilmann and excerpted from his book Beginning JavaScript with DOM Scripting and Ajax: From Novice to Professional, these articles discuss various JavaScript coding practices, e.g., script externalization, the use of feature detection, authoring with accessibility in mind, and the like. Part 1 moves along at an even pace; Part 2 escalates rapidly in complexity and will overwhelm most newbies. A helpful Summary section is provided at the end of Part 2.

The articles' title posits a false distinction between DHTML and the DOM: when you mutate a document on the fly via a DOM 'setter' operation, you are definitely engaging in DHTML. But don't take my word for it. Consider the append-a-link-to-a-parent-element code that appears in Part 2: the createElement( ), setAttribute( ), appendChild( ), and createTextNode( ) DOM Core methods employed by this code are all listed on Microsoft's DHTML Methods page.

"Browser Detect Script"

Credited to Dan Ragle and imported from WebReference.com, this tutorial presents a colossal, annotated browser-sniffing script - a script that is Exhibit A as to why everybody should code to the W3C's standards, and that's as much as I'm going to say about it.

"Using JavaScript Variables and Built-In Functions [Part 1]" and Part 2
"Writing Your Own JavaScript Functions [Part 1]" and Part 2

Authored by Dave Thau (a.k.a. thau!) and excerpted from his book The Book of JavaScript, 2nd Edition: A Practical Guide to Interactive Web Pages, these are very basic tutorials that really belong in HTML Goodies' JavaScript Primers sector. The "Using JavaScript Variables and Built-In Functions" articles cover variables, arithmetic operators, strings and string concatenation, the document.write( ) method, and the window.alert( ) method (at no point does thau! use the word "method" to classify document.write( ) and window.alert( ), nor does he identify alert( ) as a method of the window object). The "Writing Your Own JavaScript Functions" articles cover the creation of functions, function parameterization, function returns, and the use of local variables in functions.

The "Writing Your Own JavaScript Functions" articles veer into some embarrassingly dated territory. Part 1 works with an openAndCenterWindow( ) function whose body begins with a browser-sniffing conditional meant to flag Netscape 4+*. Even worse, the second page of Part 2 sports a "Dealing with Y2K" section offering code for dealing with the long-obsolete dateObject.getYear( ) method. (And this book was published in 2006.) thau!, if you're out there reading this, you might want to hook up with a better editor if or when you update your book again.

*BTW, upon throwing out the navigator.appVersion and navigator.appName tests, the rest of the openAndCenterWindow( ) code works just fine with MSIE 4.5 in the SheepShaver environment.

"Accessible JavaScripting From The Ground Up"

Authored by Stephen Philbin, this descriptive article is concerned with JavaScript-enhanced Web pages that malfunction for JavaScript-disabled users and how to avoid creating such pages; towards the latter, you are urged to
(a) implement JavaScript as a nonessential extra and
(b) make sure your Web page HTML displays smoothly for one and all before adding any JavaScript to it.

That brings us at last to "How to Populate Fields from New Windows Using JavaScript", which was authored by Jonathan Fenocchi and imported from WebReference.com. Earlier in the sector as part of a tour of the "Opening New Windows With JavaScript" set of tutorials, we checked over "Remote Control JavaScript", which presents a script that uses a secondary window to load new documents into an opener window. "How to Populate Fields from New Windows Using JavaScript" also fits the remote control paradigm, offering code that uses a secondary window to explain and set values for form controls in an opener document.

The "How to Populate Fields from New Windows Using JavaScript" code comprises three parts:
(1) a forms.html opener document;
(2) a style.css style sheet that applies various styles to the forms.html document; and
(3) a help.html remote control document.
A files2 folder containing these documents can be downloaded via the zip file link at the end of the Conclusion section on the tutorial's third page.

The files2 code is a bit of a chore to read through, but it works flawlessly. Links to a forms.html demo and its isolated help.html page are given on the first page of the tutorial; there's no link for the demo's style.css page - view it here. While we're on the subject of links, I should mention that the first page's learn more about opening new windows in JavaScript link to Martin Webb's "The JavaScript Pop-up Window Primer" is dead: the primer can still be read here.

Deconstruction-wise, the author doesn't discuss the forms.html and style.css code at all but provides a reasonably detailed analysis of the help.html code. We ourselves will not go through all of the code line by line but rather will paint a general picture, fill in some blanks, and perhaps suggest some coding alternatives. And as that might take a while, we are probably better off putting it off until the next entry.

reptile7


Powered by Blogger

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