Looping through multiple divs and pulling each input value from each - javascript

I have created an html page the will dynamically add or remove inputs, all within a parent div, each having their own div to determine each seperatly. I have the logic to loop through and find these child divs, however I cannot seem to figure out how to grab the inputs from each div, only the first child div even though I am looping through all children.
Any idea how?
html:
<div id="volumeRateDiv">
<div id="volumeRateDivNew_0" class="volumeRateDivChild">
<input id="kc_start" type="number" name="kc_start" maxlength="9" step="1" min="0" placeholder="0">
<input id="volume_rate" type="number" name="volume_rate" maxlength="12" step=".0001" min="0" placeholder="0.0000">
<input id="delete_VolumeRate" type="button" name="delete_VolumeRate" value="Delete" onclick="removeItem('volumeRateDivNew_0')">
</div>
<div id="volumeRateDivNew_1" class="volumeRateDivChild">
<input id="kc_start" type="number" name="kc_start" maxlength="9" step="1" min="0" placeholder="0">
<input id="volume_rate" type="number" name="volume_rate" maxlength="12" step=".0001" min="0" placeholder="0.0000">
<input id="delete_VolumeRate" type="button" name="delete_VolumeRate" value="Delete" onclick="removeItem('volumeRateDivNew_1')">
</div>
</div>
Javascript:
var divs = document.getElementsByClassName("volumeRateDivChild");
for(var i = 0; i < divs.length; i++)
{
var div = divs[i];
alert (div.className+" - "+div.id+" - "+document.getElementById("kc_start").value );
}

You could add the same index number (0, 1, etc) to the end of the inputs' IDs, and then use that in the for loop, eg:
for(var i = 0; i < divs.length; i++)
{
var div = divs[i];
alert (div.className+" - "+div.id+" - "+document.getElementById("kc_start_" + i).value );
}

The first comment in your answer is correct all id's should be unique.
If you can be certain that the input you want to extract the value of is always the first child then you could do the same as this jsfiddle
<div id="volumeRateDiv">
<div id="volumeRateDivNew_0" class="volumeRateDivChild">
<input id="kc_start" type="number" name="kc_start" maxlength="9" step="1" min="0" placeholder="0" value="0"/>
<input id="volume_rate" type="number" name="volume_rate" maxlength="12" step=".0001" min="0" placeholder="0.0000"/>
<input id="delete_VolumeRate" type="button" name="delete_VolumeRate" value="Delete" onclick="removeItem('volumeRateDivNew_0')"/>
</div>
<div id="volumeRateDivNew_1" class="volumeRateDivChild">
<input id="kc_start" type="number" name="kc_start" maxlength="9" step="1" min="0" placeholder="0" value="0"/>
<input id="volume_rate" type="number" name="volume_rate" maxlength="12" step=".0001" min="0" placeholder="0.0000"/>
<input id="delete_VolumeRate" type="button" name="delete_VolumeRate" value="Delete" onclick="removeItem('volumeRateDivNew_1')"/>
</div>
</div>
var divs = document.getElementsByClassName("volumeRateDivChild");
for(var i = 0; i < divs.length; i++)
{
var div = divs[i];
alert (div.className+" - "+div.id+" - "+div.children[0].value );
}

First of all, as #tymeJV already had mentioned, ids of HTML elements must be unique. So you need remove them or make them unique, if you plan to use them anywhere else (not in this case).
To locate elements inside your divs you could use classes or names. You can call getElementsByClassName or getElementsByName not only on document, but on any DOM-element. It could look like this:
var divs = document.getElementsByClassName("volumeRateDivChild");
for(var i = 0; i < divs.length; i++)
{
var div = divs[i];
alert(div.className+" - "+div.id+" - "+div.getElementsByName("kc_start")[0].value );
}

Do it this way
var divs = document.getElementsByClassName("volumeRateDivChild");
for(var i = 0; i < divs.length; i++)
{
var div = divs[i];
alert (div.className+" - "+div.id+" - "+div.children["kc_start"].value );
}
Demo: Demo

