Looping Through Forms: Best Practice

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • David

    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.chec ked) do action A;
    if (checkbox2.chec ked) do action B;
    if (checkbox3.chec ked) 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(fo rm){

    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(docu ment.forms[0].elements[xIndex].value);
    tempy = parseFloat(docu ment.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
  • Richard Cornford

    #2
    Re: Looping Through Forms: Best Practice

    "David" <david.binner@w estburne.ca> wrote in message
    news:9bd00297.0 309221015.5d47f 69e@posting.goo gle.com...
    <snip>[color=blue]
    >var M = 20; //Global variable, MAX number of rows of A matrix.
    >var N = 2; //Global variable, number of columns of A matrix.[/color]

    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.
    [color=blue]
    >
    >function llsqpy4Solve(fo rm){[/color]

    "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.
    [color=blue]
    >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);[/color]

    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.
    [color=blue]
    >for (var i = 0; i < M; i++)
    > A[i] = new Array(N);[/color]

    Adding M two element arrays to A in this separate loop can be avoided. I
    will explain later.
    [color=blue]
    >
    >for (var i = 0; i < M; i++) {//Examine the 20 data fields
    > if (document.forms[0].elements[checkIndex].checked){[/color]

    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){
    ....
    [color=blue]
    > tempx = parseFloat(docu ment.forms[0].elements[xIndex].value);[/color]

    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.
    [color=blue]
    > tempy = parseFloat(docu ment.forms[0].elements[yIndex].value);
    > if (!isNaN(tempx) && !isNaN(tempy)){ //Both fields contain
    > //valid numbers
    > A[numRows][0] = tempx;
    > A[numRows][1] = tempy;
    > numRows++;[/color]

    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];
    [color=blue]
    > }//End if !isNaN
    > } // End if checkbox checked
    > checkIndex += 3;
    > xIndex += 3;
    > yIndex += 3;
    > }// End for i loop
    >
    > . . .
    >
    > }// End of function llsqpy4Solve[/color]

    So:-

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

    function llsqpy4Solve(fo rm){

    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.


    Comment

    • David

      #3
      Re: Looping Through Forms: Best Practice

      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

      Comment

      • Lasse Reichstein Nielsen

        #4
        Re: Looping Through Forms: Best Practice

        david.binner@we stburne.ca (David) writes:

        [color=blue][color=green]
        >> The optimum string to number type converting method is the unary plus
        >> operator:-[/color][/color]
        [color=blue]
        > I have about three Javascript books at home, but I have never come
        > across this feature.[/color]
        [color=blue]
        > Is this method new?[/color]

        Not all new.
        [color=blue]
        > Does it adhere to the ECMA standard? (I avoid functions that only
        > work on particular browsers.)[/color]

        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 - lrn@hotpop.com
        Art D'HTML: <URL:http://www.infimum.dk/HTML/randomArtSplit. html>
        'Faith without judgement merely degrades the spirit divine.'

        Comment

        • Dr John Stockton

          #5
          Re: Looping Through Forms: Best Practice

          JRS: In article <9bd00297.03092 30814.78033610@ posting.google. com>, seen
          in news:comp.lang. javascript, David <david.binner@w estburne.ca> posted
          at Tue, 23 Sep 2003 09:14:55 :-[color=blue]
          >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.[/color]


          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 }

          tempx = Read(oFrmElemen ts[xIndex].value)

          --
          © 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.demo n.co.uk/js-index.htm> JS maths, dates, sources.
          <URL:http://www.merlyn.demo n.co.uk/> TP/BP/Delphi/JS/&c., FAQ topics, links.

          Comment

          Working...