SitePoint Sponsor

User Tag List

Results 1 to 12 of 12
  1. #1
    SitePoint Wizard wheeler's Avatar
    Join Date
    Mar 2006
    Location
    Gold Coast, Australia
    Posts
    1,369
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    passing the name of a dynamic array of checkboxes

    I'm having a bit of a problem with some javascript. I have a couple of functions that update text fields to show the total value of the selected items. There are 3 relevant fields, sub_total, tax and total. There is also an infinite amount of checkboxes which share the same name to create an array.

    Code:
    <input type=\"checkbox\" name=\"id[$id]\" value=\"$id\" checked=\"checked\" onclick=\"return update(this.form, $amount, this.name);\" />
    * note this is echoed from php.

    The idea is that when a checkbox is checked the total will update. Checked = add to total, unchecked = subtract from total. While I have the updating part working, it seems that I can't pass the correct checkbox name to the update function, hence the if statement always fails and subtracts even when I want it to add.

    I have tried adding a key to the array name, but it doesn't make any difference, the if statement always returns false. I'm pretty sure it's due to my lack of knowledge rather than any restraints in javascript itself...

    Code JavaScript:
    function calcSubTax(form) 
    {
    	var subTotal = (form.sub_total.value != '') ? eval(form.sub_total.value) : 0;
    	var tax = Math.round((subTotal * 0.1) * 100) / 100;
     
    	form.tax.value = tax;
    	form.total.value = Math.round((subTotal + tax) * 100) / 100;
    }
     
     
    function update(form, amount, name)
    {
    	var current_total = form.sub_total.value;
     
    	// if checking, add to the total
    	if (name.checked == 1)
    	{
        	new_total = current_total + amount;
    	// else subtract
     	} else {
        	new_total = current_total - amount;
    	}
     
    	form.sub_total.value = Math.round(new_total);
    	calcSubTax(form);
    }
    any ideas?
    Studiotime - Time Management for Web Developers
    to-do's, messages, invoicing, reporting - 30 day free trial!
    Thomas Multimedia Web Development

  2. #2
    SitePoint Wizard Pepejeria's Avatar
    Join Date
    Jan 2005
    Location
    Too far up north
    Posts
    1,566
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You have to pass this and not this.name to the update function.

    Also, why the return when calling update? Not necessary.

  3. #3
    SitePoint Wizard wheeler's Avatar
    Join Date
    Mar 2006
    Location
    Gold Coast, Australia
    Posts
    1,369
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks, I changed the checkbox to this:
    <input type=\"checkbox\" name=\"charges[$charge_id]\" value=\"$charge_id\" checked=\"checked\" onclick=\"update(this.form, $amount, this);\" />
    It still works, but does the same thing just keeps subtracting rather than adding when the box is rechecked.
    Studiotime - Time Management for Web Developers
    to-do's, messages, invoicing, reporting - 30 day free trial!
    Thomas Multimedia Web Development

  4. #4
    SitePoint Wizard wheeler's Avatar
    Join Date
    Mar 2006
    Location
    Gold Coast, Australia
    Posts
    1,369
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    finally got it working, can't say for sure what the problem was but seemed to be related to trying to use addition on string which makes 1+2 equal 12, and some sortof problem accessing array names no matter what I did.

    The solution is to simply check all the boxes each time one is changed. I'm a bit used to trying to reduce overhead like that given my php background, but I suppose in reality adding up 20 numbers is laughable to a modern CPU.

    Code:
    <input type=\"checkbox\" name=\"boxes\" value=\"$amount\" checked=\"checked\" onclick=\"update(this.form);\" />
    Code:
    function update(form)
    {
    	var new_total = 0;
    	var allboxes = form.boxes.length;
    	var current_total = form.sub_total.value;
    	
    	for (i=0; i<allboxes; i++)
    	{
    		if (form.boxes[i].checked==true)
    		{
    			new_total += form.boxes[i].value * 1;
    		}
    	}
    	
    	form.sub_total.value = Math.round(new_total);
    	calcSubTax(form);
    }
    Studiotime - Time Management for Web Developers
    to-do's, messages, invoicing, reporting - 30 day free trial!
    Thomas Multimedia Web Development

  5. #5
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    You found the problem all right. It was trying to add string values to each other.

    Using "* 1" is a hack, with a more appropriate method to explicitly cast it as a number so that later reviews of the code don't become confusing.

    Code javascript:
    new_total += Number(form.boxes[i].value);
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  6. #6
    SitePoint Wizard wheeler's Avatar
    Join Date
    Mar 2006
    Location
    Gold Coast, Australia
    Posts
    1,369
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    going to find brick wall to bang head against

    alright this is where it gets tricky. True to my form I had it working perfectly but needed to make it more complicated. The reason is, i've built an invoicing page where you can add 2 types of costs to the total - bookings and charges.

    I need to know what the ID is for each booking/charge (passed in value=""), so I can't keep them in the same array to prevent clashes. But whenever I put them into seperate arrays I seem to have all sorts of problems.

    It seems that a single checkbox is not treated as an array (makes sense). It also seems that everything falls apart everytime I introduce [] to the field name.

    Code:
    <input type=\"checkbox\" name=\"bookings\" value=\"$amount\" checked=\"checked\" onclick=\"update(this.form);\" />
    and
    Code:
    <input type=\"checkbox\" name=\"charges\" value=\"$amount\" checked=\"checked\" onclick=\"update(this.form);\" />
    Code:
    function update(form)
    {
    	var new_total = 0;
    	var current_total = form.sub_total.value;
    	
    	if (is_array([form.bookings]))
    	{
    		var allBoxes = form.bookings.length;
    		//alert("bookings is array");
    		// add up selected bookings
    		for (i=0; i<allBoxes; i++)
    		{
    			if (form.bookings[i].checked==true)
    			{
    				new_total += Number(form.bookings[i].value);
    			}
    		}
    	} else {
    		if (form.bookings.checked==true) new_total += Number(form.bookings.value);
    		//alert("bookings is not array");
    	}
    	
    	
    	if (is_array([form.charges]))
    	{
    		var allBoxes = form.charges.length;
    		//alert("charges is array");
    		// add up selected bookings
    		for (i=0; i<allBoxes; i++)
    		{
    			if (form.charges[i].checked==true)
    			{
    				new_total += Number(form.charges[i].value);
    			}
    		}
    	} else {
    		if (form.charges.checked==true) new_total += Number(form.charges.value);
    		alert("charges is not array");
    	}
    	
    	form.sub_total.value = Math.round(new_total);
    	calcSubTax(form);
    }
    
    
    function is_array( mixed_var ) {
        return ( mixed_var instanceof Array );
    }
    This works absolutely perfectly is both charges/bookings are arrays (there is more than one checkbox in the group) but whenever 1 group is singular, it spoils the party, and it seems to be because even a singular checkbox is being treated as an array in the if statement... whats that all about?
    Studiotime - Time Management for Web Developers
    to-do's, messages, invoicing, reporting - 30 day free trial!
    Thomas Multimedia Web Development

  7. #7
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    Some browsers have big trouble working out if it's an array or not.
    You can find a good typeOf() function at http://javascript.crockford.com/remedial.html
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  8. #8
    SitePoint Wizard wheeler's Avatar
    Join Date
    Mar 2006
    Location
    Gold Coast, Australia
    Posts
    1,369
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks Paul,

    I've tried out the 2nd typeOf function, but it is returning undefined on this:
    Code:
    <input type="checkbox" onclick="update(this.form);" checked="checked" value="35" name="bookings[115]"/>
    and it's returning object on this:
    Code:
    <input type="checkbox" onclick="update(this.form);" checked="checked" value="35" name="bookings"/>
    even better, IE is not showing my prompt at all:
    Code:
    function update(form)
    {
    	var new_total = 0;
    	var current_total = form.sub_total.value;
    	
    	if (typeOf(form.bookings)=='array')
    	{
    		var allBoxes = form.bookings.length;
    		//alert("bookings is array");
    		// add up selected bookings
    		for (i=0; i<allBoxes; i++)
    		{
    			if (form.bookings[i].checked==true)
    			{
    				new_total += Number(form.bookings[i].value);
    			}
    		}
    	} else {
    		if (form.bookings.checked==true) new_total += Number(form.bookings.value);
    		//alert("bookings is not array");
    	}
    	
    	
    	if (typeOf(form.charges)=='array')
    	{
    		var allBoxes = form.charges.length;
    		//alert("charges is array");
    		// add up selected bookings
    		for (i=0; i<allBoxes; i++)
    		{
    			if (form.charges[i].checked==true)
    			{
    				new_total += Number(form.charges[i].value);
    			}
    		}
    	} else {
    		if (form.charges.checked==true) new_total += Number(form.charges.value);
    		//alert("charges is not array");
    	}
    	
    	form.sub_total.value = Math.round(new_total);
    	calcSubTax(form);
    }
    
    
    function typeOf(value) {
        var s = typeof value;
        if (s === 'object') {
            if (value) {
                if (typeof value.length === 'number' &&
                        !(value.propertyIsEnumerable('length')) &&
                        typeof value.splice === 'function') {
                    s = 'array';
                }
            } else {
                s = 'null';
            }
        }
    	alert(s);
        return s;
    }
    Studiotime - Time Management for Web Developers
    to-do's, messages, invoicing, reporting - 30 day free trial!
    Thomas Multimedia Web Development

  9. #9
    SitePoint Wizard wheeler's Avatar
    Join Date
    Mar 2006
    Location
    Gold Coast, Australia
    Posts
    1,369
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Perhaps i'll try and summarise where i'm at. The second set of checkboxes does not work unless there is more than one. Additionally, ofType does not return an array, and does not seem to work at all in IE.
    Code HTML4Strict:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Untitled Document</title>
     
    <script type="text/javascript">
    <!--
    function typeOf(value) {
        var s = typeof value;
        if (s === 'object') {
            if (value) {
                if (typeof value.length === 'number' &&
                        !(value.propertyIsEnumerable('length')) &&
                        typeof value.splice === 'function') {
                    s = 'array';
                }
            } else {
                s = 'null';
            }
        }
    	//alert(s);
        return s;
    }
     
     
    function update(form)
    {
    	var new_total = 0;
    	var allBookings = form.bookings.length;
    	var allCharges = form.charges.length;
    	var current_total = form.sub_total.value;
     
    	//alert(typeOf(form.bookings));
     
    	if (typeOf(form.bookings)=='object')
    	{
    		for (i=0; i<allBookings; i++)
    		{
    			if (form.bookings[i].checked==true)
    			{
    				new_total += Number(form.bookings[i].value);
    			}
    		}
    	} else {
    		new_total += Number(form.bookings.value);
    	}
     
     
    	if (typeOf(form.charges)=='object')
    	{
    		alert('charges is an object');
    		for (i=0; i<allCharges; i++)
    		{
    			if (form.charges[i].checked==true)
    			{
    				new_total += Number(form.charges[i].value);
    			}
    		}
    	} else {
    		alert('charges is not an object');
    		new_total += Number(form.charges.value);
    	}
     
    	form.sub_total.value = Math.round(new_total);
    }
    -->
    </script>
     
    </head>
     
    <body>
    <form id="example" method="post" action="">
      <p>
        <input name="bookings" type="checkbox" value="1" onclick="update(this.form)" /><br />
        <input name="bookings" type="checkbox" value="2" onclick="update(this.form)" /><br />
        <input name="bookings" type="checkbox" value="3" onclick="update(this.form)" /><br />
        <input name="bookings" type="checkbox" value="4" onclick="update(this.form)" /></br />
      </p>
      <p>
    	<input name="charges" type="checkbox" value="1" onclick="update(this.form)" /><br />
        <br />
        <input name="sub_total" type="text" id="sub_total" value="0" />
      </p>
    </form>
     
    </body>
    </html>
    so close... yet so far away!
    Studiotime - Time Management for Web Developers
    to-do's, messages, invoicing, reporting - 30 day free trial!
    Thomas Multimedia Web Development

  10. #10
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,729
    Mentioned
    104 Post(s)
    Tagged
    4 Thread(s)
    In your particular situation, checking the length of the element, or array thereof, will result in a successful outcome.
    If there's time I'll try to figure out how to do it proper, but checking the length should get you there in the meantime.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  11. #11
    SitePoint Wizard wheeler's Avatar
    Join Date
    Mar 2006
    Location
    Gold Coast, Australia
    Posts
    1,369
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Unfortunately whenever I introduce a key manually to the field name ie. name="bookings[3]" I can't access the length in my function.

    In a single field without a manual key, the result is undefined - I guess I can work with that, however not until the length is correct when I pass a manual key. The reason I need to pass a manual key is because I need to use the key as an ID in the php side, unless there is a better way to pass the ID? Note I need both the value (amount) AND the ID.

    Code HTML4Strict:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Untitled Document</title>
     
    <script type="text/javascript">
    function update(form)
    {
     
    	var new_total = 0;
    	var allBookings = form.bookings.length;
    	var allCharges = form.charges.length;
    	var current_total = form.sub_total.value;
     
    	alert(allBookings); 
    	alert(allCharges); 
     
    	/*if (typeOf(form.bookings)=='object')
    	{
    		for (i=0; i<allBookings; i++)
    		{
    			if (form.bookings[i].checked==true)
    			{
    				new_total += Number(form.bookings[i].value);
    			}
    		}
    	} else {
    		new_total += Number(form.bookings.value);
    	}
     
     
    	if (typeOf(form.charges)=='object')
    	{
    		//alert('charges is an object');
    		for (i=0; i<allCharges; i++)
    		{
    			if (form.charges[i].checked==true)
    			{
    				new_total += Number(form.charges[i].value);
    			}
    		}
    	} else {
    		//alert('charges is not an object');
    		new_total += Number(form.charges.value);
    	}*/
     
    	form.sub_total.value = Math.round(new_total);
    }
    </script>
     
    </head>
     
    <body>
    <form id="example" method="post" action="">
      <p>
        <input name="bookings[0]" type="checkbox" value="1" onclick="update(this.form)" /><br />
        <input name="bookings[1]" type="checkbox" value="2" onclick="update(this.form)" /><br />
        <input name="bookings[2]" type="checkbox" value="3" onclick="update(this.form)" /><br />
        <input name="bookings[3]" type="checkbox" value="4" onclick="update(this.form)" /></br />
      </p>
      <p>
    	<input name="charges" type="checkbox" value="1" onclick="update(this.form)" /><br />
        <br />
        <input name="sub_total" type="text" id="sub_total" value="0" />
      </p>
    </form>
     
    </body>
    </html>
    Studiotime - Time Management for Web Developers
    to-do's, messages, invoicing, reporting - 30 day free trial!
    Thomas Multimedia Web Development

  12. #12
    SitePoint Wizard wheeler's Avatar
    Join Date
    Mar 2006
    Location
    Gold Coast, Australia
    Posts
    1,369
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    when all else fails, hack!
    Code HTML4Strict:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Untitled Document</title>
     
    <script type="text/javascript">
    function update(form)
    {
    	var new_total = 0;
    	var allBookings = form.bookings.length;
    	var allCharges = form.charges.length;
    	var current_total = form.sub_total.value;
     
    	if (allBookings > 0)
    	{
    		for (i=0; i<allBookings; i++)
    		{
    			if (form.bookings[i].checked==true)
    			{
    				var parts = form.bookings[i].value.split("_"); 
    				new_total += Number(parts[1]);
    			}
    		}
    	} else {
    		if (form.bookings.checked==true)
    		{
    			var parts = form.bookings.value.split("_"); 
    			new_total += Number(parts[1]);
    		}
    	}
     
    	if (allCharges > 0)
    	{
    		for (i=0; i<allCharges; i++)
    		{
    			if (form.charges[i].checked==true)
    			{
    				var parts = form.charges[i].value.split("_"); 
    				new_total += Number(parts[1]);
    			}
    		}
    	} else {
    		if (form.charges.checked==true)
    		{
    			var parts = form.charges.value.split("_"); 
    			new_total += Number(parts[1]);
    		}
    	}
     
    	form.sub_total.value = Math.round(new_total);
    }
    </script>
     
    </head>
     
    <body>
    <form id="example" method="post" action="">
      <p>
        <input name="bookings" type="checkbox" value="1_10" onclick="update(this.form)" /><br />
        <input name="bookings" type="checkbox" value="1_20" onclick="update(this.form)" /><br />
        <input name="bookings" type="checkbox" value="1_30" onclick="update(this.form)" /><br />
      </p>
      <p>
    	<input name="charges" type="checkbox" value="1_10" onclick="update(this.form)" /><br />
        <br />
        <input name="sub_total" type="text" id="sub_total" value="0" />
      </p>
    </form>
     
    </body>
    </html>
    Studiotime - Time Management for Web Developers
    to-do's, messages, invoicing, reporting - 30 day free trial!
    Thomas Multimedia Web Development


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •