• Aucun résultat trouvé

Using JavaScript Functions with HTML Forms

Dans le document Guide to HTML, JavaScript and PHP (Page 153-161)

In a sense, all the previous material in this book has been directed toward this section. 

Why? Because the basic problem-solving model for the HTML/JavaScript environment is  to use JavaScript functions together with forms in HTML documents.

The function model described in the preceding section would be very simple except for  the fact that, in JavaScript, a value passed to a function through a parameter list can be one  of three distinctly different things: a value (a character string or number), a form field, or  an entire form. These are not interchangeable, and each must be treated differently. In  order to explain these differences, consider the simple problem of calculating the area of a  circle. Given a radius r:

= π 2 Area r

139 6.3 Using JavaScript Functions with HTML Forms

Recall that prompt() and alert() and document.write() methods provided  an I/O interface for these kinds of calculations in Chap. 4. Later in Chap. 4, some JavaScript  calculations were initiated as a result of using the onclick event handler in a button  field. These approaches were acceptable at the time, but they are too limited to be good  solutions for more complex problems. The following detailed analysis of several approaches  to implementing this simple calculation in a function may seem tedious and unnecessary  because the problem itself is so simple, but a thorough understanding of the analysis is  absolutely essential to successful JavaScript programming.

6.3.1

Passing Numerical Values to a Function

A JavaScript function to solve the problem of calculating the area of a circle is:

function getArea(r) {

return Math.PI*r*r;

}

The  parameter r  is  assumed  to  be  a  number  representing  the  radius  of  a  circle.  The   calculation  is  straightforward,  using  the PI  property  of  the Math  object  (Math.PI). 

There is no exponential operator in JavaScript (r2 can’t be represented as r^2 as it could  in a spreadsheet, for example), so r is just multiplied by itself.

It seems clear that you should be able to pass a value of the radius from a form field to  getArea(). However, previous examples in Chap. 4 have provided ample evidence that  caution is required! Consider this input element appearing within a form:

<form>

<input type="text" name="radius" maxlength ="6"

size="6" value="-99" />

...

What “value” can be passed from this form to the function? Recall that the name of the  field, radius in this case, is not the same as the value associated with this field. In this  context, it is important to make sure that a function receiving information through its input  parameter  list  understands  how  to  interpret  that  input.  Consider  Document  6.1,  which  shows  one  way  pass  information.  Passing radius  to getArea  will not  produce  the  desired result, nor will radius.value. Why not? Because radius is only the “value” 

of the name attribute, and radius.value is still only a character representation of the  required numerical input.

You  should  not  be  surprised  to  learn  that  the  calling  argument  to function getArea() should be parseFloat(radius.value), as shown in Document 6.1.

140 6 JavaScript Functions

6

Document 6.1 (circle1.htm)

<html>

<head>

<title>Circle Area (1)</title>

<script language="javascript" type ="text/javascript">

function getArea(r) { return Math.PI*r*r;

</script>}

</head>

<body>

<h1>Circle Area (1)</h1>

<p>

<form>

Enter radius, then press tab key or click on "area"

box.<br />

radius (cm):

<input type="text" name="radius" size="6" maxlength="7"

value="-99",

onblur = "area.value=getArea(parseFloat(radius.value));">

area (cm<sup>2</sup>):

<input type="text" name="area" size="6" maxlength="7"

value="-99">

</form>

</body>

</html>

In Document 6.1, function getArea(r) expects a numerical value equal to the  radius of the circle. The name of the function is appropriate to its purpose and is a name  unlikely to be associated with a variable name. The shaded line of code uses the onblur  event handler to “call” the function when the user clicks elsewhere on the document or  presses the Tab key. The value passed to function getArea(r) is parseFloat (radius.value) , which converts the value of the radius field from a string to a num-ber. Note that, in this case, the parseFloat() is not actually required because JavaScript  will  perform  an  appropriate  type  conversion, but  it  is much better  style  to  perform an  explicit type conversion whenever string values need to be interpreted as numbers.

141 6.3 Using JavaScript Functions with HTML Forms

The approach taken in Document 6.1 is called “pass by value.” Another option is to 

