JavaScript button changes the html input name - javascript

I created a button with JScript that adds textareas (questions) one below another onClick. I'm having a trouble in adjusting a function that will change the name of the textareas depending on the number of question (variable n).
So, for the question 1, I want to have textarea name="question1" ...
Is there any other solution? Mine is not working :(
View code on jsfiddle
<input type="submit" value="ADD" onClick="add();">
<div id="new"></div>
script.js
n=1;
function add() {
if(1==1){
document.getElementById('new').innerHTML += '<div>' + n + '. Question: <br/><textarea name="question[n]" rows="4" cols="50"></textarea><br/></div>';
n++;
}}

You almost had it.
n=1;
function add() {
document.getElementById('new').innerHTML += '<div>' + n + '. Question: <br/><textarea name="question'+n+'" rows="4" cols="50"></textarea><br/></div>';
n++;
}
Updated fiddle: http://jsfiddle.net/5FJ4a/2/
Can make your brain happier and debugging easier by splitting up long concatenated strings.
var n=1,
container,
start, middle, end, out;
function add() {
container = document.getElementById('questions');
start = '<div>' + n + '. Question: <br/>';
middle = '<textarea name="question'+n+'" rows="4" cols="50">';
end = '</textarea><br/></div>';
out = start + middle + end;
container.innerHTML += out;
n++;
}
Alternate fiddle: http://jsfiddle.net/5FJ4a/4/

document.getElementById('new').innerHTML += '<div>' + n + '. Question: <br/><textarea name="question'+n+'" rows="4" cols="50"></textarea><br/></div>';

Related

call javascript function through dropdown list

How can I go about calling this function through a dropdown menu and the for loop catching all data and not just the last? I've tried some things and all I would get is the last bit of information. Thank you in advance.
<script>
function hey(){
for (i = 1; i < radio.length; i++){
document.write('<div class="dell"><img class="dell3" align="left" src=images/' + radio[i].image + '> <div class="space"> <font size="4">' + i + '. ' + radio[i].name + '</font></br><font color="silver">' + radio[i].category + '</br>' + radio[i].address + '</br>' + radio[i].citystate + '</font></div> </div>');
}
}
</script>
Add class to every item of <select>(<option>).
Get nodelist of option-elements:
const optionList = document.querySelectorAll('.class');
And for each element add event listener with desired function:
optionList.forEach(item => item.addEventListener('event', fucntion(){}));
Edit your code a bit because it's confusing to scroll.

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++) {
...
}

Simple Javascript Calculator

I'm trying to learn Javascript and I feel like I have a decent grasp on the fundamentals but I am having problems making it do things that i want .. for example.. I am trying to create a simple form in html that calculates the sum of 2 numbers.. here is my html and javascript:
<head>
<script type="text/javascript">
function adder(a,b) {
var a = document.getElementById('firstNum').value;
var b = document.getElementById('secondNum').value;
var numbers = new Array(a,b);
var sum = 0;
for (i=0; i < numbers.length; i++) {
sum += parseInt(numbers[i]);
}
//this part i need help with
document.getElementById('answer').write("First Number: " + a + " plus Second Number: " + b + " is " + sum).value; //this part i need help with
</script>
</head>
<body>
<form id="additionForm">
A + B = C : <input type="text" id="firstNum" placeholder="A">
+ <input type="text" id="secondNum" placeholder="B">
<input type="button" id="addBtn" value="Add" onClick="adder();">
= <input type="text" id="answer" placeholder="C">
</form>
</body>
My problem is that i don't know how to get the javascript to overwrite the value attribute for my form input id=answer .. or if i'm supposed to be using Jquery instead .. thanks in advance.
function adder() {
var a = parseInt( document.getElementById('firstNum').value, 10);
var b = parseInt( document.getElementById('secondNum').value, 10);
var sum = a + b;
//this part i need help with
document.getElementById('answer').value = "First Number: " + a + " plus Second Number: " + b + " is " + sum).value; //this part i need help with
}
If you want to modify an input field in javascript, you can simply set the value attribute:
document.getElementById('answer').value = "First Number: " + a + " plus Second Number: " + b + " is " + sum;

How to insert a string into an array of text inputs?

