Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #15769 > unrolled thread

Re: How to do calculation with dynamic form field names?

Started byMike Winter <usenet@michael-winter.me.invalid>
First post2012-09-07 15:26 +0100
Last post2012-09-07 20:57 +0100
Articles 9 — 4 participants

Back to article view | Back to comp.lang.javascript

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: How to do calculation with dynamic form field names? Mike Winter <usenet@michael-winter.me.invalid> - 2012-09-07 15:26 +0100
    Re: How to do calculation with dynamic form field names? justaguy <lichunshen84@gmail.com> - 2012-09-07 08:03 -0700
      Re: How to do calculation with dynamic form field names? Gene Wirchenko <genew@ocis.net> - 2012-09-07 10:05 -0700
        Re: How to do calculation with dynamic form field names? justaguy <lichunshen84@gmail.com> - 2012-09-07 11:39 -0700
          Re: How to do calculation with dynamic form field names? SAM <stephanemoriaux.NoAdmin@wanadoo.fr.invalid> - 2012-09-07 21:56 +0200
      Re: How to do calculation with dynamic form field names? Mike Winter <usenet@michael-winter.me.invalid> - 2012-09-07 20:05 +0100
        Re: How to do calculation with dynamic form field names? justaguy <lichunshen84@gmail.com> - 2012-09-07 12:36 -0700
          Re: How to do calculation with dynamic form field names? justaguy <lichunshen84@gmail.com> - 2012-09-07 12:51 -0700
          Re: How to do calculation with dynamic form field names? Mike Winter <usenet@michael-winter.me.invalid> - 2012-09-07 20:57 +0100

#15769 — Re: How to do calculation with dynamic form field names?

FromMike Winter <usenet@michael-winter.me.invalid>
Date2012-09-07 15:26 +0100
SubjectRe: How to do calculation with dynamic form field names?
Message-ID<8un2s.290330$Lp7.53018@fx08.am4>
On 07/09/2012 05:07, justaguy wrote:

[snip]

> <form>
> <input type="text" id="item1">, <input type="text" id="qty1">, <input
> type="text" id="price1">, fieldX1 t1

[snip]

> a) t{n} = subtotal field.
> b) number of rows is unknown, it could be 1 to 30.
>
> What I'd like to do is: calculate subtotal and total.
> each subtotal = qty{n} * parseFloat(price{n})
>
> My attempt is to loop through the entire form, I'm able to retrieve
> all the values for the qty{n} field,
> but I don't know how to retrieve the value of its Corresponding
> Price{n}.

[snip]

What you're looking for is bracket notation; the ability to construct 
property names through string concatenation. This is described in the 
FAQ (and elaborated in the notes): 
<http://jibbering.com/faq/#propertyAccessAgain>

As you don't know the number of rows, you can leverage the fact that a 
nonexistent property will return null to simplify your loop (no need to 
use String.prototype.indexOf):

   var i = 0,
       element;

   // 'item' may be a better choice below if that's always
   // present in a row and 'qty' isn't, in which case the
   // condition below should become a null comparison instead
   // of an assignment expression/boolean type-conversion.
   while ((element = form.elements['qty' + i])) {
     var subtotal = form.elements['qty' + i]
       * form.elements['price' + i];
     // ...
     i++;
   }

Alternatively, you could of course inject a script element that contains 
a variable initialised with the number of rows when the page is generated.

Hope that helps,
-- 
Mike Winter
Replace ".invalid" with ".uk" to reply by e-mail.

[toc] | [next] | [standalone]


#15770

