Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 5 of 5
  1. #1
    New to the CF scene
    Join Date
    Sep 2009
    Posts
    3
    Thanks
    2
    Thanked 0 Times in 0 Posts

    Split a number of "units" into an array(?) to return a price

    Hi,

    I am looking for a bit of help splitting out a number of units into separate "bands" to compare against a price list. The effect I am trying to achieve can be seen below:


    I have adapted a bit of code to compare a number of units against a decreasing price list, but that only calculates monthly cost (£35) + number of additional users (eg. 4 @£20) = total cost. What I need to be able to do is work out is 50 units = £35 (first three users) + next 4 users at £20 + next 41 users at £15 = total cost.

    I would guess that I need to change my static list of costs to an array, but this is beyond my current skills! My (well, my version of it anyway) JS code is as follows:

    Code:
    <SCRIPT LANGUAGE="JavaScript">
    <!-- Begin
    var max_units = 301; // quantities in excess of max_units all have the same unit price
    var currency = "£"; // currency sign used in 'formatMessage()'
    var monthly = 35;
    // Edit this function to reflect your discount prices! 
    function getDiscountPrice(units) {
    // Note: It is important to work your way down from max to min amounts!
    if (units >= max_units) return 1.50; 
    if (units >= 201) return 2.50;
    if (units >= 101) return 5;
    if (units >= 51) return 10;
    if (units >= 11) return 15;
    if (units >= 4) return 20;
    if (units <= 3) return 0;
    }
    
    function getNumberOfUnits() {
    var units = document.calculator.units.value; 
    return (units == "") ? 0 : units;
    }
    function showResult(result) {
    // adjust the following line if result must popup somewhere else
    document.calculator.respons.value = result;	
    }
    function formatMessage(units, unit_price) {
    return units + " x " + currency + formatPrice(unit_price) + " + " + currency + monthly + " = " + currency + formatPrice(units * unit_price + monthly);
    }
    // AltUnits (alternate units): add extra units to reach minimum for next discount price
    function getAltUnits(units) {
    var discount_price = getDiscountPrice(units);
    if (units < max_units) do { units++ } while (discount_price == getDiscountPrice(units));
    return units;
    }
    function findPrice() {
    var units = getNumberOfUnits();
    var unit_price = getDiscountPrice(units);
    var alt_units = getAltUnits(units);
    var alt_unit_price = getDiscountPrice(alt_units);
    var result;
    if ((units * unit_price) < (alt_units * alt_unit_price)) 
    result = formatMessage(units, unit_price); 
    else
    result = formatMessage(alt_units, alt_unit_price);
    showResult(result);
    }
    function formatPrice(value) {
    var result= Math.floor(value) + ".";
    var cents = 100 * (value-Math.floor(value)) + 0.5;
    result += Math.floor(cents / 10);
    result += Math.floor(cents % 10);
    return result;
    }
    function filterNonNumeric(field) {
    var result = new String();
    var numbers = "0123456789";
    var chars = field.value.split(""); // create array 
    for (i = 0; i < chars.length; i++) {
    if (numbers.indexOf(chars[i]) != -1) result += chars[i];
    }
    if (field.value != result) field.value = result;
    }
    //  End -->
    </script>
    This then just links to an HTML form at the bottom of the page:

    Code:
    <form name=calculator>
    <p>Enter number of users:
    <input type=text value="1" name="units" onkeydown="findPrice()" onKeyUp="filterNonNumeric(this); findPrice()" onKeyPress="return disableEnterKey(event)" size="4"></p>
    <p>Hosted Solution Cost:
    <input type=text onfocus="this.blur()" name="respons" size="30" style="border:0; font-weight:bold;"></p>
    </form>
    The HTML I am sure I can sort in the end, although the current form will have to go, or at least be split out. But I am at a loss as to how to pull the units into the correct structure to be able to compare them to the price list. Any help / links to tutorials would be appreciated. Please be gentle...

    Thanks,

    Will

  • #2
    Banned
    Join Date
    Mar 2009
    Posts
    248
    Thanks
    3
    Thanked 68 Times in 66 Posts
    Will:

    Try this:

    Code:
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <html>
    <head>
    <title>None</title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <script type="text/javascript">
    
    	var IE = navigator.appName == "Microsoft Internet Explorer" ? true : false;
    
    	function clearTable(nDisplayResult){
    
    		for(i=0; i<nDisplayResult.length; i++)
    			{
    			 nDisplayResult[i].innerHTML = "&nbsp;";
    			}
    		IE ? nDisplayResult[2].parentNode.firstChild.innerHTML = "11+" 
    		   : nDisplayResult[2].parentNode.childNodes[1].innerHTML = "11+";
    	}
    
    	function computeResult(nUsers,nDisplayResult){
    	
    		clearTable(nDisplayResult);
    		var lowRange = 35;
    		var midRange = 140;	
    		var highRange = 0;	
    		if (nUsers <= 3)
    			{
    			 nDisplayResult[0].innerHTML = "&pound;" + lowRange;
    			 midRange = 0;
    			}
    		else if (nUsers > 3 && nUsers <= 10)
    			{
    			 midRange = (nUsers - 3) * 20; 
    			 nDisplayResult[0].innerHTML = "&pound;" + lowRange;
    			 nDisplayResult[1].innerHTML = "&pound;" + midRange;
    			}
    		else if(nUsers > 10)
    			{
    			 highRange = ((nUsers - 10) * 15).toString().replace(/(\d+)(\d{3})/,"$1,$2");
    			 nDisplayResult[0].innerHTML = "&pound;" + lowRange;
    			 nDisplayResult[1].innerHTML = "&pound;" + midRange;
    			 nDisplayResult[2].innerHTML = "&pound;" + highRange;
    			 highRange = Number(highRange.replace(/[^\d]/,""));
    			 IE ? nDisplayResult[2].parentNode.firstChild.innerHTML = "11 - " + nUsers
    		            : nDisplayResult[2].parentNode.childNodes[1].innerHTML = "11 - " + nUsers
    			 
    			}		
    		var nTotal =  lowRange + midRange + highRange;
    		nDisplayResult[3].innerHTML = "&pound;" + nTotal.toString().replace(/(\d+)(\d{3})/,"$1,$2")
    	}
    
    	function verifyNumeric(nField){
    
    		var currStr = nField.value;
    		if (!/^[1-9]\d*$/.test(currStr))
    			{
    			 currStr = currStr.substring(0,currStr.length-1);
    			 nField.value = currStr;
    			} 	
    		return currStr;	
    	}	
    
    	function init(){
    
    		var calcTable = document.getElementById('calcContainer').getElementsByTagName('table')[0];		
    		var resultCells = [];
    		var nTD = calcTable.getElementsByTagName('td');		
    		for (i=0; i<nTD.length; i++)
    			{
    			 if (nTD[i].innerHTML == "&nbsp;")
    				{
    				 resultCells[resultCells.length] = nTD[i];
    				}
    			}		
    		document.forms[0]['userEntry'].onkeyup = function()
    			{
    			 if (verifyNumeric(this))
    				{
    				 computeResult(this.value,resultCells);
    				}
    			 else	{
    				  clearTable(resultCells);
    				}
    			}
    	}
    
    	IE ? attachEvent('onload', init, false) : addEventListener('load', init, false);	
    
    </script>
    <style type="text/css">
    
    	 body {background-color: #fffacd; margin-top: 60px;}
    	 form {float: left;width: 298px; margin-bottom: 0px; font-family: arial; font-size: 11pt;
    	       background-color: #00008b; color: white;  border-left: 1px solid black; 
    	       border-right: 1px solid black;}		
    	 label	{display: block; margin-left: 45px; margin-top: 5px; margin-bottom: 5px;}		
    	 th {font-family: helvetica; font-size: 9pt; border-bottom: 1px solid #fff8dc;
    	     color: #8fbc8f; border: 1px solid white;}
    	 td {border: 1px solid white;}
    	#calcContainer {height: 185px; width: 300px; margin-left: auto; margin-right: auto;}
    	#calcContainer div {float: left; width: 298px; font-family: tahoma; font-size: 10pt; text-align: center; 
    		            font-weight: bold; background-color: #6495ed; border: 1px solid black;
    		            padding-top: 3px; padding-bottom: 3px;}		
    	.user_input {text-align: center; width: 35px;}
    	.result_table {float: left; width: 300px; font-family: arial; font-size: 10pt; text-align: center;
    		       background-color: #e6e6fa; border: 1px solid black;}
    	.result_cell {text-align: right;}
    	.total_cell {font-family: helvetica; font-size: 9pt; font-weight: bold;
    		     border-bottom: 1px solid #fff8dc; color: #8fbc8f;}
    
    </style>
    </head>
    	<body>
    
    		<div id="calcContainer">
    
    			<div>TEAM iQ Cost Calculator</div>
    		
    			<form action="">
    		 
    				<label>Enter number of users: 
    					<input type="text" name="userEntry" class="user_input">	
    				</label>			
    		  
    			</form>
    		
    			<table cellpadding="3" cellspacing="0" class="result_table">
    				<tbody>
    					<tr>
    						<th>Number of Users</th>
    						<th>Cost Per Band</th>
    						<th>Total Cost</th>
    					</tr>
    					<tr>
    						<td>0-3</td>
    						<td>&pound;35</td>
    						<td class="result_cell">&nbsp;</td>
    					</tr>
    					<tr>
    						<td>4-10</td>
    						<td>&pound;20 each</td>
    						<td class="result_cell">&nbsp;</td>
    					</tr>
    					<tr>
    						<td>11+</td>
    						<td>&pound;15 each</td>
    						<td class="result_cell">&nbsp;</td>
    					</tr>
    					<tr>
    						<td colspan="2" class="total_cell">Total Cost Per Month:</td>
    						<td class="result_cell">&nbsp;</td>
    					</tr>
    				</tbody>
    			</table>	
    
    		</div>				
    
    	</body>
    </html>
    Last edited by 12 Pack Mack; 09-02-2009 at 11:46 PM. Reason: Improvement

  • Users who have thanked 12 Pack Mack for this post:

    where_is_will (09-03-2009)

  • #3
    Supreme Master coder! Philip M's Avatar
    Join Date
    Jun 2002
    Location
    London, England
    Posts
    18,144
    Thanks
    203
    Thanked 2,547 Times in 2,525 Posts
    Or more simply:-

    Code:
    <html>
    <head>
    
    <script type = "text/javascript">
    
    function findPrice() {
    var numusers = parseInt(document.calculator.units.value);
    if ((isNaN(numusers)) || (numusers > 100) || (numusers < 0)) {
    alert ("Please enter a number max. 100");
    document.calculator.units.value = "";
    document.calculator.units.focus();
    return false;
    }
    
    var Ausers = numusers - 10;
    if (Ausers<0) {Ausers = 0};
    var Busers = numusers - Ausers - 3;
    if (Busers <0) {Busers = 0}
    var totalprice = (Busers * 20) + (Ausers * 15) + 35;
    // naturally you can show each price band seperately if you want
    document.calculator.respons.value = "$" + totalprice.toFixed(2);
    }
    
    </script>
    
    </head>
    
    <body>
    
    <form name="calculator">
    <p>Enter number of users:
    <input type=text  name="units" value="0" size = "5" onfocus = "this.value = ''" onblur = "findPrice()"></p>
    <p>Hosted Solution Cost:
    <input type=text name="respons" size="6" readonly = readonly style="border:0; font-weight:bold;"></p>
    </form>
    
    </body>
    </html>
    Your code contains a vast amount of unnecessary complication and long-winded but obsolete code.


    <script language=javascript> is long deprecated and obsolete. Use <script type = "text/javascript"> instead.
    The <!--and //--> comment (hiding) tags have not been necessary since IE3. This suggests that your code is very antiquated.

    12 Pack Mack-

    Code:
    var currStr = nField.value;
    if (!/^[1-9]\d*$/.test(currStr))
    What about 9 green bottles?

    Surely far better is:-

    Code:
    var currStr = nField.value *1;
    if (isNaN(currStr)) {
    Last edited by Philip M; 09-03-2009 at 08:35 AM.

  • Users who have thanked Philip M for this post:

    where_is_will (09-03-2009)

  • #4
    New to the CF scene
    Join Date
    Sep 2009
    Posts
    3
    Thanks
    2
    Thanked 0 Times in 0 Posts
    Thanks guys, both solutions worked for me, so I'll play with both and see which works out the best for the page.

  • #5
    New to the CF scene
    Join Date
    Sep 2009
    Posts
    3
    Thanks
    2
    Thanked 0 Times in 0 Posts

    Can I build the results table dynamically?

    Hi,

    One last (!) question - the amount of "Bands" that I need to display has now grown to over 10, so I think the table should be built dynamically, based on whether the "band" has a value above 0. I have read about building at table here - https://developer.mozilla.org/en/Tra...DOM_Interfaces - would that be best approach, using a myTextNode = document.createTextNode("foo"); statement that runs in the field if the band value is >0?

    The final "total cost" row can remain hard coded, as it will always be there, this would just fill in the cells above it.

    I just wanted to check that this is the right way to go. Thanks.

    Will


  •  

    Tags for this Thread

    Posting Permissions

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