The primary issue is that you are re-declaring your variables inside the .forEach() loops, which causes the outer-scoped version of the variable not to get the value. If you simply remove the var from the .forEach() lines, then references to the variables will match the higher-scoped ones.
In your getValues() function, you are expecting values to be passed in and you are using the same names as your variables. This won't cause the variables to be passed in, it will create newly scoped variables that will hide the outer scoped ones. You can remove them and just access the higher scoped variables.
You also have to know/remember that HTML has just one data type...text. When you read the values of HTML elements into JavaScript, all those values will be strings. To do math with those values, you have to convert the strings to numbers.
Also, you have quite a few HTML errors....
While technically, <br/> is legal, it is only useful in a very few cases and should be avoided because unnecessary use of it will invariably lead to bugs, which you have because you've written </br> several times (which is never valid). In addition, you've written <fieldset/>, which isn't allowed. Also, don't use br for visual styling (adding blank lines). br is a semantic tag which indicates content continues on the next line. For styling, use CSS.
Next, you were using <label> elements inside of your fieldset elements as titles for the field sets, but that's the job of <legend>. <label> is for associating content with a form field, it's not to title fieldsets.
You've also got a submit button, when you aren't actually submitting data anywhere. In those cases, use type=button. Additionally, since you aren't actually submitting data, you don't even need the <form> element.
Now, lastly, you are repeating the same code over and over again with the only difference being that each loop totals up a different variable. In programming, the moment you write the same code twice, you should stop and think about how to not do that. It's called the DRY (Don't Repeat Yourself) principle.
If you take a look at the comments in the working code below, you will see how all those loops and functions can be reduced.
// Get reference to the HTML elements that we'll need individual access to:
var answer = document.getElementById("answer");
var submit = document.querySelector("button[type=button]");
// Set up event binding in JavaScript, not HTML
submit.addEventListener("click", getValues);
// Will store final answer:
var result = null;
// This object has properties that will actually store
// the radio button values as needed. By initializing these
// properties at the same values as their corresponding
// radio button values, we ensure that a valid answer is
// reported even if the user doesn't do any initial changes
// to the radio button selections and just clicks submit.
var scopeObject = {
basePlate:10000,
age: 1000,
region: 100,
patientType: 10,
accuracy: 1
};
// Since all your event handlers do pretty much the same thing (set the value of the
// clicked element into a particular variable, we can simplify things greatly by setting
// up two arrays: one for the varaibles to store data and one for the question groups.
// Then, we can just match the index of the question group to the index of the variable
// and we'll only need one function:
var questionGroups = ["Type of Base Plate", "Age", "Anatomical Region", "Type of Patient", "Accuracy"];
var vars = ["basePlate", "age", "region", "patientType", "accuracy"];
// Next, we'll set up just one callback function for all radio buttons, but
// not all browsers will treat the HTML Collection returned from
// .querySelectorAll() as an array, which means that .forEach()
// won't work on questions unless you explicitly convert it
// to an array.
// Also, the convention for capitalization of identifiers is to use
// PascalCase for constructor functions, ALLCAPS for constants and
// camelCase for everything else.
var questions = Array.prototype.slice.call(document.querySelectorAll('input[type=radio]'));
questions.forEach((radio)=>{
radio.addEventListener('change',(e)=>{
// Get the text of the legend of the current radio button's fieldset
var leg = e.target.parentElement.querySelector("legend").textContent;
// Look up the index number of that text in the questionGroups array:
var idx = questionGroups.indexOf(leg);
// Set the corresponding variable in the variables array to the value of the
// radio button that just got changed:
scopeObject[vars[idx]] = e.target.value;
});
});
function getValues() {
// Throw out old result
result = null;
// Loop through all the properties in our scope object and sum all the values
for(var prop in scopeObject){
// The + in front of scopeObject is needed to explicitly convert the string
// values from the radio buttons into numbers so that the addition works
result += +scopeObject[prop];
}
answer.textContent = result;
}
/* Don't use <br> as a styling tool. That's what CSS is for. */
fieldset {
margin-bottom:1em; /* This puts one line of space below each fieldset. No <br> needed. */
}
<article>
<h1 class="headings">New Mask</h1>
<fieldset>
<!-- Fieldsets get <legend>, not <label> -->
<legend>Type of Base Plate</legend> <br>
<input type="radio" name="type" value="10000" checked>High Precision<br>
<input type="radio" name="type" value="20000"> Push-Pin<br>
</fieldset>
<fieldset>
<legend>Age</legend>
<input type="radio" name="age" value="1000" checked> Adult <br>
<input type="radio" name="age" value="2000"> Paediatric <br>
</fieldset>
<fieldset>
<legend>Anatomical Region</legend>
<input type="radio" name="anatomical" value="100" checked> Brain<br>
<input type="radio" name="anatomical" value="200"> Head, Neck and Shoulders<br>
</fieldset>
<fieldset>
<legend>Type of Patient</legend>
<input type="radio" name="patient" value="10" checked> Curative<br>
<input type="radio" name="patient" value="20"> Palliative<br>
<input type="radio" name="patient" value="30"> Claustrophobic<br>
</fieldset>
<fieldset>
<legend>Accuracy</legend>
<input type="radio" name="accuracy" value="1" checked> < 1mm<br>
<input type="radio" name="accuracy" value="2"> < 2mm<br>
</fieldset>
<!-- Don't use a "submit" button when you aren't submitting data anywhere.
And, don't use inline HTML event attribtues. Do event binding in JavaScript. -->
<button type="button" value="Submit">Submit</button>
<p id="answer"></p>
</article>
Now, having shown that example, if you really think about it, why do you need to get the total calculated each time the user changes a radio button value, when you aren't actually asking for that value until the submit button is clicked? Essentially, if I click away on those buttons, but never click submit, I will have executed the code many times for no reason. That scenario also uses more memory that it needs to because each and every radio button has to now store its own change event callback function. The better approach is to simply get the sum of all the checked radio button values when the user clicks submit. That solution is even simpler:
// Get reference to the HTML elements that we'll need individual access to:
var answer = document.getElementById("answer");
var submit = document.querySelector("button[type=button]");
// Set up event binding in JavaScript, not HTML
submit.addEventListener("click", getValues);
function getValues() {
// Get only the checked radio buttons (notice the ":checked" in the selector)
// into an HTML collection and then convert that collection into an array:
var questions = Array.prototype.slice.call(document.querySelectorAll('input[type=radio]:checked'));
// Will store final answer:
var result = null;
questions.forEach((radio)=>{
// Remember: HTML values are strings. To do math, you need to
// convert the strings to numbers. The "+" right in front of "radio.value"
// does this.
result += +radio.value;
});
// Output the answer into the HTML
answer.textContent = result;
}
/* Don't use <br> as a styling tool. That's what CSS is for. */
fieldset {
margin-bottom:1em; /* This puts one line of space below each fieldset. No <br> needed. */
}
<article>
<h1 class="headings">New Mask</h1>
<fieldset>
<!-- Fieldsets get <legend>, not <label> -->
<legend>Type of Base Plate</legend> <br>
<input type="radio" name="type" value="10000" checked>High Precision<br>
<input type="radio" name="type" value="20000"> Push-Pin<br>
</fieldset>
<fieldset>
<legend>Age</legend>
<input type="radio" name="age" value="1000" checked> Adult <br>
<input type="radio" name="age" value="2000"> Paediatric <br>
</fieldset>
<fieldset>
<legend>Anatomical Region</legend>
<input type="radio" name="anatomical" value="100" checked> Brain<br>
<input type="radio" name="anatomical" value="200"> Head, Neck and Shoulders<br>
</fieldset>
<fieldset>
<legend>Type of Patient</legend>
<input type="radio" name="patient" value="10" checked> Curative<br>
<input type="radio" name="patient" value="20"> Palliative<br>
<input type="radio" name="patient" value="30"> Claustrophobic<br>
</fieldset>
<fieldset>
<legend>Accuracy</legend>
<input type="radio" name="accuracy" value="1" checked> < 1mm<br>
<input type="radio" name="accuracy" value="2"> < 2mm<br>
</fieldset>
<!-- Don't use a "submit" button when you aren't submitting data anywhere.
And, don't use inline HTML event attribtues. Do event binding in JavaScript. -->
<button type="button" value="Submit">Submit</button>
<p id="answer"></p>
</article>
var ...on each of your functions, you are declaring new variables whose scopes are only inside your functions, so when callinggetValuesall your variables are undefined, remove all yourvarfrom your functions, and try again