Fromjustaguy <lichunshen84@gmail.com>
Date2012-09-07 08:03 -0700
Message-ID<c40ba0e0-3f3a-4333-b9da-60949a55c236@n9g2000yqn.googlegroups.com>
In reply to#15769
On Sep 7, 10:26 am, Mike Winter <use...@michael-winter.me.invalid>
wrote:
> On 07/09/2012 05:07, justaguy wrote:
>
> [snip]
>
> > <form>
> > <input type="text" id="item1">, <input type="text" id="qty1">, <input
> > type="text" id="price1">, fieldX1 t1
>
> [snip]
>
> > a) t{n} = subtotal field.
> > b) number of rows is unknown, it could be 1 to 30.
>
> > What I'd like to do is: calculate subtotal and total.
> > each subtotal = qty{n} * parseFloat(price{n})
>
> > My attempt is to loop through the entire form, I'm able to retrieve
> > all the values for the qty{n} field,
> > but I don't know how to retrieve the value of its Corresponding
> > Price{n}.
>
> [snip]
>
> What you're looking for is bracket notation; the ability to construct
> property names through string concatenation. This is described in the
> FAQ (and elaborated in the notes):
> <http://jibbering.com/faq/#propertyAccessAgain>
>
> As you don't know the number of rows, you can leverage the fact that a
> nonexistent property will return null to simplify your loop (no need to
> use String.prototype.indexOf):
>
>    var i = 0,
>        element;
>
>    // 'item' may be a better choice below if that's always
>    // present in a row and 'qty' isn't, in which case the
>    // condition below should become a null comparison instead
>    // of an assignment expression/boolean type-conversion.
>    while ((element = form.elements['qty' + i])) {
>      var subtotal = form.elements['qty' + i]

Beautiful, Mike, many thanks.

Strange.  After I changed the script a bit to get subtotal value for
each row,

	 var i = 0, t=0,
		  element;
	   while ((element = forms[0].elements['qty' + i])) {
		 var subtotal = forms[0].elements['qty' + i] *
forms[0].elements['price' + i];
			 forms[0].elements['total' + i].value = subtotal;
			 t = t + parseFloat(subtotal);
			 alert(t);
		 // ...
		 i++;
   }

	forms[0].elements['totalFinal'].value = t;

I got the following error, attempted to use form reference of the
first form (there's only one form anyway),

"ReferenceError: forms is not defined"

Am I missing something here?

[toc] | [prev] | [next] | [standalone]


#15775

FromGene Wirchenko <genew@ocis.net>
Date2012-09-07 10:05 -0700
Message-ID<04ak48ls7n8nbasj13prbn9lc1vpmrv4a7@4ax.com>
In reply to#15770
On Fri, 7 Sep 2012 08:03:49 -0700 (PDT), justaguy
<lichunshen84@gmail.com> wrote:

[snip]
>each row,
>
>	 var i = 0, t=0,
>		  element;
>	   while ((element = forms[0].elements['qty' + i])) {
>		 var subtotal = forms[0].elements['qty' + i] *
>forms[0].elements['price' + i];
>			 forms[0].elements['total' + i].value = subtotal;
>			 t = t + parseFloat(subtotal);
>			 alert(t);
>		 // ...
>		 i++;
>   }
>
>	forms[0].elements['totalFinal'].value = t;
>
>I got the following error, attempted to use form reference of the
>first form (there's only one form anyway),
>
>"ReferenceError: forms is not defined"
>
>Am I missing something here?

     I think you need
          document.forms[0] ...
          ^^^^^^^^^
in front of the forms reference.

Sincerely,

Gene Wirchenko

[toc] | [prev] | [next] | [standalone]


#15777

Fromjustaguy <lichunshen84@gmail.com>
Date2012-09-07 11:39 -0700
Message-ID<cba9bfae-6484-474f-93b8-f40209be5c8e@u19g2000yqo.googlegroups.com>
In reply to#15775
On Sep 7, 1:05 pm, Gene Wirchenko <ge...@ocis.net> wrote:
> On Fri, 7 Sep 2012 08:03:49 -0700 (PDT), justaguy
>
> <lichunshe...@gmail.com> wrote:
>
> [snip]
>
>
>
>
>
>
>
>
>
> >each row,
>
> >     var i = 0, t=0,
> >              element;
> >       while ((element = forms[0].elements['qty' + i])) {
> >             var subtotal = forms[0].elements['qty' + i] *
> >forms[0].elements['price' + i];
> >                     forms[0].elements['total' + i].value = subtotal;
> >                     t = t + parseFloat(subtotal);
> >                     alert(t);
> >             // ...
> >             i++;
> >   }
>
> >    forms[0].elements['totalFinal'].value = t;
>
> >I got the following error, attempted to use form reference of the
> >first form (there's only one form anyway),
>
> >"ReferenceError: forms is not defined"
>
> >Am I missing something here?
>
>      I think you need
>           document.forms[0] ...
>           ^^^^^^^^^
> in front of the forms reference.
>
> Sincerely,
>
> Gene Wirchenko

Thanks alot.  That helps.  Now, the alert(t) line does not return
alert.  I added another alert as the first line for the loop and it
does not return alert neither.  How's wrong?  Firefox 15 with Firebug.

[toc] | [prev] | [next] | [standalone]


#15781

FromSAM <stephanemoriaux.NoAdmin@wanadoo.fr.invalid>
Date2012-09-07 21:56 +0200
Message-ID<504a516d$0$21255$ba4acef3@reader.news.orange.fr>
In reply to#15777
Le 07/09/12 20:39, justaguy a écrit :
> On Sep 7, 1:05 pm, Gene Wirchenko <ge...@ocis.net> wrote:
>> On Fri, 7 Sep 2012 08:03:49 -0700 (PDT), justaguy
>>
>> <lichunshe...@gmail.com> wrote:
>>
>> [snip]



function t(el) {            // el = one of the quantity inputs
var f = el.form,            // in which form are we ?
     n = f.elements.length,  // how many elements are there ?
     z = 0,
     p = 0,                 // sub-total
     s = 0;                 // total
// if the quantity is greater than zero
if(el.value>0) {
    // we will calculate each row whith a loop thru all elements
    while(n--)
    if( f[n] && f[n].name.indexOf('qty')>=0) {
       // we get that row
       el = f[n].parentNode;
       while (el.tagName.toLowerCase() != 'tr') el = el.parentNode;
       // collection of textfields of the row
       el = el.getElementsByTagName('INPUT'); z = el.length;
       // calcul the row
       el[z-1].value = p = el[z-2].value *  el[z-3].value;
       // add result to the total
       s += p*1;
      }
    // finaly complete the textfield 'total'
    f['total'].value = s;
    }
}


<form>
<table>
<tr>
   <td>Article 1:</td>
   <td><input value="15.25"></td>
   <td> * <input name="qty[]"></td>
   <td> = <input name="subTotal[]"></td>
</tr>
<tr>
   <td>Article 2:</td>
   <td><input value="15.25"></td>
   <td> * <input name="qty[]" onblur="t(this)"></td>
   <td> = <input name="subTotal[]"></td>
</tr>
<tr>
    <td colspan="3">total : </td>
    <td><input name="total"></td>
</tr>
</table>
</form>



We certainly could do the loop with the rows of the table

function t(el) {                        // el = quantity input
var f = el.form,                        // in which form are we ?
     r = f.getElementsByTagName('TR'),   // collection of rows
     n = r.length,                       // how many rows ?
     p = 0,                 // sub-total
     s = 0;                 // total
// if the quantity is greater than zero
if(el.value>0) {
    // we will calculate each row whith a loop thru rows
    while(n--)
       {
       // we get the inputs of that row
       el = r[n].getElementsByTagName('INPUT'); z = el.length;
       if(z==3) {
          el[z-1].value = p = el[z-2].value *  el[z-3].value;
          // add result to the total
          s += p*1;
          }
       }
    // finaly we complete the textfield 'total'
    f['total'].value = s;
    }
}


-- 
Stéphane Moriaux avec/with iMac-intel

[toc] | [prev] | [next] | [standalone]


#15778

FromMike Winter <usenet@michael-winter.me.invalid>
Date2012-09-07 20:05 +0100
Message-ID<Tzr2s.523194$6h3.7439@fx25.am4>
In reply to#15770
On 07/09/2012 16:03, justaguy wrote:

> On Sep 7, 10:26 am, Mike Winter <use...@michael-winter.me.invalid>
> wrote:
>> On 07/09/2012 05:07, justaguy wrote:
>>
>> [snip]
>>
>>> <form>
>>> <input type="text" id="item1">, <input type="text" id="qty1">, <input
>>> type="text" id="price1">, fieldX1 t1

[snip]

> Strange.  After I changed the script a bit to get subtotal value for
> each row,
>
>   var i = 0, t=0,

Here, i should've been initialised to 1: the first row has a "qty1", not 
a "qty0". This was an oversight on my part.

>     element;
>   while ((element = forms[0].elements['qty' + i])) {

As Gene pointed out, you cannot just use "forms" as-is. With the code I 
originally posted. the simple adaptation would be to declare and 
initialise form:

   var form = document.forms[0];

I didn't include it as that might not be the best way to obtain that 
reference. If your function is called from the form element's submit or 
the button's click event handler, then:

   <form ... onsubmit="return calculateTotal(this.form);">

   function calculateTotal(form) {
     // ...

would be better. Regardless, using a single reference has the advantage 
of avoiding repeated property references and, in my opinion at least, 
improving readability.

>     var subtotal = forms[0].elements['qty' + i] *
>       forms[0].elements['price' + i];
>     forms[0].elements['total' + i].value = subtotal;
>     t = t + parseFloat(subtotal);

   t += subtotal;

The subtotal variable will already be a floating-point number as the 
multiplication operator attempts to type-convert strings to numbers 
automatically. There's no need to call parseFloat here. If you're 
concerned with values not being numbers, you need to be validating those 
values.

[snip]

> Am I missing something here?

Hopefully that's cleared up a few things.
Kind regards,
-- 
Mike Winter
Replace ".invalid" with ".uk" to reply by e-mail.

[toc] | [prev] | [next] | [standalone]


#15779

Fromjustaguy <lichunshen84@gmail.com>
Date2012-09-07 12:36 -0700
Message-ID<8999254d-5896-4ba3-becd-ae08c3b242d0@v15g2000yqi.googlegroups.com>
In reply to#15778
On Sep 7, 3:05 pm, Mike Winter <use...@michael-winter.me.invalid>
wrote:
> On 07/09/2012 16:03, justaguy wrote:
>
> > On Sep 7, 10:26 am, Mike Winter <use...@michael-winter.me.invalid>
> > wrote:
> >> On 07/09/2012 05:07, justaguy wrote:
>
> >> [snip]
>
> >>> <form>
> >>> <input type="text" id="item1">, <input type="text" id="qty1">, <input
> >>> type="text" id="price1">, fieldX1 t1
>
> [snip]
>
> > Strange.  After I changed the script a bit to get subtotal value for
> > each row,
>
> >   var i = 0, t=0,
>
> Here, i should've been initialised to 1: the first row has a "qty1", not
> a "qty0". This was an oversight on my part.
>
> >     element;
> >   while ((element = forms[0].elements['qty' + i])) {
>
> As Gene pointed out, you cannot just use "forms" as-is. With the code I
> originally posted. the simple adaptation would be to declare and
> initialise form:
>
>    var form = document.forms[0];
>
> I didn't include it as that might not be the best way to obtain that
> reference. If your function is called from the form element's submit or
> the button's click event handler, then:
>
>    <form ... onsubmit="return calculateTotal(this.form);">
>
>    function calculateTotal(form) {
>      // ...
>
> would be better. Regardless, using a single reference has the advantage
> of avoiding repeated property references and, in my opinion at least,
> improving readability.
>
> >     var subtotal = forms[0].elements['qty' + i] *
> >       forms[0].elements['price' + i];
> >     forms[0].elements['total' + i].value = subtotal;
> >     t = t + parseFloat(subtotal);
>
>    t += subtotal;
>
> The subtotal variable will already be a floating-point number as the
> multiplication operator attempts to type-convert strings to numbers
> automatically. There's no need to call parseFloat here. If you're
> concerned with values not being numbers, you need to be validating those
> values.
>
> [snip]
>
> > Am I missing something here?
>
> Hopefully that's cleared up a few things.
> Kind regards,
> --
> Mike Winter
> Replace ".invalid" with ".uk" to reply by e-mail.

Many thank, Mike.  I was a bit careless myself.
Here's the code that works except that I have a checkbox dynamic field
name starting with
"Remove_" keyword, I attempted to determine if some of such checkbox
has been checked with
the following line of code to no effect,
document.forms[0].elements['Remove_' + i]
or
document.forms[0].elements['Remove_' + i].checked // this line threw
an error.
To remove/subtract the subtotal from such row(s).


var i = 1, t=0,
		  element;
	   while ((element = document.forms[0].elements['qty' + i])) {
		 var subtotal = document.forms[0].elements['qty' + i].value *
document.forms[0].elements['priceLabel' + i].value;
			 // alert(subtotal);
			 document.forms[0].elements['total' + i].value = subtotal;
			 t = t + subtotal;

			 if (document.forms[0].elements['Remove_' + i]) {
				t = t - subtotal;
				}

			 //alert(t);
			 document.forms[0].elements['totalFinal'].value = t;

		 i++;
   }

[toc] | [prev] | [next] | [standalone]


#15780

Fromjustaguy <lichunshen84@gmail.com>
Date2012-09-07 12:51 -0700
Message-ID<117baeeb-bb31-4b2d-a11d-01ef7ef5eeb0@l14g2000yqo.googlegroups.com>
In reply to#15779
On Sep 7, 3:36 pm, justaguy <lichunshe...@gmail.com> wrote:
> On Sep 7, 3:05 pm, Mike Winter <use...@michael-winter.me.invalid>
> wrote:
>
>
>
>
>
>
>
>
>
> > On 07/09/2012 16:03, justaguy wrote:
>
> > > On Sep 7, 10:26 am, Mike Winter <use...@michael-winter.me.invalid>
> > > wrote:
> > >> On 07/09/2012 05:07, justaguy wrote:
>
> > >> [snip]
>
> > >>> <form>
> > >>> <input type="text" id="item1">, <input type="text" id="qty1">, <input
> > >>> type="text" id="price1">, fieldX1 t1
>
> > [snip]
>
> > > Strange.  After I changed the script a bit to get subtotal value for
> > > each row,
>
> > >   var i = 0, t=0,
>
> > Here, i should've been initialised to 1: the first row has a "qty1", not
> > a "qty0". This was an oversight on my part.
>
> > >     element;
> > >   while ((element = forms[0].elements['qty' + i])) {
>
> > As Gene pointed out, you cannot just use "forms" as-is. With the code I
> > originally posted. the simple adaptation would be to declare and
> > initialise form:
>
> >    var form = document.forms[0];
>
> > I didn't include it as that might not be the best way to obtain that
> > reference. If your function is called from the form element's submit or
> > the button's click event handler, then:
>
> >    <form ... onsubmit="return calculateTotal(this.form);">
>
> >    function calculateTotal(form) {
> >      // ...
>
> > would be better. Regardless, using a single reference has the advantage
> > of avoiding repeated property references and, in my opinion at least,
> > improving readability.
>
> > >     var subtotal = forms[0].elements['qty' + i] *
> > >       forms[0].elements['price' + i];
> > >     forms[0].elements['total' + i].value = subtotal;
> > >     t = t + parseFloat(subtotal);
>
> >    t += subtotal;
>
> > The subtotal variable will already be a floating-point number as the
> > multiplication operator attempts to type-convert strings to numbers
> > automatically. There's no need to call parseFloat here. If you're
> > concerned with values not being numbers, you need to be validating those
> > values.
>
> > [snip]
>
> > > Am I missing something here?
>
> > Hopefully that's cleared up a few things.
> > Kind regards,
> > --
> > Mike Winter
> > Replace ".invalid" with ".uk" to reply by e-mail.
>
> Many thank, Mike.  I was a bit careless myself.
> Here's the code that works except that I have a checkbox dynamic field
> name starting with
> "Remove_" keyword, I attempted to determine if some of such checkbox
> has been checked with
> the following line of code to no effect,
> document.forms[0].elements['Remove_' + i]
> or
> document.forms[0].elements['Remove_' + i].checked // this line threw
> an error.
> To remove/subtract the subtotal from such row(s).
>
> var i = 1, t=0,
>                   element;
>            while ((element = document.forms[0].elements['qty' + i])) {
>                  var subtotal = document.forms[0].elements['qty' + i].value *
> document.forms[0].elements['priceLabel' + i].value;
>                          // alert(subtotal);
>                          document.forms[0].elements['total' + i].value = subtotal;
>                          t = t + subtotal;
>
>                          if (document.forms[0].elements['Remove_' + i]) {
>                                 t = t - subtotal;
>                                 }
>
>                          //alert(t);
>                          document.forms[0].elements['totalFinal'].value = t;
>
>                  i++;
>    }


The following line does the trick.  Problem resolved.  Many thanks.

 if (document.forms[0].elements['Remove_' + i] &&
document.forms[0].elements['Remove_' + i].checked) {
				t = t - subtotal;
				}

[toc] | [prev] | [next] | [standalone]


#15782

FromMike Winter <usenet@michael-winter.me.invalid>
Date2012-09-07 20:57 +0100
Message-ID<Wks2s.295006$Xu5.65204@fx10.am4>
In reply to#15779
On 07/09/2012 20:36, justaguy wrote:

> On Sep 7, 3:05 pm, Mike Winter <use...@michael-winter.me.invalid>
> wrote:
 >
> [snip]
 >
>> If your function is called from the form element's submit or
>> the button's click event handler, then:
>>
>>     <form ... onsubmit="return calculateTotal(this.form);">

Sorry, I'm obviously not thinking clearly today. With a form, the value 
passed would be simply the object referenced by the this keyword. With a 
form control, it would be the expression, this.form

[snip]

> Here's the code that works except that I have a checkbox dynamic field
> name starting with
> "Remove_" keyword, I attempted to determine if some of such checkbox
> has been checked with
> the following line of code to no effect,
> document.forms[0].elements['Remove_' + i]
> or
> document.forms[0].elements['Remove_' + i].checked // this line threw
> an error.

That expression would only produce an error if the control didn't exist. 
Are these checkboxes present in every row? If not, you'll need to test 
for both the presence of the control and whether it's checked:

   var skipRowCheckbox = form.elements['Remove_' + i];
   if (skipRowCheckbox && skipRowCheckbox.checked) {
      t -= subtotal;
   }

Or to reverse the logic, so that the subtotal is only increased if there 
is no checkbox, or there is but it's unchecked:

   var skipRowCheckbox = form.elements['Remove_' + i];
   if (!skipRowCheckbox || !skipRowCheckbox.checked) {
      t += subtotal;
   }

[snip]

-- 
Mike Winter
Replace ".invalid" with ".uk" to reply by e-mail.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.javascript


csiph-web