Change name values with JavaScript - javascript

Been at this for a long time, and it seems so simple but I cannot get it to do what I want.
Each book has a 'getOrRequest' value that is selected using radio buttons. Every time a div is duplicated, the name value needs to be changed so that a book has its own getOrRequest value. I've finally got the duplicating down, but now renaming the correct inputs isn't cooperating.
What's really bugging me is that it works, but it's not changing the name values that I'm trying to grab. It has something to do with what parts of the array are being changed, but I can't get the values that I want, namely the last two getOrRequest names.
A working example of what I'm struggling with here.
My JS function:
function addAnotherPost(){
var bookInfo = document.getElementById('bookInformation');
var copyDiv = document.getElementById('addListing').cloneNode(true);
copyDiv.id = 'addListing' + idNumber;
bookInfo.appendChild(copyDiv);
var divID = 'addListing' + idNumber;
var newDiv = document.getElementById(divID);
var postType = document.getElementsByName("getOrRequest[]");
alert(postType[0].name + postType[1].name + postType[2].name + postType[3].name);
for(var i = 2; i < postType.length; i++){
postType[i].name = 'getOrRequest' + idNumber + '[]';
}
alert("got this far" + postType.length);
idNumber++;
}
The relevant chunk of HTML:
<div id='addListing'>
<table class='aListing'>
<tr>
<td>
<label>
<input type='radio' name='getOrRequest[]' value='1' />
Request</label>
<label>
<input type='radio' name='getOrRequest[]' value='0' />
Offer</label>
</td>
[...]
</table>
</div>

