How do I reference text boxes using a variable - javascript

So I am making a small quiz on JavaScript for the first time. I wanted the user to be able to select between 3 options(a, b and c) by entering the letter in a text box and clicking a button to check the answer. A text will then appear underneath the text box to show whether the user entered the right option or not.
I have managed to make this work but since there are multiple questions, I wanted to use a for loop to loop through each text box (I named each text box "0", "1" ...) but I cannot reference them using i. How can I do it?
Here is my JavaScript:
var answer = ["a", "b", "c"];
var results = "results"
function check() {
for (i = 1; i = 4; i++) {
var input = document.getElementById(i).value;
if (input == answer[parseInt(i-1)]) {
document.getElementById(results.concat(i)).innerHTML = "Correct";
}
else {
document.getElementById(results.concat(i)).innerHTML = "Wrong";
}
}
}
Here is the HTML (I repeated the same code for each question with a different ID):
<input type="text" id="0" value="a, b or c"><br>
<input type=button value="Check" onClick="check()"><br>
Result: <span id="results0"></span><br><br>

This should work:
There are a few things wrong with your original code
Wrong:
for (i = 1; i = 4; i++)
usually we start our iterations on 0 index, also the middle portion of the for loop should return truthy which means it should evaluate to true or false "i = 4" will never be either because = is an assignment operator, you should use evaluation operators >, <, >=, ==, etc.
for (i = 0; i < 3; i++) {
var input = document.getElementById(i).value;
if (input == answer[i]) {
document.getElementById("results" + i).innerHTML = "Correct";
}
else {
document.getElementById("results" + i).innerHTML = "Wrong";
}
}
Additionally you were using "result" like a variable in this:
results.concat(i)
So results would need to be a variable that contains the string "results" which I doubt is the case. so what we are telling the getElementById method by doing it this way
document.getElementById("results" + i)
is to find an element with an ID of "results" plus the index of the loop eg. id="result0", or id="result1" etc.

If you have all of these within a <div> or div tag you can reference them using :nth-child notation. This works by referencing the nth child from the beginning.
$("div:nth-child(i)");

With the html you provided your for loop is incorrect.
Since you started your input at 0 you want to start looping at 0.
for (i = 0; i <= 2; i++) { //with three values 0,1,2
...
}
Your <span> tag also need to be closed with a </span>

Looping through id's feels very dirty to me. From a maintenance and readability standpoint, I recommend you loop through a collection of Nodes instead.
I believe that you are looking for:
document.getElementsByClassName("someClass")[0];
Where [0] Would be the index of the element whos class is shared.
Here is a code sample I wrote for you to reference using textboxes and outputting the values into a div within a for loop.
https://jsfiddle.net/4ocnyy38/1/

You can dynamically create inputbox and result span and alot dynamic ids to them and then check the correct answer on click of button
Javascript:
var answer = ["a", "b", "c"];
var results = "results";
setTimeout(function(){
var injectData='';
for(var i=0;i<3;i++){
injectData+="<input type='text' id='id_"+i+"' placeholder='a, b or c'/> Result: <span id='results_"+i+"'></span><br/>";
}
document.getElementById('inject').innerHTML=injectData;
},500);
function check() {
for (i = 0; i <3; i++) {
var input = document.getElementById('id_'+i).value;
if (input == answer[i]) {
document.getElementById("results_"+i).innerHTML = "Correct";
}
else {
document.getElementById("results_"+i).innerHTML = "Wrong";
}
}
}
HTML:
<div id="inject">
</div>
<input type=button value="Check" onClick="check();"><br>
Demo: https://jsfiddle.net/9ea46of5/

Related

JS loop and maintain index of parameters that meet condition

