Hi everyone, my name is aaron and I'm working on a little project for fun. I'm nearly complete just have a few other things to finish up, this being one of the most important I thought I would start with this first. Basically I have a text box named "cost1" (goes up to 4) and need to multiply it by the quantity, "quantity1" in a drop down box and put it in the "total1" textbox. Here's what I have so far, but to no avail do I have it working, nor do I think I'm executing it properly. I was hoping to get it to run at the time the "cost" has changed and even the "quantity" one if too possible. Any help is much appreciated!
PHP Code:
<script type="text/javascript" language="JavaScript">
function calc_totals()
{
//gets values of field 1 and 2
var c1 = document.getElementById('cost1').value;
var q1 = document.getElementById('quantity1').value;
var t1 = document.getElementById('total1').value;
var c2 = document.getElementById('cost2').value;
var q2 = document.getElementById('quantity2').value;
var t2 = document.getElementById('total2').value;
var c3 = document.getElementById('cost3').value;
var q3 = document.getElementById('quantity3').value;
var t3 = document.getElementById('total3').value;
var c4 = document.getElementById('cost4').value;
var q4 = document.getElementById('quantity4').value;
var t4 = document.getElementById('total4').value;
if(c1 != null)
{
//does math on the values of field 1 and 2
t1 = c1 * q1;
//makes the value of outputfield = field1 + field2
document.getElementById('total1').value = t1;
}
if(c2 != null)
{
//does math on the values of field 1 and 2
t2 = c2 * q2;
//makes the value of outputfield = field1 + field2
document.getElementById('total2').value = t2;
}
var calcButton = document.getElementById('totals');
if (calcButton.addEventListener) // this is to support real browsers ;) { calcButton.addEventListener("click",function() { calc_totals(); }, false); } else if(calcButton.attachEvent) { // this function is to support IE calcButton.attachEvent("onclick",function() { calc_totals(); }); }
}
//======================================================= // Add our init function to the window load ////======================================================= if(window.addEventListener) // non IE fail { window.addEventListener("load", init, false); } else if(window.attachEvent) // IE fail { window.attachEvent("onload", init); } else { document.addEventListener("load", init, false); }
function calc_totals() { //gets values of field 1 and 2 var c1 = document.getElementById('cost1').value; var q1 = document.getElementById('quantity1'); q1 = q1.options[q1.selectedIndex].value; var t1 = document.getElementById('total1').value; var c2 = document.getElementById('cost2').value; var q2 = document.getElementById('quantity2'); q2 = q2.options[q2.selectedIndex].value; var t2 = document.getElementById('total2').value; var c3 = document.getElementById('cost3').value; var q3 = document.getElementById('quantity3'); q3 = q3.options[q3.selectedIndex].value; var t3 = document.getElementById('total3').value; var c4 = document.getElementById('cost4').value; var q4 = document.getElementById('quantity4'); q4 = q4.options[q4.selectedIndex].value; var t4 = document.getElementById('total4').value;
if(c1 != null) { //does math on the values of field 1 and 2 t1 = c1 * q1; //makes the value of outputfield = field1 + field2 document.getElementById('total1').value = t1; }
if(c2 != null) { //does math on the values of field 1 and 2 t2 = c2 * q2; //makes the value of outputfield = field1 + field2 document.getElementById('total2').value = t2; } } </script>
The following version shows two different methods for determining which input values to get...and only works when the cost changes. The other thing I've done, is now you can have an infinite number of rows (not just 4), and the code will detect which fields it needs to update automatically.
I'll post again when I've refactored it to use only Method 2, and works on changing either cost or Quantity.
var method = 2; var calcButton = document.getElementById('totals'); // for our click button event handler var inputArray = document.forms[0].getElementsByTagName('input'); var selectArray = document.forms[0].getElementsByTagName('select'), quantityArray;
// loop through costs for (var i=0; i<inputArray.length; i++) { if (inputArray[i].className !== 'cost') continue; // wrong element, skip to next var ele = inputArray[i];
// add the event handler addEvent(ele,'change',function() {
//====================================================================== // Now we need to get the current value, get the value of the right quantity, // and figure out which box to put the total in. // Then we run our get_sum() function and set the value //======================================================================
var curCost = this.value; // the value of the current node
//====================================================================== // There are several ways to figure out what the right nodes are // Method 1 : DOM Traversal // Method 2 : based on ID // Method 3 : we could add a custom attribute to each element via the // data- prefix. e.g. <select data-rowid='2' class='quantity'> // and then read that prefix. //======================================================================
if (method == 1) { // ********************************************************************* // Method 1 : DOM Traversal // *********************************************************************
// --------------------------------------- // I originally did this using the childNodes[x] // where x was an index. While it worked with: // x = 1; // costs // x = 3; // quantity // x = 5; // totals // I'm not sure about cross-browser compatibility // As such, I switched to using the Resig functions // ---------------------------------------
// get parent <TD> of COSTS <TD> var parentTD = parent(this);
// get quantity <TD> var quantityTD = next(parentTD);
// get total <TD> var totalTD = next(quantityTD);
// get the Quantity value var quantityArray = quantityTD.getElementsByTagName('select'); var curQuantity = quantityArray[0]; curQuantity = curQuantity.options[curQuantity.selectedIndex].value;
// get the Totals field var totalsArray = totalTD.getElementsByTagName('input'); var totalInput = totalsArray[0];
// set the total totalInput.value = get_sum(curCost,curQuantity);
} else {
// ********************************************************************* // Method 2 : based on ID // *********************************************************************
var idArray = this.id.split('t'); // this splits the 'id' into an array // our array looks like this: // ['cost',<number>];
var rowNum = idArray[1]; // get the number
// --------------------------------------- // Now we know which elements to update // --------------------------------------- var curQuantity = document.getElementById('quantity' + rowNum).value; var totalInput = document.getElementById('total' + rowNum); totalInput.value = get_sum(curCost, curQuantity);
}
}); // end event listener
} // end for loop
} // end init()
//====================================================================== // Add our init function to the window load //======================================================================
// Cross-browser implementation of element.addEventListener() // Example use: // var ele = document.getElementById('someElementID'); // addEvent(ele,'click',function(ev) { // alert('ev'); // }); var addEvent, removeEvent;
Ok. So this version is a little bit different. It uses a custom domready() function by Dustin Diaz to only bind events to the items when they've loaded.
Additionally, I've changed the totals function into an object ( function RowUpdater() ), because this allows more flexibility in the callback.
Lastly, this does require that the appropriate classes be assigned to each input, *AND* that the ID be: "cost_", "quantity_", "total_" and then the number.
var inputArray = document.forms[0].getElementsByTagName('input'); var selectArray = document.forms[0].getElementsByTagName('select');
// loop through costs for (var i=0; i<inputArray.length; i++) { if (inputArray[i].className !== 'cost') continue; // wrong element, skip to next var ele = inputArray[i];
var item = new RowUpdater(ele); addEvent(ele,'change',item.update);
}
// loop through quantities for (var i=0; i<selectArray.length; i++) { if (selectArray[i].className !== 'quantity') continue; // wrong element, skip to next var ele = selectArray[i];
var item = new RowUpdater(ele); addEvent(ele,'change',item.update);
Lastly, here's a jQuery solution. It basically includes zero comments, and has the following requirements:
- jQuery
- costs have to have a class of 'cost'
- quantities have a to have a class of 'quantity'
- totals have to have a class of 'total'
- cost, quantity, and total must all exist within the same parent <TR> (though this can be configured).
It's much cleaner to maintain, but what you were proposing looked to be pure javascript, and it is infinitely more advisable that you learn how to do it with plain javascript before you learn how to do it with a library like jquery.
Ok. So this version is a little bit different. It uses a custom domready() function by Dustin Diaz to only bind events to the items when they've loaded.
Additionally, I've changed the totals function into an object ( function RowUpdater() ), because this allows more flexibility in the callback.
Lastly, this does require that the appropriate classes be assigned to each input, *AND* that the ID be: "cost_", "quantity_", "total_" and then the number.
var inputArray = document.forms[0].getElementsByTagName('input');
var selectArray = document.forms[0].getElementsByTagName('select');
// loop through costs
for (var i=0; i<inputArray.length; i++)
{
if (inputArray[i].className !== 'cost') continue; // wrong element, skip to next
var ele = inputArray[i];
var item = new RowUpdater(ele);
addEvent(ele,'change',item.update);
}
// loop through quantities
for (var i=0; i<selectArray.length; i++)
{
if (selectArray[i].className !== 'quantity') continue; // wrong element, skip to next
var ele = selectArray[i];
var item = new RowUpdater(ele);
addEvent(ele,'change',item.update);
I have it full integrated and it looks great, only one thing though..
53.910000000000004 is what I get for the input of 5.99 * 9, I just need to round it off and it would be perfect. I'll PM you the link
var product = 5.99 * 9;
document.getElementById("putItHere").value = product.toFixed(2);
Or similar.
toFixed( digitsRIghtOfDecimalPoint ) converts a number to a string with specified number of decimal digits. Note that the result *IS* a string, so you should *NOT* use it in further calculations. Only use it to present a "pretty" number to the user, as the last step in any processing.
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.
var product = 5.99 * 9;
document.getElementById("putItHere").value = product.toFixed(2);
Or similar.
toFixed( digitsRIghtOfDecimalPoint ) converts a number to a string with specified number of decimal digits. Note that the result *IS* a string, so you should *NOT* use it in further calculations. Only use it to present a "pretty" number to the user, as the last step in any processing.
Thanks! I'll get to that part in a bit, but I just ran into a problem using the solution I quoted above. I'm using the POST command when sending it to the next page, I wasn't able to echo total_1
Form fields WITHOUT NAMES will *NEVER* be sent to the next page, whether using POST or GET.
Putting an ID on a form field is *USELESS* for POST or GET purposes.
If you think you need an ID (I don't think you do, but there's no point in rewriting that JS code at this point), okay. But then make sure you also give the field a name.
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.