You are getting an object list for a specific name identifier:
var postType = document.getElementsByName("getOrRequest[]");
so postType is changing once you've renamed an element (Yes man that thing is inteligent)
console.log(postType.length); // = 4
postType[i].name = 'getOrRequest' + idNumber + '[]';
console.log(postType.length); // = 3
so basically the for loops changes because postType.length changes.
I guess what you want to do is something like:
postType[0].name = 'getOrRequest' + idNumber + '[]'; //ref changed.
postType[0].name = 'getOrRequest' + idNumber + '[]';
however thats bad style anyways you should clone from a marked source and rename by name before you append to something, like so ( http://jsfiddle.net/bHLZA/2/ ):
var bookInfo = document.getElementById('bookInformation');
var copyDiv = document.getElementById('addListing').cloneNode(true);
copyDiv.id = 'addListing' + idNumber;
postType = copyDiv.getElementsByTagName('input');
postType[0].name = 'getOrRequest' + idNumber + '[]';
postType[1].name = 'getOrRequest' + idNumber + '[]';
bookInfo.appendChild(copyDiv);
see http://jsfiddle.net/bHLZA/

Related

Javascript: how get all the values and id from an inputs array?

So I'm trying to get all the values and id of every input from an array, but I have an issue, the user can duplicate the input and each input have a randomly generated ID so I can't select the data with the ID and every input use name="cate[]" so every input have the same name, so I can use something like this:
function regTour() {
var input = document.getElementsByName('cat[]');
var k = "The respective values are :";
for (var i = 0; i < input.length; i++) {
var a = input[i];
k = k + "array[" + i + "].value= "
+ a.value + " ";
}
console.log('Console: ' + k);
}
but how I can get the ID from every input from the array paired with the input value?
Edit: -------------------
the input looks like this:
<input type="text" id="1666239497429" name="cat[]" class="form-control">
<input type="text" id="12983172462" name="cat[]" class="form-control">
<input type="text" id="812361647812" name="cat[]" class="form-control">
this input it's created dynamically by the user so the id changes, this id later it's stored with other sub fields that should be related with that id, that's why it's some kind important for me be able to store all the id's
You can get the id of DOM elements using the id property. From your example, just use a.id to access it.
Side note, you should use const instead of var if the variable is not going to be changed, and let if it does change. var shouldn't be used any more.
function regTour() {
var input = document.getElementsByName('cat[]');
var k = "The respective values are :";
for (var i = 0; i < input.length; i++) {
var a = input[i];
k = k + "array[" + i + "].value= "
+ a.value + " array[" + i + "].id= " + a.id;
}
console.log('Console: ' + k);
}
can you share more data from the front? how is your form?
This ist OK var input = document.getElementsByName('cat[]'); but I'm not sure what the problem is

Getting Data out of a container

I wrote a function that creates new Input fields based on the number of input fields needed. That code is below.
for (i=0;i<number;i++){
container.appendChild(document.createTextNode("Guest " + (i+1)));
var input = document.createElement("input");
input.id = "Guest" + i;
container.appendChild(input);
container.appendChild(document.createElement("br"));
console.log(i.value);
It creates a new Id for each input field. In the function below,depending on the number you set for i, the function creates a generated message.
function sendInput ()
{
var guestNames = document.getElementById("Guest").value
var personName = document.getElementById("people").value;
var eventType = document.getElementById("event").value;
var date = document.getElementById("date").value;
var output = "Dear " + guestNames + " You have been invited to " + personName + "'s " + eventType + " on " + date + " Thank you for coming!!";
document.getElementById('output').innerHTML = output.repeat(i);
}
The problem is it is not collecting the data for guestNames. I am pretty new to JS but have searched and cannot find a solution to my problem. Any feedback wouls be helpful.
IDs are difficult to work with in a dynamic environment, classes are generally the simplest solution. This code will convert your inputs to have classes, then loop through them and collect the names.
So change:
input.id = "Guest" + i;
to
input.setAttribute("class","guest");
And change
var guestNames = document.getElementById("Guest").value
to:
var guests = document.querySelectorAll(".guest");
var guestNames = [];
guests.forEach(function(el){
guestNames.push(el.value);
});
guestNames = guestNames.join(",");
If you are wanting a message for EACH guest, then you would use the below function:
function sendInput ()
{
var personName = document.getElementById("people").value;
var eventType = document.getElementById("event").value;
var date = document.getElementById("date").value;
var guests = document.querySelectorAll(".guest");
var guestNames = [];
document.getElementById('output').innerHTML = "";
guests.forEach(function(el){
document.getElementById('output').innerHTML += "Dear " + el.value + " You have been invited to " + personName + "'s " + eventType + " on " + date + " Thank you for coming!!";
});
}
You try to get node by id var guestNames = document.getElementById("Guest").value
But all nodes have a different id, like a Guest0,Guest1 etc. I am trying to write my own code, but your snippet isn't full. I hope I helped you.
As far as I can see, when you try to fetch the guest name
var guestNames = document.getElementById("Guest").value
you won't get any element for two reasons because there's no element with id "Guest". In fact you generate them in the form "GuestN"
`input.id = "Guest" + i;`
You probably want to add a parameter i to sendInput () function, so that internally you can concatenate it to Guest as you did above and get the correct element with getElementById().
Your code is incomplete (as far as I can tell).
You do not specify the following elements anywhere:
'container', 'guest', 'people', 'event', 'data' or 'output'
I assume they should be defined somewhere in the HTML section (not provided)
To be able to create the variable displays, you need to define the 'container' you wish to initialize it before it is used in the for() loop that follows.
Example: var container = document.getElementById('container');
Within the loop, console.log(i.value) is invalid as i is not an element that has been assigne a value to display. It is a counter of the for() loop.
The function of sendInput(), I assume, is to collect the information from the user for each "Guest#" created by the first loop of your code. However you try to collect from "Guest" which has not been defined. For a number of 5, the collections should be for "Guest1", "Guest2", "Guest3", "Guest4", "Guest5". "Guest" only can not be found anywhere in your loop creation. Same goes for 'people, 'event' and 'date' which are referenced for value collection, but there are no elements named as such.
Not exactly sure why you are mixing DOM creation techniques (???).
You create the number of element for the guest, but then output the results with .innerHTML. You should use the DOM creation method, but I have used your code as you indicated you are a beginner.
Here is some (partially) corrected code that you can continue on with.
<!DOCTYPE html><html lang="en"><head><title> Test Page </title>
<meta charset="UTF-8">
<meta name="viewport" content="width-device-width,initial-scale=1.0, user-scalable=yes"/>
<!-- link rel="stylesheet" href="common.css" media="screen" -->
<style>
</style>
</head><body>
<input type="text" value="5/28/2020" id="date">
<pre id='container'></pre>
<button id="report">Report</button>
<pre id='output'></pre>
<script>
console.clear();
function init() {
var number = 5;
var container = document.getElementById('container');
for (i=0;i<number;i++) {
var value = "Guest " + (i+1)+' ';
container.appendChild(document.createTextNode(value));
var input = document.createElement("input");
input.id = "Guest" + i;
input.value = value;
container.appendChild(input);
container.appendChild(document.createElement("br"));
console.log(i); // .value);
}
document.getElementById('report').addEventListener('click',sendInput);
} init();
function sendInput () {
var date = document.getElementById("date").value,
output = document.getElementById('output'),
info = '';
var guestNames = [...document.querySelectorAll('#container input')]; // alert(guestNames.length);
for (let i=0; i<guestNames.length; i++) {
info = `Dear ${guestNames[i].value}:\nYou have been invited to XXX's EVENT on ${date}\nThank you for coming!!\n\n`;
output.innerHTML += info;
}
// var guestNames = document.getElementById("Guest").value
// var personName = document.getElementById("people").value;
// var eventType = document.getElementById("event").value;
// var output = "Dear " + guestNames + " You have been invited to " + personName + "'s " + eventType + " on " + date + " Thank you for coming!!";
// output = `Dear ${guestNames}:\nYou have been invided to XXX's EVENT on ${date}\nThank you for coming!!`;
// document.getElementById('output').innerHTML = output.repeat(i);
}
</script>
</body></html>

Creating and deleting divs using javascript

I have a few JavaScript functions designed to add and remove HTML divs to a larger div. The function init is the body's onload. New lines are added when an outside button calls NewLine(). Divs are removed when buttons inside said divs call DeleteLine(). There are a few problems with the code though: when I add a new line, the color values of all the other lines are cleared, and when deleting lines, the ids of the buttons, titles, and line boxes go out of sync. I've gone through it with the Chrome debugger a few times, but each time I fix something it seems to cause a new problem. I would greatly appreciate some input on what I'm doing wrong.
function init()
{
numOfLines = 0; //Keeps track of the number of lines the Artulator is displaying
}
function NewLine()
{
var LineBoxHolder = document.getElementById("LineBoxHolder");
numOfLines += 1;
LineBoxCode += "<div class = 'Line Box' id = 'LineBox" + numOfLines + "'>" //The code is only split onto multiple lines to look better
+ " <h6 id = 'Title " + numOfLines + "' class = 'Line Box Title'>Line " + numOfLines + "</h6>";
+ " <p>Color: <input type = 'color' value = '#000000'></p>"
+ " <input type = 'button' value = 'Delete Line' id = 'DeleteLine" + numOfLines + "' onclick = 'DeleteLine(" + numOfLines + ")'/>"
+ "</div>";
LineBoxHolder.innerHTML += LineBoxCode;
}
function DeleteLine(num)
{
deletedLineName = "LineBox" + num;
deletedLine = document.getElementById(deletedLineName);
deletedLine.parentNode.removeChild(deletedLine);
num++;
for ( ; num < numOfLines + 1 ; )
{
num++;
var newNum = num - 1;
var changedLineName = "LineBox" + num;
var changedHeaderName = "Title" + num;
var changedButtonName = "DeleteLine" + num;
var changedButtonOC = "DeleteLine(" + newNum + ")";
var changedLine = document.getElementById(changedLineName);
var changedHeader = document.getElementById(changedHeaderName);
var changedButton = document.getElementById(changedButtonName);
var changedLine.id = "LineBox" + newNum;
var changedHeader.innerHTML = "Line" + newNum;
var changedHeader.id = "Title" + newNum;
var changedButton.setAttribute("onclick",changedButtonOC);
var changedButton.id = "DeleteLine" + newNum;
}
num--;
numOfLines = num;
}
You are having a hard time debugging your code because of your approach. You are "marking" various elements with the IDs you construct, and using the IDs to find and address elements. That means that when things change, such as line being deleted, you have to go back and fix up the markings. Almost by definition, the complicated code you wrote to do something like that is going to have bugs. Even if you had great debugging skills, you'd spend some time working through those bugs.
Do not over-use IDs as a poor-man's way to identify DOM elements. Doing it that way requires constructing the ID when you create the element and constructing more IDs for the sub-elements. Then to find the element again, you have to construct another ID string and do getElementById. Instead, use JavaScript to manage the DOM. Instead of passing around IDs and parts of IDs like numbers, pass around the DOM elements themselves. In your case, you don't need IDs at all.
Let's start off with DeleteLine. Instead of passing it a number, pass it the element itself, which you can do my fixing the code inside your big DOM string to be as follows:
<input type='button' value='Delete Line' onclick="DeleteLine(this.parentNode)"/>
So we have no ID for the line element, no ID for the element, and no ID within the onclick handler. DeleteLine itself can now simply be
function DeleteLine(line) {
{
line.parentNode.removeChild(line);
renumberLines();
}
We'll show renumberLines later. There is no need to adjust IDs, rewrite existing elements, or anything else.
Since we no longer need the ID on each line or its sub-elements, the code to create each element becomes much simpler:
function NewLine()
{
var LineBoxHolder = document.getElementById("LineBoxHolder");
numOfLines += 1;
var LineBoxCode = "<div class='LineBox'>" +
+ " <h6 class='LineBoxTitle'>Line " + "numOfLines + "</h6>"
+ " <p>Color: <input type='color' value='#000000'></p>"
+ " <input type='button' value='Delete Line' onclick= 'DeleteLine(this.parentNode)'/>"
+ "</div>";
LineBoxHolder.innerHTML += LineBoxCode;
}
The only remaining work is to fix up the titles to show the correct numbers. You can do this by just looping through the lines, as in
function renumberLines() {
var LineBoxHolder = document.getElementById("LineBoxHolder");
var lines = LineBoxHolder.childElements;
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
var h6 = line.querySelector('h6');
h6.textContent= "Line " + (i+1);
}
}
I voted to close because the question is too broad, but will answer anyway on a few points to... well, point in the right direction.
var changedButton.setAttribute("onclick",changedButtonOC); This is not a variable declaration. Omit the var.
for ( ; num < numOfLines + 1 ; ) { num++; ... The correct form here would be simply for (; num < numOfLines + 1; num++) { ....
Instead of incrementing (num++) then decrementing (num--) around the loop, why not just use the right math?
See:
for (; num < numOfLines; num++) {
...
}

No input text value via JavaScript DOM

I use JavaScript to create input text fields. And everything works fine, except attribute value. It simply doesn't generate and I don't know why?
Here's my code:
k=1;
function addtxt() {
var tip = document.createElement("input");
tip.type = "text";
tip.name = "tip[" + k + "]";
tip.value = "Question1";
var div = document.createElement("div");
div.innerHTML = "Question: " + tip.outerHTML + "<br />";
document.getElementById("mydiv").appendChild(div);
k++
}
This is what I got:
<input type="text" name="tip[1]">
may be try using setAttribute(), like, change:
tip.value = "Question1";
to
tip.setAttribute('value', "Question1");

JavaScript & HTML - Modifying dynamically created subclasses within a dynamically created class

Problem:
I have a dynamically created HTML table, that is used for filling out time sheets. It is created programmatically - there is no formal control. The design is a mix of CSS with text boxes being created through JavaScript. Now each 'row' of this table is in a class called 'divRow', and is separated from the others by having 'r' and the number of the row assigned to it as the class (i.e 'divRow r1', 'divRow r2', etc.).
Within each of these 'divRow's, I have cells in a class called 'divCell cc'. These do not have any identifiers in the class name. At the very last cell, I have a 'Total' column, which ideally calculates the total of the row and then adds it into a dynamically created text box.
What I have at the moment:
// Function to create textboxes on each of the table cells.
$(document).on("click", ".cc", function(){
var c = this;
if(($(c).children().length) === 0) {
var cellval = "";
if ($(c).text()) {
cellval = $(this).text();
if(cellval.length === 0) {
cellval = $(this).find('.tbltxt').val();
}
}
var twidth = $(c).width() + 21;
var tid= 't' + c.id;
if(tid.indexOf('x17') >= 0){
var thtml = "<input id='t" + c.id + "' type='text' Class='tbltxt' style='width: " + twidth + "px;' readonly />";
eval(spproc(spcol(t[getx(c.id)],thtml,tid,twidth)));
//var getRow = $(this).parent().attr('class'); - this gets the 'divRow r#' that it is currently on.
var arr = document.getElementsByClassName('cc');
var tot = 0;
for(var i = 0; i<arr.length; i++){
if(parseInt(arr[i].innerHTML) > 0){
tot += parseInt(arr[i].innerHTML);}
}
$('#t' + c.id).focus();
$(this).children().val(tot);
}else{
var thtml = "<input id='t" + c.id + "' type='text' Class='tbltxt' style='width: " + twidth + "px;' />";
eval(spproc(spcol(t[getx(c.id)],thtml,tid,twidth)));
$('#t' + c.id).focus();
$('#t' + c.id).val(cellval);
}}
});
As you can see, when the user clicks on the 'divCell cc', it creates a text box if one is not present. If the user clicks on the 17th column ('x17'), then it runs the for loop, and assigns the value of the total to the text box.
What I need to happen:
So what happens now is that the last cell sums the total of each cell that has a value. However, they are not row-dependent. I need it to calculate based on the row that it is currently 'on'. So if I'm calculating the 2nd row, I don't want the sum of the first, second and third being entered into the total, I just want the 2nd rows' values summed.
What I've tried:
I've tried looping through and using the 'divRow r#' number to try and get the items in the array that end in that number. (cells are given an id of 'x#y#' and the text boxes assigned to those cells are given an id of 'tx#y#').
I've tried getting elements by the cell class name, and then getting their parent class and sorting by that; didn't get far though, keep running into simple errors.
Let me know if you need more explanation.
Cheers,
Dee.
For anyone else that ever runs into this issue. I got it. I put the elements by the row class into an array, and then using that array, I got the childNodes from the row class. The reason the variable 'i' starts at 2 and not 0 is because I have 2 fields that are not counted in the TimeSheet table (Jobcode and description). It's working great now.
Cheers.
$(document).on("click", ".cc", function(){
var c = this;
if(($(c).children().length) === 0) {
var cellval = "";
if ($(c).text()) {
cellval = $(this).text();
if(cellval.length === 0) {
cellval = $(this).find('.tbltxt').val();
}
}
var twidth = $(c).width() + 21;
var tid= 't' + c.id;
if(tid.indexOf('x17') >= 0){
var thtml = "<input id='t" + c.id + "' type='text' Class='tbltxt' style='width: " + twidth + "px;' readonly />";
eval(spproc(spcol(t[getx(c.id)],thtml,tid,twidth)));
// Get current row that has focus
var getRow = $(this).parent().attr('class');
// Get the row number for passing through to the next statement
var rowPos = getRow.split('r', 5)[1];
// Get all the elements of the row class and assign them to the rowClass array
var rowClass = document.getElementsByClassName('r' + rowPos)
// Given the rowClass, get the children of the row class and assign them to the new array.
var arr = rowClass.item(0).childNodes
// Initialize the 'total' variable, and give it a value of 0
var tot = 0;
// Begin for loop, give 'i' the value of 2 so it starts from the 3rd index (avoid the Req Code and Description part of the table).
for(var i = 2; i<arr.length; i++){
if(parseInt(arr[i].innerHTML) > 0){
tot += parseInt(arr[i].innerHTML);}
}
// Assign focus to the 'Total' cell
$('#t' + c.id).focus();
// Assign the 'total' variable to the textbox that is dynamically created on the click.
$(this).children().val(tot);
}else{
var thtml = "<input id='t" + c.id + "' type='text' Class='tbltxt' style='width: " + twidth + "px;' />";
eval(spproc(spcol(t[getx(c.id)],thtml,tid,twidth)));
$('#t' + c.id).focus();
$('#t' + c.id).val(cellval);
}}
});

Categories