Javascript Math's Help

Discussion in 'JavaScript' started by ianhaney, Feb 2, 2013.

  1. #1
    Hi

    I have the following coding in my website that add's or remove's prices to a quote page and works perfect but I need to insert another input field that takes the order total and divides it by 2

    Just wondering how I do that in this coding

    Below is the HTML

    <form name="checkbox">
           
            One Page<input type="checkbox" name="PROD_CH_70.00" value="70" onchange="CalculateTotal(this.form)">
            <br>
            Two Pages<input type="checkbox" name="PROD_CH_140.00" value="140" onchange="CalculateTotal(this.form)">
            <br>
            Three Pages(Bronze Package)<input type="checkbox" name="PROD_CH_179.00" value="179" onchange="CalculateTotal(this.form)">
            <br>
            Six Pages(Silver Package)<input type="checkbox" name="PROD_CH_339.00" value="339" onchange="CalculateTotal(this.form)">
            <br>
            Ten Pages(Gold Package)<input type="checkbox" name="PROD_CH_549.00" value="549" onchange="CalculateTotal(this.form)">
            <br>
            New Business Start up<input type="checkbox" name="PROD_CH_289.00" value="289" onchange="CalculateTotal(this.form)">
            <br>
            Ecommerce Package<input type="checkbox" name="PROD_CH_449.00" value="449" onchange="CalculateTotal(this.form)">
            <br>
            SEO on all pages<input type="checkbox" name="PROD_CH_30.00" value="449" onchange="CalculateTotal(this.form)">
            <br>
            Logo Design<input type="checkbox" name="PROD_CH_25.00" value="25" onchange="CalculateTotal(this.form)">
           
    <!--<input type="text" name="PROD_DC_15" size="10" maxlength="3" onchange="CalculateTotal(this.form)">
    <input type="text" name="PROD_CC_20" size="10" maxlength="3" onchange="CalculateTotal(this.form)">-->
    <br><br>
    <span style="color: #FFFFFF;">£<input type="text" name="TOTAL" size="10" onfocus="this.form.elements[0].focus()
    "> 
    </span>
    </form>
    HTML:
    Below is the Javascript coding

    function CalculateTotal(frm) {
            var order_total = 0
     
     
            // Run through all the form fields
            for (var i=0; i < frm.elements.length; ++i) {
     
     
                    // Get the current field
                    form_field = frm.elements[i]
     
     
                    // Get the field's name
                    form_name = form_field.name
     
     
                    // Is it a "product" field?
                    if (form_name.substring(0,4) == "PROD") {
     
     
                            // If so, extract the price from the name
                            item_price = parseFloat(form_name.substring(form_name.lastIndexOf("_") + 1))
     
     
                            // Get the quantity
                            if(form_field.type == 'checkbox') {
                                    item_quantity = form_field.checked;
                            } else {
                                    item_quantity = parseInt(form_field.value);               
                            }
     
     
                            // Update the order total
                            if (item_quantity >= 0) {
                                    order_total += item_quantity * item_price
                   
                   
     
     
                            }
                    }
            }
     
     
            // Display the total rounded to two decimal places
            frm.TOTAL.value = round_decimals(order_total, 2)
            }
     
     
            function round_decimals(original_number, decimals) {
            var result1 = original_number * Math.pow(10, decimals)
            var result2 = Math.round(result1)
            var result3 = result2 / Math.pow(10, decimals)
            return pad_with_zeros(result3, decimals)
            }
     
     
            function pad_with_zeros(rounded_value, decimal_places) {
     
     
            // Convert the number to a string
            var value_string = rounded_value.toString()
           
            // Locate the decimal point
            var decimal_location = value_string.indexOf(".")
     
     
            // Is there a decimal point?
            if (decimal_location == -1) {
                   
                    // If no, then all decimal places will be padded with 0s
                    decimal_part_length = 0
                   
                    // If decimal_places is greater than zero, tack on a decimal point
                    value_string += decimal_places > 0 ? "." : ""
            }
            else {
     
     
                    // If yes, then only the extra decimal places will be padded with 0s
                    decimal_part_length = value_string.length - decimal_location - 1
            }
           
            // Calculate the number of decimal places that need to be padded with 0s
            var pad_total = decimal_places - decimal_part_length
           
            if (pad_total > 0) {
                   
                    // Pad the string with 0s
                    for (var counter = 1; counter <= pad_total; counter++)
                            value_string += "0"
                    }
            return value_string
            }
    Code (markup):
     
    ianhaney, Feb 2, 2013 IP
  2. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,999
    Best Answers:
    253
    Trophy Points:
    515
    #2
    Well... I'm not sure why you're using a pre-increment so it skips the first frm.element... and really using .elements is 'old school' and really not a recommended way of handling things... but of course having no fieldset, labels, ID's to point those labels at, etc, etc... :p It's also not helping the use of periods in your names, which much like in classes isn't exactly kosher. I'd probably use a camelcase version of the item text instead ...

    I'd put all the ones you want to add up in a fieldset -- it's why we HAVE fieldsets. Then you could just getElementById that fieldset, and getElementsByTagName('input') ... and of course any GOOD scripting should NOT be manually saying onchange on every element either. Hmm... in fact if you're gonna hook them, you could then use parentNode to walk the childer.

    (BTW, wouldn't these make more sense as radio buttons?)

    So first order of business is fixing the markup.

    
    <form action="#" method="post" id="selectProducts">
    
    	<fieldset id="pageCount">
    	
    		<legend><span>Select Your products</span></legend>
    	
    		<label for="prod_1">One Page</label>
    		<input type="radio" name="PROD_pages" id="prod_1" value="70" />
    		<span>$70.00</span>
    		<br />	
    
    		<label for="prod_2">Two Pages</label>
    		<input type="radio" name="PROD_pages" id="prod_2" value="140" />
    		<span>$140.00</span>
    		<br />	
    		
    		<label for="prod_3">Three Pages</label>
    		<input type="radio" name="PROD_pages" id="prod_3" value="179" />
    		<span>$179.00</span>
    		<br />	
    		
    		<label for="prod_6">Six Pages (Silver Package)</label>
    		<input type="radio" name="PROD_pages" id="prod_6" value="339" />
    		<span>$339.00</span>
    		<br />	
    		
    		<label for="prod_10">Ten Pages (Gold Package)</label>
    		<input type="radio" name="PROD_pages" id="prod_10" value="549" />
    		<span>$549.00</span>
    		<br />	
           
    		<label for="prod_eCom">E-Commerce Package</label>
    		<input type="checkbox" name="PROD_eCom" id="prod_eCom" value="449" />
    		<span>$449.00</span>
    		<br />	
    		
    		<label for="prod_SEO">SEO on all Pages</label>
    		<input type="checkbox" name="PROD_SEO" id="prod_SEO" value="30" />
    		<span>$30.00</span>
    		<br />	
    		
    		<label for="prod_logo">Logo Design</label>
    		<input type="checkbox" name="PROD_logo" id="prod_logo" value="25" />
    		<span>$25.00</span>
    		<br />	
    
    	</fieldset>
    	
    	<div class="submitsAndData">
    		Total: $<span id="pageCount_total" class="total">0.00</span>
    	</div>
    
    </form>
    
    Code (markup):
    For the script... Pretty easy to just grab the inputs off the parent fieldset. I'll make it handle regular inputs, hiddens, etc, etc, in addition to radio and checkboxes. If we extend the fieldset's object to handle adding that fieldset together...

    
    function addFormTotaller(fieldsetId) {
    	"use strict"
    
    	var
    		fs = document.getElementById(fieldsetId),
    		list = fs.getElementsByTagName('input'),
    		t=0, e;
    		
    	fs.targetTotal = document.getElementById(fieldsetId + '_total');
    	
    	fs.recalcTotal = function() {
    		var
    			list = this.getElementsByTagName('input'),
    			tt = this.targetTotal,
    			t = 0, total = 0, e;
    		while (e = list[t++]) { switch (e.type) {
    			case 'checkbox':
    			case 'radio':
    				if (e.checked) total += Number(e.value);
    			break;
    			default:
    				total += Number(e.value);
    		}}
    		while (tt.firstChild) tt.removeChild(tt.firstChild);
    		tt.appendChild(document.createTextNode(total.toFixed(2)));
    	}
    	
    	while (e = list[t++]) {
    		e.onchange = function(e) {
    			e=e || window.event;
    			var	target=e.target || e.srcElement;
    			target.parentNode.recalcTotal();
    		}
    	}
    	
    } // addFormTotaller
    
    Code (markup):
    I put up a live demo of that in action here:
    http://www.cutcodedown.com/for_others/ianhaney/

    Hope this helps.

    -- edit --

    Real world deployment, I'd consider having that add function create the total line so that scripting off it's not shown, then have a NOSCRIPT saying "submit to see your total" or some such -- first rule should always be make it work without scripting FIRST, then enhance it.
     
    deathshadow, Feb 2, 2013 IP
  3. ianhaney

    ianhaney Greenhorn

    Messages:
    72
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    18
    #3
    Hi deathshadow

    Thank you so much for the coding etc

    Looks so much better and nicer than what I got

    Is it possible to have another field under Total to display a deposit that is 50% off the total

    Is that possible to do
     
    ianhaney, Feb 2, 2013 IP
  4. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,999
    Best Answers:
    253
    Trophy Points:
    515
    #4
    Pretty simple, just add another line with that value to the markup and a new ID, and replicate.

    I just uploaded a new copy to that directory to show how that works.. second line shows half the total.
     
    deathshadow, Feb 2, 2013 IP
  5. ianhaney

    ianhaney Greenhorn

    Messages:
    72
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    18
    #5
    Perfect, thank you so much

    Looks so much nicer than my way I had it, mine worked but looked awful design wide, was in a big blue rounded box with the checkboxes not in line

    Your's looks nicely laid out and easier to read

    Thank you so much
     
    ianhaney, Feb 2, 2013 IP
  6. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,999
    Best Answers:
    253
    Trophy Points:
    515
    #6
    Bonus time -- I just uploaded a new copy that also generates the two total fields in the scripting, and added that noscript button. That way scripting off dead elements don't show up and you can add a handler for that.

    The total button and submit both would have name="submit" -- but their 'value' will show up as $_POST['submit'] letting you tell them apart. Sneaky trick a lot of people don't know about :D
     
    deathshadow, Feb 2, 2013 IP
  7. ianhaney

    ianhaney Greenhorn

    Messages:
    72
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    18
    #7
    Hi

    I have just seen the reply, sorry for my late reply

    I love the order button etc you put in, was thinking of doing something like that and have the info sent to my email address or add a checkout button that is linked to PayPal or something

    Prob best to have it sent to my email address for now and then can send a customer a invoice for it on how to pay etc, be easier and less hassle won't it than setting up a checkout button etc and creating a checkout page and that so they can pay through PayPal or bank transfer

    Kind regards

    Ian
     
    ianhaney, Feb 3, 2013 IP