Hello and welcome to our community! Is this your first visit?
Enjoy an ad free experience by logging in. Not a member yet? Register.

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

1. ## 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. Will:

Try this:

Code:
```<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<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);
}
}
}

</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;
.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>
<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>

<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>```

3. ## Users who have thanked 12 Pack Mack for this post:

where_is_will (09-03-2009)

4. Or more simply:-

Code:
```<html>

<script type = "text/javascript">

function findPrice() {
var numusers = parseInt(document.calculator.units.value);
if ((isNaN(numusers)) || (numusers > 100) || (numusers < 0)) {
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>

<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:
</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))```

Surely far better is:-

Code:
```var currStr = nField.value *1;
if (isNaN(currStr)) {```

5. ## Users who have thanked Philip M for this post:

where_is_will (09-03-2009)

6. Thanks guys, both solutions worked for me, so I'll play with both and see which works out the best for the page.

7. ## 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