Related

How to reset JavaScript code when input value is changed?

I would like for the code to change its answer when I change the value of the input.
So let's say instead of 10, I would like it to tell me how much HP (health points) I will have at level 15. Is there any way I can do this? I'm not that experienced in Javascript.
So right now I coded it to default to 10 on all stats. My website tells me that at level 10, I have 895.4 hp. The only problem is that it won't stay at 15 when I try to press enter. It will just revert back to 10. Pretty much useless. Is there any way to keep that number 15 when I press enter?
var finalhp = 500;
let hpmultiplier = 1.06;
var hpvaluestring = document.querySelector('.hp').value;
var hpvalue = parseInt(hpvaluestring);
for (let i = 0; i < hpvalue; i++) {
var finalhp = finalhp * hpmultiplier
}
console.log(finalhp)
<form>
<div>
<input class="hp" id="amount" type="number" value="10" min="0" max="50" oninput="rangeInput.value=amount.value">
<input class="slider" id="rangeInput" type="range" value="10" min="0" max="50" oninput="amount.value=rangeInput.value">
</div>
</form>
Add a form submit event listener to the form element and prevent form submission there.
<form onsubmit="submitForm(event)">
<div>
<input class="hp" id="amount" type="number" value="10" min="0" max="50" oninput="rangeInput.value=amount.value">
<input class="slider" id="rangeInput" type="range" value="10" min="0" max="50" oninput="amount.value=rangeInput.value">
</div>
</form>
Add a submitForm function inside a script tag
function submitForm(event){
event.preventDefault();
var finalhp = 500;
let hpmultiplier = 1.06;
var hpvaluestring = document.querySelector('.hp').value;
var hpvalue = parseInt(hpvaluestring);
for (let i = 0; i < hpvalue; i++) {
var finalhp = finalhp * hpmultiplier
}
console.log(finalhp)
}
So mainly I'm just adding eventListeners to trigger the function calculateHP on input/slider value change. The function calculateHP contains the same logic that you shared. I did this so that the eventListeners can callback the function.
Try the following:
const input = document.querySelector('.hp')
const slider = document.querySelector('.slider')
slider.addEventListener('change', calculateHP)
input.addEventListener('change', calculateHP)
function calculateHP(){
let multiplier = 1.06
let level = Number(input.value)
let HP = 500
for(let i = 0; i<level; i++){
HP = HP * multiplier
}
return console.log(HP)
}
<div>
<label>Level: </label>
<input class="hp" id="amount" type="number" value="10" min="0" max="50" oninput="rangeInput.value=amount.value">
<input class="slider" id="rangeInput" type="range" value="10" min="0" max="50" oninput="amount.value=rangeInput.value">
</div>

Display values of multiple input type range in one page

I'm trying to display values of every slider I have on my page, this is my code so far:
var i = 0;
var st = 'slider';
var ot = 'output';
var s = '';
var o = '';
for (var x = 0; x < 3; x++) {
i++;
s = st+i;
o = ot+i;
var s = document.getElementById("range"+i);
var o = document.getElementById("limit"+i);
o.innerHTML = s.value;
s.oninput = function() {
o.innerHTML = this.value;
}
}
<div id="slidecontainer">
<input type="range" min="2" max="50" value="20" class="slider" id="range1" >
<label>You chose <span id="limit1"></span></label>
</div>
<div id="slidecontainer">
<input type="range" min="2" max="50" value="20" class="slider" id="range2" >
<label>You chose <span id="limit2"></span></label>
</div>
<div id="slidecontainer">
<input type="range" min="2" max="50" value="20" class="slider" id="range3" >
<label>You chose <span id="limit3"></span></label>
</div>
It's only changing the last value when I move any slider, I want to display the value of each slider respectively. I'm using a loop in my JavaScript code because I have more than 20 sliders and I don't want to write a function for each of them unless that is the only way of doing it. Any suggestions?
The problem you are having is related to variable scope. There is only one variable named o, each iteration of the loop changes this variable. So when the
oninput function is evaluated o equals the last value you set it to equal. The current value of o is not "saved" in the function definition.
See https://www.w3schools.com/js/js_scope.asp for more information.
See solution below, here I find the limit in each call to the function.
function updateLabel() {
var limit = this.parentElement.getElementsByClassName("limit")[0];
limit.innerHTML = this.value;
}
var slideContainers = document.getElementsByClassName("slidecontainer");
for (var i = 0; i < slideContainers.length; i++) {
var slider = slideContainers[i].getElementsByClassName("slider")[0];
updateLabel.call(slider);
slider.oninput = updateLabel;
}
<div class="slidecontainer">
<input type="range" min="2" max="50" value="20" class="slider">
<label>You chose <span class="limit"></span></label>
</div>
<div class="slidecontainer">
<input type="range" min="2" max="50" value="20" class="slider">
<label>You chose <span class="limit"></span></label>
</div>
<div class="slidecontainer">
<input type="range" min="2" max="50" value="20" class="slider">
<label>You chose <span class="limit"></span></label>
</div>