I have a bunch of div's that I'm selecting by getElementsByClassName let's call it:
let myDivs = document.getElementsByClassName('small-divs');
I need to set innerText conditionally to myDivs depending on whether each <div> in myDivs is style.visibility != 'hidden'
So I'm looping using a for loop and within the loop I have the condition checking for visibility:
for(let i=0; i < myDivs.length; i++){
if(myDiv[i].style.visibility != 'hidden'){
myDiv[i].innerText = letter + i; // letter is a user defined array of letters to use for 'rows'
}
}
This is working as it should but my problem is that I need the i in letter + i to begin from 1 rather than from the element's index that meets the condition. Here's a pictorial of what I have:
This is before hiding any divs:
And here's what I have after hiding some divs and running the above code. Notice that the inner text starts from the index that meets the conditions. For instance I need "row K" to start from K1
How can I achieve this? Seems like a small step I should do that I'm missing
Do you mean something like this? Use a counter which increments only when a non-hidden div is found
let number = 1;
for(let i=0; i < myDivs.length; i++){
if(myDiv[i].style.visibility != 'hidden'){
myDiv[i].innerText = letter + number; // letter is a user defined array of letters to use for 'rows'
number += 1;
}
}

Javascript For Loop will not increment

I am trying to use a for loop to push values entered by a user into an array. But, for some reason, the loop will not increment to push the next value into the array but will instead overwrite the first location. This is the HTML used to get the user's input below.
<div class="total-budget-fields">
<h3>Enter Budget</h3>
<input type="number" placeholder="$1000" id="budget">
<input type="button" onclick="addNum();" class="btn hit" id="budget" value="Calculate">
</div>
And this here is the javascript function linked to the button below.
addNum = () => {
// console.log('addNum');
var budgetArray = [];
var budget = document.getElementById('budget').value;
for (i=0; ; i++) {
if (budget.trim() == '') {
alert("Field is Empty!");
} else if (!(isNaN(budget))) {
budgetArray.push(budget);
break;
}
}
console.log(budgetArray);
console.log(i);
}
I tried using a while loop as an alternative which didn't work. Any and all help is welcomed, thank you in advanced!
Like already mentioned in the comments, the loop makes non sense and you dont need an index variable like i. Instead make the array global and just push new values. This will increase the size of the array automatically. If budgetArray is in the scope of your function, it is created on every call of this function.
var budgetArray = [];
addNum = ()=>{
var budget = document.getElementById('budget').value;
if (budget.trim() == '') {
alert("Field is Empty!");
} else if (!(isNaN(budget))) {
budgetArray.push(budget);
}
}
Also in your markup file two elements has the same id budget. You should fix that and make your id's unique across your whole document. It currently works because if there is more than one element with the same id, getElementById will just give you the first one.
The first problem is that on every click you are reassigning you budgetArray to be an empty array. This is why you will always have only one item in the array.
You have to cache your array outside the addSum function. As your budget container will not change during the time, it is a good idea to cache it as well.
Also, you do not need for loop for this task at all. So something like this will do the job.
var budgetArray = [];
var budgetContainer = document.getElementById('budget');
addNum = () => {
const budget = budgetContainer.value.trim();
if (budget == '') {
alert("Field is Empty!");
} else if (!(isNaN(budget))) {
budgetArray.push(budget);
}
}
console.log(budgetArray);
console.log(i);

JavaScript array.sort() Issue

