-1

I'm trying to use the product of one function to be used later on in my program.

I have the following code:

var calculate = function(ingVolume, percentCarrier, totalCarrierVolume, totalIngredientVolume) {
    var volume = document.getElementById(ingVolume).value;
    var carrier = document.getElementById(percentCarrier).value;
    var mCarrier = carrier/100;

    var x = document.getElementById(totalCarrierVolume).innerHTML = mCarrier*(volume/(1-   
    mCarrier));
    var y = document.getElementById(totalIngredientVolume).innerHTML = parseInt(volume) + x;

    return [x, y];
};

var value1 = calculate('a', 'b', 'c', 'd');
var subvalue1_1 = value1[0];
var subvalue1_2 = value1[1];
var value2 = calculate('e', 'f', 'g', 'h');
var subvalue2_1 = value2[0];
var subvalue2_2 = value2[1];
var value3 = calculate('i', 'j', 'k', 'l');
var subvalue3_1 = value3[0];
var subvalue3_2 = value3[1];
var value4 = calculate('m', 'n', 'o', 'p');
var subvalue4_1 = value4[0];
var subvalue4_2 = value4[1];
var value5 = calculate('q', 'r', 's', 't');
var subvalue5_1 = value5[0];
var subvalue5_2 = value5[1];

function calculate2() {
    document.getElementById("demo").innerHTML = value1;
};

If I plug some numbers into this and run it, the variable 'value1' is returned as undefined. However, when I run calculate('a', 'b', 'c', 'd') in the javascript console it runs fine and returns [value of x, value of y] for those parameters.

The exact error message is

"Uncaught TypeError: Cannot read property 'value' of null" for line 17

which is var volume = document.getElementById(ingVolume).value;

It is being run for the following html:

<form name="testing">
<table border="1" style="padding: 5px;">
<tr>
    <td>Ingredient Name</td>
    <td>Amount (in Mg)</td>
    <td>% Carrier</td>
    <td></td>
    <td>Total Carrier Volume</td>
    <td>Total Ingredient Volume</td>
</tr>
<tr>
    <td><input type="text"></input></td>
    <td><input type="number" id="a"> Mg</input></td>
    <td><input type="number" id="b"></input> %</td>
    <td><button type="button" onclick="calculate('a', 'b', 'c', 'd')">Calculate Final     
     Volume</button></td>
    <td id="c"></td>
    <td id="d"></td>
    <td><a href="#" onclick="toggleRow('row2')">New Ingredient</a></td>

</tr>
<tr id="row2" style="display: none;">
    <td><input type="text"></input></td>
    <td><input type="number" id="e"> Mg</input></td>
    <td><input type="number" id="f"></input> %</td>
    <td><button type="button" onclick="calculate('e', 'f', 'g', 'h')">Calculate Final 
     Volume</button></td>
    <td id="g"></td>
    <td id="h"></td>
    <td><a href="#" onclick="toggleRow('row3')">New Ingredient</a></td>
    <td><a href="#" onclick="toggleRow('row2')">Delete Ingredient</a></td>
</tr>
<tr id="row3" style="display: none;">
    <td><input type="text"></input></td>
    <td><input type="number" id="i"> Mg</input></td>
    <td><input type="number" id="j"></input> %</td>
    <td><button type="button" onclick="calculate('i', 'j', 'k', 'l')">Calculate Final 
     Volume</button></td>
    <td id="k"></td>
    <td id="l"></td>
    <td><a href="#" onclick="toggleRow('row4')">New Ingredient</a></td>
    <td><a href="#" onclick="toggleRow('row3')">Delete Ingredient</a></td>
</tr>
<tr id="row4" style="display: none;">
    <td><input type="text"></input></td>
    <td><input type="number" id="m"> Mg</input></td>
    <td><input type="number" id="n"></input> %</td>
    <td><button type="button" onclick="calculate('m', 'n', 'o', 'p')">Calculate Final 
     Volume</button></td>
    <td id="o"></td>
    <td id="p"></td>
    <td><a href="#" onclick="toggleRow('row5')">New Ingredient</a></td>
    <td><a href="#" onclick="toggleRow('row4')">Delete Ingredient</a></td>