JS/jQuery: fire onchange from a disabled/readonly input without using button

The goal is to get the total Qty for the whole year.
The user will input numbers into 3 different textboxes(Jan,Feb,Mar), then the sum will be displayed into a disabled textbox(Quarter1).
Now I have 4 instances of these knowing we have 4 quarters/year.
I can easily display the sum per quarter, by using the onchange() function attached to the textboxes.
Now I am having issues getting the sum from the 4 disabled textboxes, knowing we can't use the onchange() on it because it's disabled.
I have searched and probably getting results only when a button is used.
TLDR: I am trying to display the sum from the four disabled textboxes to another textbox automatically, without the user clicking any button(just like firing the onchange event)
I have tried this one, wherein I tried to display the value of the first quarter to the total, and not working:
$(document).ready(function() {
$('input[id$=yearlyTotal]').bind("displaytotal", function() {});
$('#qtr1').change(function() {
var mos = document.getElementsByClassName("quantityA");
var mosCount = mos.length;
var total = 0;
for (var i = 0; i < mosCount; i++) {
total = total + parseInt(mos[i].value);
}
$('input[id$=yearlyTotal]').val(total).trigger('displaytotal');
});
});
Hope it's possible, thanks in advance
EDIT: Added UI
Showing Q1 (its just the same for the 4 qtrs)
<div class="form-group col-md-6">
<label class="col-sm-1 control-label">Jan:</label>
<div class="col-sm-2 small">
<input type="number" min="0" id="col3" class="form-control input-sm monthly" data-q="q1" name="January" />
</div>
<label class="col-sm-1 control-label">Feb:</label>
<div class="col-sm-2 small">
<input type="number" min="0" id="col4" class="form-control input-sm monthly" data-q="q1" name="February" />
</div>
<label class="col-sm-1 control-label">Mar:</label>
<div class="col-sm-2 small">
<input type="number" min="0" id="col5" class="form-control input-sm monthly" data-q="q1" name="March" />
</div>
<label class="col-sm-1 control-label">Q1:</label>
<div class="col-sm-2 small">
<input type="text" min="0" id="q1" class="form-control input-sm quarter" name="q1" style="background-color: #b3dcf5;" disabled />
</div>
</div>
This is the div for the total Qty
<div class="col-md-6">
<label class="col-sm-3 control-label" id="">Total Quantity:</label>
<div class="col-sm-3 small">
<input type="text" id="final" class="form-control input-sm" name="TotalQuantity" value="0" disabled />
</div>
</div>
Method 1:
Basically, what you need to do is to trigger the change event for the disabled quarter fields programatically, using jQuery .trigger() function.
As I don't know how your HTML is structured -this why it is always recommended to provide MCVE example- I made a demo example and I've done things differently, like below:
jsFiddle 1
var monthly = $('.monthly'),
Qrt = $('.quarter');
monthly.on('change, input', function() {
var $th = $(this),
// depending on the value of the data-q attribute, we pick
// all input fields with the same data-q as an array, then
//loop through them adding their values up
q = $th.attr('data-q'),
qArray = $th.parent().children('input[data-q="' + q + '"]'),
tempSum = 0;
for (var i = 0, ln = qArray.length; i < ln; i++) {
tempSum += +$(qArray[i]).val();
}
// we pick the corresponding quarter sum field, again depending
// on the value of the data-q attritues, and update its value, then
// we trigger the change event of this quarter sum field.
$('#' + q).val(tempSum).trigger('change'); // here you trigger it
});
Qrt.on('change', function() {
var qSum = 0;
for (var i = 0, ln = Qrt.length; i < ln; i++) {
qSum += +$(Qrt[i]).val();
}
$('#final').val(qSum);
});
.monthly { width: 32%; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<h3>Grand Total:</h3><input type="text" id="final" disabled><hr>
<h3>1st Q:</h3>
<input type="text" class="monthly" data-q="q1">
<input type="text" class="monthly" data-q="q1">
<input type="text" class="monthly" data-q="q1">
<br>Sum:<input id="q1" type="text" class="quarter" disabled>
<h3>2nd Q:</h3>
<input type="text" class="monthly" data-q="q2">
<input type="text" class="monthly" data-q="q2">
<input type="text" class="monthly" data-q="q2">
<br>Sum:<input id="q2" type="text" class="quarter" disabled>
<h3>3rd Q:</h3>
<input type="text" class="monthly" data-q="q3">
<input type="text" class="monthly" data-q="q3">
<input type="text" class="monthly" data-q="q3">
<br>Sum:<input id="q3" type="text" class="quarter" disabled>
<h3>4th Q:</h3>
<input type="text" class="monthly" data-q="q4">
<input type="text" class="monthly q-4th" data-q="q4">
<input type="text" class="monthly q-4th" data-q="q4">
<br>Sum:<input id="q4" type="text" class="quarter" disabled>
Method 2:
since any change you make to any .monthly field will change the corresponding value of quarter sum, and thus it'll also affect the value of the yearly sum, you don't need to capture the change event of the disabled quarter sum fields, just loop through their values and update the value of the yearly field, all should be done inside the on('change') event of the .monthly fields, like below:
jsFiddle 2
jQuery
var monthly = $('.monthly'),
Qrt = $('.quarter');
monthly.on('change, input', function() {
var $th = $(this),
q = $th.attr('data-q'),
qArray = $th.parent().children('input[data-q="' +q+ '"]'),
tempSum = 0,
qSum = 0;
for (var i = 0, ln = qArray.length; i < ln; i++) {
tempSum += +$(qArray[i]).val();
}
$('#' + q).val(tempSum);
// code below
for (var i = 0, ln = Qrt.length; i < ln; i++) {
qSum += +$(Qrt[i]).val();
}
$('#final').val(qSum);
});
Update:
For the updated HTML in the OP, replace qArray line with this one:
$th.parents('.form-group').find('input[data-q="' + q + '"]')`,
Note parents() is with "s" letter, unlike the former parent() which moves up a single level up the DOM, it does " search through the ancestors of these elements in the DOM tree and construct a new jQuery object from the matching elements ordered from immediate parent on up. ", so it travels up until we reach the matchng parent, here it is .form-group.
Then instead of children(), we use find().
jsFiddle 3
Please find the below code (Finding the total for quarter A & quarter B) for your reference. Please use same methodology for other quarters.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
/* FINDING THE QUARTER A AND QUARTER B */
function findingQuaterTotal () {
/* LOADING QUARTER A AND FINDING ITS TOTAL - STARTS */
var mosQuarterA = document.getElementsByClassName("quarterA"),
mosCountQuarterA = mosQuarterA.length,
totalQuarterA = 0,
i = 0;
for (i = 0; i < mosCountQuarterA; i++) {
totalQuarterA = totalQuarterA + parseInt(mosQuarterA[i].value);
}
/* ADDING INTO QUATER A DISABLED TEXTBOX */
$("#quarterA").val(totalQuarterA);
/* LOADING QUARTER A AND FINDING ITS TOTAL - ENDS */
/* LOADING QUARTER B AND FINDING ITS TOTAL - STARTS */
var mosQuarterB = document.getElementsByClassName("quarterB"),
mosCountQuarterB = mosQuarterB.length,
totalQuarterB = 0;
for (i = 0; i < mosCountQuarterB; i++) {
totalQuarterB = totalQuarterB + parseInt(mosQuarterB[i].value);
}
/* ADDING INTO QUARTER B DISABLED TEXTBOX */
$("#quarterB").val(totalQuarterB);
/* LOADING QUARTER B AND FINDING ITS TOTAL - ENDS */
/* TRIGGERING CHANGE EVENT IN THE DISABLED TEXTBOX WHOSE ID STARTS WITH QUARTER.*/
$("input[id^='quarter']").trigger("change");
};
/* ABOVE CHANGE TRIGGER WILL CALL BELOW EVENTS - STARTS */
$("input[id^='quarter']").change(function () { $("#final").val(parseInt($("#quarterA").val())+parseInt($("#quarterB").val()));
});
/* ABOVE CHANGE TRIGGER WILL CALL BELOW EVENTS - ENDS */
/* IF ANY VALUE CHANGES IN MONTH TEXT BOX, FLLWING FUNCTION WILL BE CALLED - STARTS */
$("input[id^='month']").on("change keyup",function () {
findingQuaterTotal();
});
findingQuaterTotal();
/* IF ANY VALUE CHANGES IN MONTH TEXT BOX, FLLWING FUNCTION WILL BE CALLED - ENDS */
});
</script>
</head>
<body>
<h2>Quater A</h2>
Jan - <input type="number" id="month1" value="6" class="quarterA"></br>
Feb - <input type="number" id="month2" value="16" class="quarterA"></br>
March - <input type="number" id="month3" value="25" class="quarterA"></br>
Quater A Total - <input type="number" id="quarterA" value="" disabled></br>
<br/><br/>
<h2>Quater B</h2>
April - <input type="number" id="month4" value="6" class="quarterB"></br>
May - <input type="number" id="month5" value="16" class="quarterB"></br>
June - <input type="number" id="month6" value="25" class="quarterB"></br>
Quater B Total - <input type="number" id="quarterB" value="" disabled></br>
Quarter A and Quarter B total - <input type="number" id="final" value="" disabled>
</body>
</html>

How to make array of values of objects

<input name="hello">value1
<input name="hello">value2
<input name="hello">value3
<input name="hello">value4
var a = getElementsByName('hello')
Now, how do I create an array that contains (value1,value2,value3,value4)?
I thought of using makeArray, but it returns just the objects not the values.
You can iterate over them, or use map.
var items = Array.prototype.map.call(a, function(el){
return el.nextSibling.textContent;
});
demo
var items = [];
for (var i=0; i<a.length; i++) {
items.push(a[i].nextSibling.textContent);
}
demo
First of all your html should look like that:
<input name="hello1" value="value1" type="text" />
<input name="hello2" value="value2" type="text" />
<input name="hello3" value="value3" type="text" />
<input name="hello4" value="value4" type="text" />
I.e. if you are using text boxes your name attribute should be different. Otherwise you can't get the values. And of course the values are actually attributes. Here is a pure javascript code which could do what you want:
var inputs = document.querySelectorAll("input[type='text']");
var result = [];
for(var i=0; field=inputs[i]; i++) {
result.push(field.value);
}
alert(result);
And here is a jsfiddle demonstrating the example http://jsfiddle.net/krasimir/nbmjG/
You should do this like:
HTML:
<input type="text" id="hello1" value="value1">
<input type="text" id="hello2" value="value2">
<input type="text" id="hello3" value="value3">
<input type="text" id="hello4" value="value4">
JS:
alert('ready?');
var n = 4;
var arr = new Array(n);
for(var i = 0; i < n; i++) {
arr[i] = document.getElementById('hello' + (i+1)).value;
}
alert(arr);
DEMO
Your inputs have to be like so: Demo
<input name="hello" value="value1">
<input name="hello" value="value2">
<input name="hello" value="value3">
<input name="hello" value="value4">
Then following will return array of values:
var arr = Array.prototype.map.call(document.getElementsByName('hello'), function(elem){
return elem.value;
});
You need to use []
<input name="hello[]">value1</input>
<input name="hello[]">value2</input>
<input name="hello[]">value3</input>
<input name="hello[]">value4</input>

Add and remove inputs dynamicly with a other input

I searched a lot for this, but I can only find +1 -1 solutions.
But I want to set the number of inputs with a other input like this:
//Enter the number of inputs (1 is the start-value)
<input type="text" size="3" maxlength="3" id="count" name="count" value="1">
//Display that number of inputs (1 at start)
<input type="text" size="30" maxlength="30" id="input_1" name="input_1">
When the user now writes 5 in the first field, the form should look like this:
//Enter the number of inputs (1 is the start-value)
<input type="text" size="3" maxlength="3" id="count" name="count" value="1">
//Display that number of inputs (1 at start)
<input type="text" size="30" maxlength="30" id="input_1" name="input_1">
<input type="text" size="30" maxlength="30" id="input_2" name="input_2">
<input type="text" size="30" maxlength="30" id="input_3" name="input_3">
<input type="text" size="30" maxlength="30" id="input_4" name="input_4">
<input type="text" size="30" maxlength="30" id="input_5" name="input_5">
How can I make this? MUST I use js?
Here's a simple javascript snippet that doesn't make use of any frameworks:
function addInputs() {
var count = parseInt(document.getElementById("count").value);
for (var i = 2; i <= count; i++) {
document.getElementById('moreinputs').innerHTML += '<input type="text" name="input_' + i + '" id="input_' + i + '" />';
}
}
In this example you have to add a container (div) with id 'moreinputs'. However, when calling this function more than once, it will not work properly (e.g. it can only increase the number of input but not decrease)
Yes, either you use javascript, or you send the form to the server, where a new html page with all the inputs is generated (e.g. with PHP).
Yes you must use js to do it dynamically on the spot You have a jQuery tag so I will show an example in jQuery
This is not the best example but it works and it's a starting point
JS:
$(function(){
$('#master').on('change', function() {
var count = $(this).val();
$('#otherInputs').html('')
for( var i = 0; i < count; i++) {
$('#otherInputs').append(
$('<input>', {type: 'text'})
);
}
});
});
HTML:
<input type="number" id="master" value="1">
<div id="otherInputs"></div>
Demo
In English this is saying...
When you change #master I will empty #master (html('')) loop through and append a new input depending on #master's value
Here's the FIDDLE. Hope it helps. :)
html
<input type="text" size="3" maxlength="3" id="count" name="count" value="1">
<div id="container"></div>
script
$('#count').on('keyup', function () {
var $this = $(this);
var count = $this.val();
$('#container').empty();
for (var x = 1; x <= count; x++) {
var newInput = '<input type="text" size="30" maxlength="30" id="input_' + x + '" name="input_' + x + '">';
$('#container').append(newInput);
}
});
This worked for me
function AddField() {
var count = $("#countetfield").val();
var i = 1;
var id = $("#container .testClass:last").attr('name');
var test = id.split("_");
id_name = test[1];
while (i <= count) {
id_name++;
var a = '<input type="text" class="testClass" size="30" maxlength="30" id="input_' + id_name + '" name="input_' + id_name + '"/>';
$("#container").append(a);
i++;
}
}
<input type="text" id="countetfield" value="1" />
<input type="button" value="Go" onclick="AddField();" />
<div id="container">
<input type="text" class="testClass" size="30" maxlength="30" id="input_1" name="input_1" />
</div>

Categories

Resources