473,385 Members | 1,766 Online

# Looping Through Forms: Best Practice

Hello.

I am looking for advice on what is "best practice" regarding looping
through a form to check its checkboxes and associated data fields.

Here is what I am trying to do (Here is the page I am working on:
http://www3.telus.net/thothworks/LinLeastSqPoly4.html).
I provide a form for a user to enter up to twenty (M = 20) data pairs.
The user need not enter data for all twenty pairs, but
the user must indicate that data is present by checking the checkbox
beside each valid pair.

If a checkbox is checked, two things happen:
i) a counter, numRows, is incremented to keep track of the total
number of valid pairs entered.
ii) the associated two data values (being x and y) are checked to
ensure that they are valid numbers and, if so, are entered in an array
for use later.

Previously, my forms were small, and I was able to examine each
checkbox of a form individually:
"if (checkbox1.checked) do action A;
if (checkbox2.checked) do action B;
if (checkbox3.checked) do action C;
etc."

However, now that my form has twenty checkboxes, and may get bigger, I
would like to learn how to accomplish this task with a concise loop.
Following is my first attempt and it seems to work. If anyone can
suggest improvements for this code, or even a better/different way to
achieve the goal, that would be appreciated.

=================

var M = 20; //Global variable, MAX number of rows of A matrix.
var N = 2; //Global variable, number of columns of A matrix.

function llsqpy4Solve(form){

var numRows = 0; // Total number of valid data pairs input
var checkIndex = 0; // Form index for checkboxes
var xIndex = 1; // Form index for x data field
var yIndex = 2; // Form index for y data field
var tempx, tempy; //Dummy variables

var A = new Array(M);

for (var i = 0; i < M; i++)
A[i] = new Array(N);

for (var i = 0; i < M; i++) {//Examine the 20 data fields
if (document.forms[0].elements[checkIndex].checked){
tempx = parseFloat(document.forms[0].elements[xIndex].value);
tempy = parseFloat(document.forms[0].elements[yIndex].value);
if (!isNaN(tempx) && !isNaN(tempy)){ //Both fields contain valid
numbers
A[numRows][0] = tempx;
A[numRows][1] = tempy;
numRows++;
}//End if !isNaN
} // End if checkbox checked
checkIndex += 3;
xIndex += 3;
yIndex += 3;
}// End for i loop

.. . .

}// End of function llsqpy4Solve
Jul 20 '05 #1
4 4858
"David" <da**********@westburne.ca> wrote in message
<snip>
var M = 20; //Global variable, MAX number of rows of A matrix.
var N = 2; //Global variable, number of columns of A matrix.
I don't see any reason for N being a global variable (or a variable at
all) as you have hard coded the number of fields being read by the
function as two so you may as well replace all references to N within
the function with the number 2.