</tr>
<tr id="row5" style="display: none;">
    <td><input type="text"></input></td>
    <td><input type="number" id="q"> Mg</input></td>
    <td><input type="number" id="r"></input> %</td>
    <td><button type="button" onclick="calculate('q', 'r', 's', 't')">Calculate Final    
    Volume</button></td>
    <td id="s"></td>
    <td id="t"></td>
    <td><a href="#" onclick="noMoreRows()">New Ingredient</a></td>
    <td><a href="#" onclick="toggleRow('row5')">Delete Ingredient</a></td>
</tr>
</table>
</form>

<button type="button" onclick="calculate2()">Click Me</button>

<p id="demo"></p>

I want to eventually use subvalue1_1 and subvalue1_2 for additional calculations by other functions, but it won't work if there's no value stored for value1.

The html appears after the javascript, which is in the head of the html document.

Phil
  • 128,310
  • 20
  • 201
  • 202
Jonathan Bechtel
  • 2,509
  • 3
  • 30
  • 54
  • 1
    I do not see where the code that you posted is called in the HTML. I can see the `calculate` is called, but where is what you have at the bottom (`value1 = calculate('a', 'b', 'c', 'd')`)? in other words, it is unclear what you are asking. – akonsu Dec 02 '14 at 23:22
  • Seems like you're calling `calculate` directly, before the elements have any value, and you end up with `NaN` ? – adeneo Dec 02 '14 at 23:23
  • @akonsu It would be called when the script is loaded. – James Westman Dec 02 '14 at 23:23
  • @kittycat3141 the HTML does not mention any script... – akonsu Dec 02 '14 at 23:24
  • @akonsu I'm assuming the code is somewhere in the HTML page. – James Westman Dec 02 '14 at 23:26
  • 2
    @Verhaeren `ingVolume` is one of the parameters of the function. – James Westman Dec 02 '14 at 23:26
  • 1
    Is the code before the HTML page or after? – James Westman Dec 02 '14 at 23:27
  • If you click the file location to the right of the error message, what is the exact line that it takes you to? I have a feeling you may be trying to use `value1` either before it is defined or in a different scope – Phil Dec 02 '14 at 23:28
  • If calculate () is called when the page is loaded, your input fields don't have numerical values yet, right, so you must end up manipulating some NaN values. What do you have in the console? – Julien Bérubé Dec 02 '14 at 23:31
  • @Phil to me it is not clear where the variable is defined and accessed. This error is impossible to get if you run the code in the first snippet. – akonsu Dec 02 '14 at 23:32
  • @akonsu which is why I assume that the error is actually occurring somewhere else – Phil Dec 02 '14 at 23:33
  • 1
    @Verhaeren - it is valid, as assigning a value returns that value, but it is extremely bad practice to assign the return value of an assigment back to a variable. – adeneo Dec 02 '14 at 23:33
  • @adeneo - NaN is not showing up, simply undefined. It's not run directly in the code, but after I run calculate value1 shows up as being undefined in the javascript console, whereas as the value of calculate('a', 'b', 'c', 'd') shows up correctly. – Jonathan Bechtel Dec 03 '14 at 00:09
  • @JulienBérubé, calculate() is not run when the page is loaded, it's loaded onclick by a button in the table. I'm going to add the rest of my code to my example. – Jonathan Bechtel Dec 03 '14 at 00:10
  • possible duplicate of [Why does jQuery or a DOM method such as getElementById not find the element?](http://stackoverflow.com/questions/14028959/why-does-jquery-or-a-dom-method-such-as-getelementbyid-not-find-the-element) – Phil Dec 03 '14 at 00:37

1 Answers1

1

You need to give a default value to the numeric variables if a value has not been entered. Works fine in this snippet.

 var calculate = function(ingVolume, percentCarrier, totalCarrierVolume, totalIngredientVolume) {
   
       // added  || 0 here.  if the value of the textbox is empty, this will default the variables to 0 instead.
  var volume = document.getElementById(ingVolume).value || 0;
  var carrier = document.getElementById(percentCarrier).value || 0;
  var mCarrier = carrier/100;
  
  var x = document.getElementById(totalCarrierVolume).innerHTML = mCarrier*(volume/(1-   
        mCarrier));
  var y = document.getElementById(totalIngredientVolume).innerHTML = parseInt(volume) + x;
  
  return [x, y];
    };

    var value1 = calculate('a', 'b', 'c', 'd');
    var subvalue1_1 = value1[0];
    var subvalue1_2 = value1[1];
    <form name="testing">
    <table border="1" style="padding: 5px;">
 <tr>
  <td>Ingredient Name</td>
  <td>Amount (in Mg)</td>
  <td>% Carrier</td>
  <td></td>
  <td>Total Carrier Volume</td>
  <td>Total Ingredient Volume</td>
 </tr>
 <tr>
  <td><input type="text"></input></td>
  <td><input type="number" id="a"> Mg</input></td>
  <td><input type="number" id="b"></input> %</td>
  <td><button type="button" onclick="calculate('a', 'b', 'c', 'd')">Calculate Final     
         Volume</button></td>
  <td id="c"></td>
  <td id="d"></td>
  <td><a href="#" onclick="toggleRow('row2')">New Ingredient</a></td>

 </tr>
    </table>
    </form>

EDIT: here's a new snippet to match the OP's updated code sample. Note that to have the button click work, the values have to be in the textboxes prior to calculating value1. Note that this calculation should really be executed just prior to putting the value into the paragraph. Click the No, Click Me... button to see it work in real-time (only for value1, like your code was doing).

var calculate = function(ingVolume, percentCarrier, totalCarrierVolume, totalIngredientVolume) {
    var volume = document.getElementById(ingVolume).value || 0;
    var carrier = document.getElementById(percentCarrier).value || 0;
    var mCarrier = carrier/100;

    var x = document.getElementById(totalCarrierVolume).innerHTML = mCarrier*(volume/(1-   
    mCarrier));
    var y = document.getElementById(totalIngredientVolume).innerHTML = parseInt(volume) + x;

    return [x, y];
};

var value1 = calculate('a', 'b', 'c', 'd');
var subvalue1_1 = value1[0];
var subvalue1_2 = value1[1];
var value2 = calculate('e', 'f', 'g', 'h');
var subvalue2_1 = value2[0];
var subvalue2_2 = value2[1];
var value3 = calculate('i', 'j', 'k', 'l');
var subvalue3_1 = value3[0];
var subvalue3_2 = value3[1];
var value4 = calculate('m', 'n', 'o', 'p');
var subvalue4_1 = value4[0];
var subvalue4_2 = value4[1];
var value5 = calculate('q', 'r', 's', 't');
var subvalue5_1 = value5[0];
var subvalue5_2 = value5[1];

function calculate2() {
    // added the || 0 here, too. 
    document.getElementById("demo").innerHTML = value1 || 0;
};

function thisIsHowCalculate2ShouldLook(){
  value1 = calculate('a', 'b', 'c', 'd');
  document.getElementById("demo").innerHTML = value1 || 0;
}

function toggleRow(id){
  document.getElementById(id).style.display = document.getElementById(id).style.display === 'none' ? 'table-row' : 'none';
}

function noMoreRows(){
  alert('no more rows can be added-- script is not dynamic, yet.');
}
<form name="testing">
<table border="1" style="padding: 5px;">
<tr>
    <td>Ingredient Name</td>
    <td>Amount (in Mg)</td>
    <td>% Carrier</td>
    <td></td>
    <td>Total Carrier Volume</td>
    <td>Total Ingredient Volume</td>
</tr>
<tr>
    <td><input type="text"></input></td>
    <td><input type="number" id="a" /> Mg</td>
    <td><input type="number" id="b" /> %</td>
    <td><button type="button" onclick="calculate('a', 'b', 'c', 'd')">Calculate Final     
     Volume</button></td>
    <td id="c"></td>
    <td id="d"></td>
    <td><a href="#" onclick="toggleRow('row2')">New Ingredient</a></td>

</tr>
<tr id="row2" style="display: none;">
    <td><input type="text"></input></td>
    <td><input type="number" id="e"> Mg</input></td>
    <td><input type="number" id="f"></input> %</td>
    <td><button type="button" onclick="calculate('e', 'f', 'g', 'h')">Calculate Final 
     Volume</button></td>
    <td id="g"></td>
    <td id="h"></td>
    <td><a href="#" onclick="toggleRow('row3')">New Ingredient</a></td>
    <td><a href="#" onclick="toggleRow('row2')">Delete Ingredient</a></td>
</tr>
<tr id="row3" style="display: none;">
    <td><input type="text"></input></td>
    <td><input type="number" id="i"> Mg</input></td>
    <td><input type="number" id="j"></input> %</td>
    <td><button type="button" onclick="calculate('i', 'j', 'k', 'l')">Calculate Final 
     Volume</button></td>
    <td id="k"></td>
    <td id="l"></td>
    <td><a href="#" onclick="toggleRow('row4')">New Ingredient</a></td>
    <td><a href="#" onclick="toggleRow('row3')">Delete Ingredient</a></td>
</tr>
<tr id="row4" style="display: none;">
    <td><input type="text"></input></td>
    <td><input type="number" id="m"> Mg</input></td>
    <td><input type="number" id="n"></input> %</td>
    <td><button type="button" onclick="calculate('m', 'n', 'o', 'p')">Calculate Final 
     Volume</button></td>
    <td id="o"></td>
    <td id="p"></td>
    <td><a href="#" onclick="toggleRow('row5')">New Ingredient</a></td>
    <td><a href="#" onclick="toggleRow('row4')">Delete Ingredient</a></td>
</tr>
<tr id="row5" style="display: none;">
    <td><input type="text"></input></td>
    <td><input type="number" id="q"> Mg</input></td>
    <td><input type="number" id="r"></input> %</td>
    <td><button type="button" onclick="calculate('q', 'r', 's', 't')">Calculate Final    
    Volume</button></td>
    <td id="s"></td>
    <td id="t"></td>
    <td><a href="#" onclick="noMoreRows()">New Ingredient</a></td>
    <td><a href="#" onclick="toggleRow('row5')">Delete Ingredient</a></td>
</tr>
</table>
</form>

<button type="button" onclick="calculate2()">Click Me</button>

<button type="button" onclick="thisIsHowCalculate2ShouldLook()">No, Click Me To See It Work</button>

<p id="demo"></p>
ps2goat
  • 7,102
  • 1
  • 28
  • 59
  • thank you for this, but when I take this, enter some numbers for the fields, and hit 'calculate final volume', when I go into the javascript console value1 is still undefined, whereas if I run calculate('a', 'b', 'c', 'd') then it returns the values – Jonathan Bechtel Dec 02 '14 at 23:59
  • @JonathanBechtel As I asked in the comments above (you may have missed it), where **exactly** is the error message pointing (as in file name and line number)? What is on that line? – Phil Dec 03 '14 at 00:05
  • @Phil - It reads: "Uncaught TypeError: Cannot read property 'value' of null" for line 17, which is "var volume = document.getElementById(ingVolume).value;" – Jonathan Bechtel Dec 03 '14 at 00:24
  • @JonathanBechtel Why on Earth couldn't you have said that in the first place?!?!?! – Phil Dec 03 '14 at 00:33
  • @Phil, I've been working on this script for several days now, and it's always said that and it's never stopped the script from working so I didn't think it was the issue, so I left it out. – Jonathan Bechtel Dec 03 '14 at 00:44
  • @Phil, my big concern is that when I run calculate() and pass parameters into it works fine and returns the correct values, but when I save the calculate function with those same parameters to a variable it creates an error. (Value1, Value2, Value3, etc), which I don't believe has anything to do with the error referenced above. Like you said in your first comment, I think it has something to do with scope, but I'm not sure exactly what. – Jonathan Bechtel Dec 03 '14 at 00:52
  • @JonathanBechtel No, it's because you probably have the ` – Phil Dec 03 '14 at 02:27
  • @Phil, I updated the answer with a second example. The calculation and assignment to `value1` looks like it is being done on page load. Subsequently clicking the `Calculate...` buttons only fills the results into the other two columns of the table, but does not re-assign these values to the variables the OP is trying to use when clicking his button. I think my second snippet now shows how he should approach it, at least in the case of clicking his demo button: running the calculation and assigning it to the variable just prior to displaying the value. (though the variable is overkill) – ps2goat Dec 03 '14 at 05:41