“pass by name.” The field name is provided as input to the function, which then must do  the job of converting the value attribute to a number, as shown in Document 6.2.

Document 6.2 (circle2.htm)

<html>

<head>

<title>Circle Area (2)</title>

<script language="javascript" type ="text/javascript">

function getArea(r) {

var radius=parseFloat(r.value);

return Math.PI*radius*radius;

</script>}

</head>

<body>

<h1>Circle Area (1)</h1>

<p>

<form>

Enter radius, then press tab key or click on "area"

box.<br />

radius (cm):

<input type="text" name="radius" size="6" maxlength="7"

value="-99", onblur = "area.value=getArea(radius);">

area (cm<sup>2</sup>):

<input type="text" name="area" size="6" maxlength="7"

value="-99">

</form>

</body></html>

There is no difference in the results produced by these two approaches, and either is accept-able as long as you are careful not to confuse a field name with its value. If you pass something  inappropriate to a function, such as a string value that isn’t converted to a numerical value, then  the function will generate a syntax error or return a result of NaN, for “not a number.”

There is another subtlety worth noting about using functions with forms. Consider this  modification of Document 6.1:

<script language="javascript" type="text/javascript">

// UNACCEPTABLE CHOICE FOR FUNCTION NAME!

function area(r) { return Math.PI*r*r;

</script>} ...<form>

142 6 JavaScript Functions

6

Enter radius, then press tab key or click on "area"

box.<br />

radius (cm):

<input type="text" name="radius" size="6"

maxlength="7" value="-99", onblur =

"area.value=area(parseFloat(radius.value));" />

area (cm<sup>2</sup>):

<input type="text" name="area" size="6"

maxlength="7" value="-99" />

...

In this code, the function name, area, is the same as a field name in the form. Although  one could envision a programming environment in which this conflict could be resolved  based on the context, this code will simply not work in JavaScript. So,

The names of functions should never be the same as the names of form input  fields.

6.3.2

Using Entire Forms as Input

There is yet another way to write a function that calculates the area of a circle. Consider  Document 6.3.

Document 6.3 (circle3.htm)

<html>

<head>

<title>Circle Area (4)</title>

<script language="javascript" type ="text/javascript">

function getArea(f) {

var r=parseFloat(f.radius.value);

f.area.value = Math.PI*r*r;

</script>}

</head>

<body>

<h1>Circle Area (3)</h1>

<form>

Enter radius, then press tab key or click on "area"

box.<br />

radius (cm):

143 6.3 Using JavaScript Functions with HTML Forms

<input type="text" name="radius" size="6"

maxlength="7" value="-99", onblur = "getArea(form);" />

area (cm<sup>2</sup>):

<input type="text" name="area" size="6"

maxlength="7" value="-99" />

</form>

</body>

</html>

In this version of function getArea(), the entire form (actually, just  information  about where the form is located in computer memory) is passed to the function, through  the parameter name f. There is no return  statement. How, then, is the result of the cal-culation made available to the area form field? The answer lies in these two statements:

var r=parseFloat(f.radius.value);

f.area.value = Math.PI*r*r;

The  first  statement  extracts  the  numerical  value  of  the  radius.  The  second  statement   modifies  not  the form  parameter  itself,  but  the value  property  of  one  of  its  fields.  

(It automatically converts the number back to text, too.) Note that this approach requires  the function to “know” the names of the fields in the form passed as input to the function. 

This is a major conceptual difference compared to the previous approaches. The fact that  the  form  and  the  JavaScript  function  are  linked  in  this  way  is  not  a  problem  for  self-  contained documents such as this. The only disadvantage is that it could limit the use of the  function in other scripts that use different field names for the same physical quantities.

In the previous discussion of JavaScript’s function model, it was clear that the parameter  list acted as a one-way path for input to be passed to a function, but it could not be used to  deliver output. Document 6.3 appears to violate this rule because the output has, in fact, been  delivered back to the form “through” the parameter f. However, this result does not, in fact,  compromise the model. When you pass a “value” to a function, you are actually passing  memory addresses telling the function where particular parameters are stored. The function is  allowed to make use of information stored at these addresses, but not to change the addresses  themselves.  Specifically,  when  the  location  of  a  form  is  passed  as  a  parameter,  what  the   function can do is modify the contents of fields stored in the form. This is what the