Basically, I have a large string that i am splitting, then splitting again.
I then need to use the smallest split array to place its elements into text inputs on my page.
This is my Javascript
var splitquestions = vals[2].split('\n');
//Loop to go through all current questions
for (var i = 0; i < splitquestions.length - 1; i++)
{
//trigger a question add where a single question data can be added into
$( "#add" ).trigger('click');
//split current question into separate items
var s = splitquestions[i].split(',');
//Loop to go over all sections in a question
var count = 0;
for(var j = 0; j < s.length; j++)
{
count = count + 1;
var qs = document.getElementById('questions[' + j +'][' + count + ']').value;
qs = s[j];
}
}
There will be many questions on the page, depending how many the user will like to add. Each new question block will consist of a question, 3 wrong answers, and 1 correct answer.
The part that is going wrong is within the last loop. This is where I need to grab each individual element within the 's' array, and place it within each text input.
This is how the raw data is displayed before it is split by the 'splitquestions' variable:
question1,incorrect-answer1,incorrect-answer2,incorrect-answer3,correct-answer
question2,incorrect-answer1,incorrect-answer2,incorrect-answer3,correct-answer
question3,incorrect-answer1,incorrect-answer2,incorrect-answer3,correct-answer
As you can see from above, each question is separated by a line-break, being \n, then each individual part is comma separated.
Each question input has a multidimensional variable assigned to its ID. For example, using the data above, the first line of data, along with the very first element (being question1) would be question[1][1]. Another example would be 'incorrect-answer1' on the third line of data, which would be question[3][2]. The first number is the question number, and the second number is the element number.
I hope that I've explained this well enough, since I am a little confused on how to explain it myself since I am new to multidimensional arrays and loops inside loops. So please, if you need any additional information, just post a comment and I'll do my best.
If needed, this is the function that creates the question elements dynamically:
function dynamicForm () {
//set a counter
var i = $('.dynamic-input#form-step2').length + 1;
//alert(i);
//add input
$('a#add').click(function () {
$('<table><tr><td><p><span class="left"><input type="text" class="dynamic-input" name="questions[' +i +'][1]" id="' + i + '" placeholder="Question" /></span>' + '<span class="right"><input type="text" class="dynamic-input" name="questions[' +i +'][2]" id="' + i + '" placeholder="Distraction 1" /><br /><input type="text" class="dynamic-input" name="questions[' +i +'][3]" id="' + i + '" placeholder="Distraction 2" /><br /><input type="text" class="dynamic-input" name="questions[' +i +'][4]" id="' + i + '" placeholder="Distraction 3" /><br /><input type="text" class="dynamic-input" name="questions[' +i +'][5]" id="' + i + '" placeholder="Correct Answer" /><br />Remove</span></p></td></tr></table>').fadeIn("slow").appendTo('#extender');
i++;
$("a:contains('Remove')").click(function () {
$(this).parent().parent().remove();
});
return false;
});
//fadeout selected item and remove
$("#form-step2.dynamic-input").on('click', 'a', function () {
$(this).parent().fadeOut(300, function () {
$(this).empty();
return false;
});
});
}
After further discussions with the OP, we fixed the code ended up being what's below. Basically, his input numbers are starting at index 1 instead of 0, so that was one of the issues. He was also trying to select by id while the inputs in question only had a name attribute.
//Loop to go over all sections in a question
for (var j = 1, len = s.length; j <= len; j++) {
$('input[name="questions[' + (i + 1) + '][' + j + ']"]').val(s[j - 1]);
}

Name and ID changing

