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>');

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>');

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, 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

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

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.


Comments: Post a Comment

<< Home

Powered by Blogger

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