drafting up a quick listing tool to list local kids baseball teams. Takes a couple of inputs and writes to a text field. There's some validation and whatnot too, but that's out of scope and doesn't seem to be impacting things.
Problem is, I'm having trouble figuring out how to "capture" the existing text, add the new inputs and sort the whole lot, before writing the new result to the paragraph element (effectively replacing it).
So far I have:
var LeagueTeams = [];
var IndividualTeam = '';
LeagueTeams.push(document.forms[0].TeamName.value);
LeagueTeams.push(document.getElementById('TeamList')
LeagueTeams = LeagueTeams.sort();
for (j = 0; j < LeagueTeams.length; j++) {
IndividualTeam = LeagueTeams.pop();
IndividualTeam = IndividualTeam + '' + \n;
document.forms[0].TeamName.value += IndividualTeam;
}
What I end up getting is my input, and then an array of my input PLUS the previous contents, with a couple of line breaks. Setting the operator to = instead of =+ stops it from printing to the array at all.
i.e.
Enter: a
Text area: a
Then enter: b
Text area: a ab
(etc)
OK, now that we have a better idea of what you're trying to do, here's some code that will do that:
HTML:
<label>Enter Team Name: <input id="newTeam" type="text"></label>
<button id="add">Add</button><br>
All Teams:<br>
<textarea id="allTeams" rows="40" cols="40"></textarea>
Javascript (plain javascript, no framework, called after page is loaded):
var teamList = ["Dodgers", "Mets", "Giants"];
document.getElementById("add").onclick = function() {
var input = document.getElementById("newTeam");
if (input.value) {
teamList.push(input.value);
}
updateTeamList();
input.value = "";
}
function updateTeamList() {
teamList.sort();
var o = document.getElementById("allTeams");
o.value = teamList.join("\n");
}
updateTeamList();
And, you can see it working here: http://jsfiddle.net/jfriend00/HkhsL/
Comments on your existing code:
I'm not sure I understand what you're trying to do overall, but do you realize that this loop is going to have problems:
for (j = 0; j < LeagueTeams.length; j++) {
IndividualTeam = LeagueTeams.pop();
IndividualTeam = IndividualTeam + '' + \n;
document.forms[0].TeamName.value += IndividualTeam;
}
Each time you do LeagueTeams.pop() you are reducing the length of the array and you're continually comparing to LeagueTeams.length in the for loop. This will only get half way through the array because each time through the loop, you increment j and decrement LeagueTeams.length which means you'll only get half way through the array.
If you intend to iterate all the way through the array in your for loop, you should use this version that gets the length once initially and simplifies the code in the loop:
for (j = 0, len = LeagueTeams.length; j < len; j++) {
document.forms[0].TeamName.value += LeagueTeams.pop() + '\n';
}
or perhaps even better, this version that doesn't even use j:
while (LeagueTeams.length > 0) {
document.forms[0].TeamName.value += LeagueTeams.pop() + '\n';
}
Then further, I see that you're trying to use LeagueTeams.sort() on an array that has both strings in it and DOM object references. What are you trying to do with that sort because the built-in sort function does a lexigraphical sort (e.g. alpha) which will do something odd with a DOM reference (probably sort by whatever toString() returns which may be object type)?
If you want to sort the input by team name, then you would need to put both team name and the DOM reference into an object, insert that object into the array as one unit and then use a custom sort function that would sort by the name in the object. As your code is written above, you see to be using document.getElementById('TeamList') which is the same for all teams so I'm not sure why you're putting it into the array at all.
If you can show your HTML and a more complete version of your code, we could help further. What you have above is just a non-working piece of code and we don't know what your HTML looks like that it's trying to operate on.
FYI, there are several syntax errors in the code you posted, so this can't be running code:
Missing paren at the end of this: LeagueTeams.push(document.getElementById('TeamList'))
Missing quotes around \n: IndividualTeam = IndividualTeam + '' + '\n';
If you are just trying to make a list of the teams, try something like:
<script type="text/javascript">
function addTeam(form) {
var para = document.getElementById('teamList');
var teams = para.innerHTML.split(/<br\s*[\\]?>/);
teams.push(form.teamName.value);
para.innerHTML = teams.sort().join('<br>');
}
</script>
<form action="">
<input type="text" name="teamName">
<input type="button" value="Add team" onclick="addTeam(this.form)">
</form>
<p id="teamList"></p>
You may be using different elements or layout, but the strategy should be about the same. If you are making a set of options for a select, things are a little easier.

Can someone explain what this snippet of code is doing?

Im trying to learn javascript by tracing through some code at the moment, I was wondering if someone could explain what is happening in this snippet of code (this snippet is just part of a function hence no closing brace):
document.addEventListener("keydown",function(e){
for(i=0;i < keys.length; i++) {
if(e.keyCode == keys[i]){
var tri = document.getElementById("foo").childNodes[i];
if(i==0){
var tri = document.getElementById("foo").childNodes[1];
}
if(i==1){
var tri = document.getElementById("foo").childNodes[3];
}
if(i > 1) {
var tri = document.getElementById("foo").childNodes[(i*2)+1];
}
The part im confused about most in this is the childNodes[] and the if(i) statements?
// Bind an event handler to keydown on the entire document
document.addEventListener("keydown",function(e){
// Everything in here happens on keydown
// keys must be an array declared somewhere earlier in the code
// This loops through that array
for(i=0;i < keys.length; i++) {
// If the current key we are looking at in the array
// is the key that was pressed
if(e.keyCode == keys[i]){
// Get the (i+1)th childnode of foo
var tri = document.getElementById("foo").childNodes[i];
// If i = 0 get the second element (not the first)
if(i==0){
var tri = document.getElementById("foo").childNodes[1];
}
// If i == 1 get the fourth element (not the second)
if(i==1){
var tri = document.getElementById("foo").childNodes[3];
}
// Otherwise get the (i*2+2)th element.
if(i > 1) {
var tri = document.getElementById("foo").childNodes[(i*2)+1];
}
// Here we are still in an if-statement, in a loop, in a function,
// so there is probably more code here, at least some closing }'s
Note that var tri = document.getElementById("foo").childNodes[i]; is a useless line, because i cannot be negative, one of the next three if statements will always succeed and tri will be overwritten.
Also note that when i = 0, (i*2)+1 = 1 and when i = 1, (i*2)+1 = 3, so those other two if statements are useless as well because the third covers all cases and doesn't need to even be in an if clause. The above code is 100% equivalent to:
document.addEventListener("keydown",function(e){
for(i=0;i < keys.length; i++) {
if(e.keyCode == keys[i]){
var tri = document.getElementById("foo").childNodes[(i*2)+1];
...
Since i is the variable used to iterate through the array called keys, and the node selected depends on i. keys must be an array with an unusual purpose. It is an array of keyCodes, where the position of the keyCode in the array determines which node should be selected and stored in tri when that key is pressed.
Childnodes is the collection (array, effectively) of descendents of a DOM element.
E.g. consider some markup:
<div id='div1'>
<p id='p1'>
<span id='s1'>Span one</span>
<span id='s2'>Span two</span>
<span id='s3'>Span three</span>
</p>
</div>
in this scenario, document.getElementById('p1').childnodes[0] will return span with id='s1', childnodes[1] will return the span with id='s2' and so on.
http://www.w3schools.com/Dom/prop_element_childnodes.asp
More detail: https://developer.mozilla.org/En/DOM/Node.childNodes
People will complain about a link to w3schools.com, but imho it is adequate for quick intros to concepts.
It gets different DOM elements based on key being pressed.

How to go over all inputs that have a custom attribute

I have a form with checkboxes.
All of the checkboxes have an attribute called att, which contains several numbers that are separated by commas.
I'd like to create a function that gets a number, goes over all the checkboxes and checks all the checkboxes that their att attribute contains that number.
Can please someone point me at the right direction?
Using jQuery you can do something like
function myfunc(num)
{
$(":checkbox[att!='']").each(function()
{
var i, l, values = $(this).attr("att").split(",");
for (i = 0, l = values.length; i < l; ++i)
{
if (values[i] == num)
{
$(this).attr("checked", "checked");
break;
}
}
});
}
With JQuery you would use the attribute-contains selector to get all elements where an attribute contains a certain value.
$('input[att*="100"]').val('input has 100 in it!');
This loops over all input elements and gives you an array containing the values of att (split using the comma), so I'd add some logic to pick out only checkboxes:
for (var i = 0; i < document.getElementsByTagName('input'); i++)
{
var att_array = document.getElementsByTagName('input')[i].getAttribute('att').split(',');
}
This will get you all inputs with the attribute ATTR and then alerts the val of each of those. You can, of course, do whatever you want with the val when you have it.
$("input[ATTR]").each(function(){
alert($(this).attr("ATTR"))
})
If you want to limit this to checkboxes, change the selector as is shown below
$(":checkbox[ATTR]").each(function(){
alert($(this).attr("ATTR"))
})

Categories