I try to build an register form. This register form as text box called "address1" and near it a button called "Add Address". The function of the button - it adds text box for more addresses. the button near the previous address boxes changes to "Remove" which remove the address box and the button. The problem is: I have to set the text boxes in order - 1,2,3,... - I have to change their names and id's. For example - if I remove addressbox number 4 (name, id="address4") then all the next text boxes's names and id's should decrease by 1. I try to do this in for loop. This is hard to explain so I just give you the code. Try in your VS to write for example 'document.getElementById("address"+n).' and you'll see that you even don't see in the list you get that you can write after the dot id or name or value. I realized it is because there is a variable in this is the problem I think. Now here's the code:
<html>
<head>
<title>Untitled Page</title>
<script type="text/javascript">
var n1 = 1; //counting the buttons and divs. doesn't decrease.
//In another words - it counts the number of calls to Add()
var n3 = 1; //counting the address text fields.
//It being reduced and increased so that it will represent the exact number of text fields
function Add() {
n1++;
n3++;
s1 = "<div id='div" + n1 + "'>";
s1 += "Address <input type='text' name='address" + n3 + "' id='address" + n3 + "' />";
s1 += "<input type='button' name='add" + n1 + "' id='add" + n1 + "' value='Add Branch' onclick='Add();' /><br />";
s1 += "</div>";
var n2 = n1 - 1;
document.getElementById('div' + n2).insertAdjacentHTML('afterEnd', s1);
document.getElementById('add' + n2).onclick = function () { Remove(n2, (n3-1)); };
document.getElementById('add' + n2).value = 'Remove';
}
function Remove(nn1, nn2) { //nn1 - div number to remove. nn2 - the address field number in this div
var parent = document.getElementById('barcode');
var child = document.getElementById('div' + nn1);
parent.removeChild(child);
for (nn2 += 1; nn2 <= n3; nn2++) {
var n2 = nn2 - 1; //nn2 - current address text field. n2 - the new number for the address field
document.getElementById('address' + nn2).setAttribute('name', 'address' + n2);
document.getElementById('address' + nn2).setAttribute('id', 'address' + n2);
document.getElementById('address' + n2).setAttribute('value', 'address' + n2);
// try: document.getElementById('address' + nn2).name='address'+n2. doesn't work (for me)
}
n3--;
}
var check = false;
</script>
</head>
<body>
<form name='barcode' id='barcode' action="" >
<div id='div1'>
Address <input type='text' name='address1' id='address1' />
<input type='button' name='add1' id='add1' value='Add Branch' onclick='Add();' /><br />
</div></form>
</body>
</html>
Sorry for the disorder :) I keeped in this code only what linked to the address field and I added comments.
Thanks very much!
edit:
I forgot that you don't see the bug in this code because I already tried to fix it. Before I changed the code it ordered all the divs, text fields and add/remove buttons so all the exsisting items will always be numbered in order (1, 2, 3, ...).
The problem in the following code can be seen if you click 2 times add button, then you remove the first address field and then you click the add button again.
<html>
<head>
<script type="text/javascript">
var n1 = 1;
function Add() {
n1++;
s1 = "<div id='div" + n1 + "'>";
s1 += "Address <input type='text' name='address" + n1 + "' id='address" + n1 + "' />";
s1 += "<input type='button' name='add" + n1 + "' id='add" + n1 + "' value='Add Branch' onclick='Add()' /><br />";
s1 += "</div>";
var n2 = n1 - 1;
document.getElementById('div' + (n2)).insertAdjacentHTML('afterEnd', s1);
document.getElementById('add' + (n2)).onclick = function () { Remove(n2); };
document.getElementById('add' + (n2)).value = 'Remove';
}
function Remove(n) {
var parent = document.getElementById('barcode');
var child = document.getElementById('div' + n);
parent.removeChild(child);
for (n += 1; n <= n1; n++) {
var n2 = n1 - 1;
document.getElementById('add' + n).onclick = function () { Remove(n2); };
document.getElementById('address' + n).setAttribute('name', 'address' + n2);
document.getElementById('add' + n).setAttribute('name', 'add' + n2);
document.getElementById('address' + n).setAttribute('id', 'address' + n2);
document.getElementById('add' + n).setAttribute('id', 'add' + n2);
document.getElementById('div' + n).setAttribute('id','div' + n2);
}
n1--;
document.getElementById('add' + n1).onclick = function () { Add() };
}
</script>
</head>
<body>
<form name='barcode' id='barcode' action="" >
<div id='div1'>
Address <input type='text' name='address1' id='address1' />
<input type='button' name='add1' id='add1' value='Add Branch' onclick='Add();' /><br />
</div>
</form>
</body>
</html>
I think you are working a bit too hard to maintain the order of the addresses and i don't see a general reason to do it (if you have one, please add it to your question).
If you add the inputs with a unique index like you are doing, they will always be different and ordered.
Here's what you can do:
Pass the event caller to the functions Add and Remove and inside you can make the changes you want to those elements.
For example your Remove function (that you would call with Remove(this);) would look like this:
function Remove(callerButton) {
var parent = document.getElementById('barcode');
var child = callerButton.parentNode;
// child is the DIV you want to remove
parent.removeChild(child);
n3--;
}
This way you wouldn't need to do all the sorting you are doing right now.
At the end you can access all the remaining elements with:
var addresses = document.getElementById("barcode").getElementsByTagName("input");
for(var i = 0; i < addresses.length; i++) {
if(addresses[i].type == "text") {
// I'm printing them in the console, you can do with it whatever you like
// If you want to exclude the one with "Add Branch in front of it you can validate for address+n1
console.log("Element.id : " + addresses[i].id + " - Element.value: "+ addresses[i].value );
}
}
I added a jsFiddle with these changes (added a submit button to show the remaining fields in the form).
See if it solves your problem.

Categories