function llsqpy4Solve(form){
"form" may not be the best name to give to this parameter (maybe oForm)
as it is usually best to avoid identifiers that correspond with DOM
object properties such as the "form" property of form elements (like
the - this.form - that is passed to this function. However, this
parameter identifier is invisible outside of this function so using this
name will not actually case problems.
var numRows = 0; // Total number of valid data pairs input
var checkIndex = 0; // Form index for checkboxes
var xIndex = 1; // Form index for x data field
var yIndex = 2; // Form index for y data field
var tempx, tempy; //Dummy variables

var A = new Array(M);
There is not need to provide a dimension for the Array constructor,
doing so is harmless but not doing so may have advantages. You might
consider using Array literal syntax when creating arrays, - var A =
[]; - as it is slightly less bytes to download.
for (var i = 0; i < M; i++)
A[i] = new Array(N);
Adding M two element arrays to A in this separate loop can be avoided. I
will explain later.

for (var i = 0; i < M; i++) {//Examine the 20 data fields
if (document.forms[0].elements[checkIndex].checked){
You have passed this function a reference to the form object (the "form"
parameter) so there is no need to re-resolve the reference to the form
each time you access one of its elements (60 times). You could use -
form.elements[checkIndex].checked - but I would be inclined to avoid
re-resolving the reference to the elements collection as well by
creating another local variable that referred to that and using it to
reference the elements:-

var oFrmElements = fome.elements;
....
if(oFrmElements[checkIndex].checked){
....
tempx = parseFloat(document.forms[0].elements[xIndex].value);
The optimum string to number type converting method is the unary plus
operator:-

tempx = (+oFrmElements[xIndex].value);

- it is about 4 times faster than parseFloat and still produces NaN
results if the string cannot be converted into a number.

You could still be indexing the elements collection by name, using a
string that represents the start of the name and concatenating the for
loop counter:-

tempx = (+oFrmElements['x'+i].value);

- removing the need to have checkIndex, xIndex and yIndex as local
variables and allowing additional elements to be added to the form
before the required fields without requiring the re-writing of the
function. Though the for loop counter would have to start at 1 and count
to <= M.
tempy = parseFloat(document.forms[0].elements[yIndex].value);
if (!isNaN(tempx) && !isNaN(tempy)){ //Both fields contain
//valid numbers
A[numRows][0] = tempx;
A[numRows][1] = tempy;
numRows++;
You can add the two element arrays as elements of A at this point. If A
had not been pre-dimensioned to M elements you could add elements at
A.length and avoid the need for a numRows local variable, later reading
A.length when you needed to know how many items had been assigned to the
array:-

A[A.length] = [tempx, tempy];
}//End if !isNaN
} // End if checkbox checked
checkIndex += 3;
xIndex += 3;
yIndex += 3;
}// End for i loop

. . .

}// End of function llsqpy4Solve

So:-

var M = 20; //Global variable, MAX number of rows of A matrix.

function llsqpy4Solve(form){

var oFrmElements = form.elements;
var tempx, tempy, A = [];

for (var i = 1; i <= M; i++) {//Examine the 20 data fields
if (oFrmElements['p'+i].checked){
tempx = (+oFrmElements['x'+i].value);
tempy = (+oFrmElements['y'+i].value);
if (!isNaN(tempx) && !isNaN(tempy)){ //Both fields contain
// valid numbers
A[A.length] = [tempx, tempy];
}//End if !isNaN
} // End if checkbox checked
}// End for i loop

....

}// End of function llsqpy4Solve

Richard.
Jul 20 '05 #2
Thank-you, Richard.

You have given me a lot of good advice.

One suggestion that you made completely surprised me:

******
The optimum string to number type converting method is the unary plus
operator:-

tempx = (+oFrmElements[xIndex].value);

- it is about 4 times faster than parseFloat and still produces NaN
results if the string cannot be converted into a number.
******

I have about three Javascript books at home, but I have never come
across this feature. Is this method new? Does it adhere to the ECMA
standard? (I avoid functions that only work on particular browsers.)

Once again, thanks for your help. Those were exactly the sorts of
suggestions I was looking for.
David
Jul 20 '05 #3
da**********@westburne.ca (David) writes:

The optimum string to number type converting method is the unary plus
operator:-
I have about three Javascript books at home, but I have never come
across this feature. Is this method new?
Not all new.
Does it adhere to the ECMA standard? (I avoid functions that only
work on particular browsers.)

It does. ECMA says:
---
11.4.6 Unary + Operator
The unary + operator converts its operand to Number type.

The production UnaryExpression : + UnaryExpression is evaluated as follows:

1. Evaluate UnaryExpression.
2. Call GetValue(Result(1)).
3. Call ToNumber(Result(2)).
4. Return Result(3).
----

It won't work in all browsers (e.g., Netscape 2 and 3), but it seems to
work in modern browsers (Netscape 4, Opera 4+). I can't check old IE's,
but I would guess IE 3 could have a problem.

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
Art D'HTML: <URL:http://www.infimum.dk/HTML/randomArtSplit.html>
'Faith without judgement merely degrades the spirit divine.'
Jul 20 '05 #4
JRS: In article <9b**************************@posting.google.com >, seen
in news:comp.lang.javascript, David <da**********@westburne.ca> posted
at Tue, 23 Sep 2003 09:14:55 :-
Thank-you, Richard.

You have given me a lot of good advice.

One suggestion that you made completely surprised me:

******
The optimum string to number type converting method is the unary plus
operator:-

tempx = (+oFrmElements[xIndex].value);

- it is about 4 times faster than parseFloat and still produces NaN
results if the string cannot be converted into a number.

Nevertheless, one must be careful. I find that
parseFloat('0x1') differs from +'0x1'
parseFloat('') differs from +''
Richard has, I think, given the fastest and best way of converting a
string with optional sign then all digits.

But for converting input from the user via a text control, unary + will
be fastest, but the best should be something with checks, like :

function Read(S, Q) {
if (/^[-+]?\d+\$/.test(S)) return +S
alert(Q) ; return NaN }

--
© John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 IE 4 ©
<URL:http://jibbering.com/faq/> Jim Ley's FAQ for news:comp.lang.javascript
<URL:http://www.merlyn.demon.co.uk/js-index.htm> JS maths, dates, sources.
<URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/JS/&c., FAQ topics, links.
Jul 20 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.