f.area.value = Math.PI*r*r;

statement does.

It is important to understand that the name f appearing in the function getArea(form)  has nothing to do with names used in the HTML document. This is a consequence of the 

“protected” environment created by a function definition, in which names defined within  the function are invisible to the rest of a document and script. In fact, it would be accept-able from JavaScript’s point of view to use form as a parameter name, although this might  not be a good choice as a matter of style.

144 6 JavaScript Functions

6

The ability of a function to modify fields within a form is important because it is one  way to circumvent the restriction that a return statement can return only a single value  as output. Suppose you wanted to calculate both the area and circumference of a circle. 

Does this require two separate functions? No. Consider Document 6.4.

Document 6.4 (circleStuff.htm)

<html>

<head>

<title>Circle Stuff</title>

<script language="javascript" type ="text/javascript">

function circleStuff(f) {

var r=parseFloat(f.radius.value);

f.area.value=Math.PI*r*r;

f.circumference.value=2*Math.PI*r;

</script>}

</head>

<body bgcolor="#99ccff">

<h1>Circle Stuff</h1>

<form>

Enter radius, then press tab key or click on "area"

box.<br />

radius (cm):

<input type="text" name="radius" size="6"

maxlength="7" value="-99", onblur = "circleStuff(form);" />

area (cm<sup>2</sup>):

<input type="text" name="area" size="6"

maxlength="7" value="-99" />

circumference(cm):

<input type="text" name="circumference" size="6"

maxlength="7" value="-99" />

</form>

</body>

</html>

145 6.3 Using JavaScript Functions with HTML Forms

Document  6.4  includes  an  additional  form  field  for  the  circumference,  calculated   in the

f.circumference.value=2*Math.PI*radius;

statement in circleStuff(). Both the area and the circumference are calculated within  the function, but no return statement is used.

It is not quite true that a function accepting a form name as a parameter must know the  values of all the <input... /> tag name attributes. Recall from Chap. 5 that all form  fields are available in an array called elements[] which is automatically created along  with a form. The following modification of the function in Document 6.4 will also work. 

It uses the elements[] array to access the form fields.

function circleStuff(f) {

var r=parseFloat(f.elements[0].value);

f.elements[1].value=Math.PI*r*r;

f.elements[2].value=2*Math.PI*r;

}

In this case, the function must still be aware of the physical meaning of each form field  as well as its position among the other fields.

It  is  important  to  understand  that  the  significance  of  Document  6.5  rests  on  its   demonstration of how to use a single function to generate more than one output value, to  circumvent the requirement that a function can return only a single value.

6.3.3

Using Arrays to Return Output Values

Yet another way to return multiple values from a function is to have the function return an  array, the elements of which contain the output values of interest. Document 6.5 shows how  to do this by presenting another version of the “circle stuff” code given in Document 6.4.

Document 6.5 (circleStuff2.htm)

<html>

<head>

<title>Circle Stuff with Arrays</title>

<script language="javascript" type ="text/javascript">

function circleStuff(r) { var A = Array();

A[0] = Math.PI*r*r;

A[1] = 2*Math.PI*r;

return A;

</script>}

</head>

146 6 JavaScript Functions

6

<body bgcolor="#99ccff">

<h1>Circle Stuff</h1>

<form>

Enter radius, then press tab key or click on "area" or

"circumference" field.<br />

radius (cm):

<input type="text" name="radius" size="6"

maxlength="7" value="-99", onblur = "var A = Array();

A = circleStuff(parseFloat(radius.value));

area.value = A[0]; circumference.value = A[1]; " />

area (cm<sup>2</sup>):

<input type="text" name="area" size="6"

maxlength="7" value="-99" />

circumference(cm):

<input type="text" name="circumference" size="6"

maxlength="7" value="-99" />

</form>

</body>

</html>

Of course, with this approach it is necessary for the programmer to keep track of which  output value is stored in which array element.

Dans le document Guide to HTML, JavaScript and PHP (Page 153-161)