getElementByID.onchange not working after i update html with = innerHTML - javascript

My starting html looks like this:
<label> Names: </label><br>
<input type="text" class="form-control name" placeholder="name1" id="name1" name ="name1"><br>
and i have a variable that captures the html:
var html = "<label> Names: </label><br><input type=\"text\" class=\"form-control name\" placeholder=\"name1\" id=\"name1\" name =\"name1\"><br>"
Then I have an onchange operator that performs a couple functions when the first row has text in it. the .onchange is picked up fine the first time and the subsequent functions are run. I end up with an additional row:
for (n = 1; n < inputLength+1 ; ++n) {
var test2 = document.getElementById(dude+n);
test2.onchange = forFunction
}
function forFunction() {
for (m = 1; m < inputLength+1 ; ++m) {
var test = document.getElementById(dude+m)
if (test.value != "") {
var txt = "<input type=\"text\" class=\"form-control name\" placeholder="+dude+(m+1)+" id="+dude+(m+1)+" name="+dude+(m+1)+"><br>";
document.getElementById('group_names').innerHTML = updateHTML(txt);
//function updateHTML(txt)
}
}
}
var html = "<label> Names: </label><br><input type=\"text\" class=\"form-control name\" placeholder=\"name1\" id=\"name1\" name =\"name1\"><br>"
function updateHTML(txt) {
html = html + txt;
return html;
}
The issue is that after all that completes i end up with two input rows as desired: name1 and name2. However, when i enter text in those fields for a second time, the .onchange is not picked up. but the elements are there in the html when i inspect and view the html.
Also, when i
console.log(inputFormDiv.getElementsByTagName('input').length);
the length of the inputs increases from 1 to 2 after i first run functions (upon the first time i change the value in my input field) so that is getting recognized correctly, just not the .onchange.
thoughts?

The onchange will only work if added to the attribute on the html and the user clicks out of a textbox e.g:
<input onchange="forFunction()" type="text" class="form-control name" placeholder="name1" id="name1" name ="name1">
To add the onchange event in JavaScript code. Add the change event to the addEventListener e.g:
var test2 = document.getElementById(dude+n);
test2.addEventListener('change', forFunction, false)
However if you want the event to fire whilst the user is types a key then use the keypress event. e.g:
var test2 = document.getElementById(dude+n);
test2.addEventListener('keypress', forFunction, false
A basic example: https://jsfiddle.net/xrL6y012/1/

Instead of .innerHTML = html + text do .insertAdjacentHTML('beforeend', text), that way you keep the original html (and events binding).
Edit: https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML

I had the same problem, it seems like modifying the HTML will never work, regardless of how you do it (.innerHTML or .insertAdjacentHTML()).
The only way that worked for me is to append a child instead of editing the HTML, like so:
const span = document.createElement('span');
span.innerHTML = 'text and <b> html stuff </b>';
initialElement.appendChild(span);
And if you actually need to insert just pure text, then this works:
initialElement.append('just text');
Hope that helps.

Related

How to add new lines after HTML elements

I have a simple method for adding input boxes after a button is clicked. The goal of this method is to generate a set of input boxes with a newline inserted after each div.
In the screenshot above you can see that the divs are spaced properly. However, when the add_more button is clicked the generated inputs do not come out properly.
Expected:
The code should generate new input boxes like so:
<div>
Key Term 2: <input id="el2" type="text" value=""> <br>
</div>
<br>
Actual:
function add_more() {
// we've added more inputs.
addMore = true;
// set html generated to false, because new inputs have been added.
htmlGenerated = false;
// increment the number of inputs.
numberOfInputs++;
//fetch the input boxes.
inputs = document.getElementById("inputBoxes");
// create newline
br_key = document.createElement("br");
// create newline
br_description = document.createElement("br");
//create a new row for a key term.
row = document.createElement("div");
// set the key term text.
row.innerHTML = "Key Term ";
row.innerHTML += numberOfInputs;
row.innerHTML += " :";
// create the input for the key.
key = document.createElement("input");
key.setAttribute("id", "el" + numberOfInputs);
//add the key to the row.
row.appendChild(key);
row.after(br_key);
//create a row for the new description.
row2 = document.createElement("div");
// set the description text.
row2.innerHTML = "Description "
row2.innerHTML += numberOfInputs;
row2.innerHTML += " :";
// create the description input
description = document.createElement("input");
description.setAttribute("id", "dl" + numberOfInputs);
// add the description to the row.
row2.appendChild(description);
row2.after(br_description);
// add the rows for the key and the description to the inputBoxes.
inputs.appendChild(row);
inputs.appendChild(row2);
}
<div>Key Term 5 :<input id="el5"></div>
Any help figuring out this issue would be greatly appreciated. Thanks.
Your issue here is essentially incorrect HTML, CSS. I'd implement your inputs, etc. like this:
.full-width-label {
display:block;
}
<label class="full-width-label" for="1">Label</label>
<input type="text" id="1"/>
There are multiple ways to achieve the above, this is just one of your options but now you no longer need to embed the look into the HTML and the format of your HTML (line breaks) is independent of your look.
You might want to look into an off the shelf solution for these kinds of things, like Bootstrap or Tailwind
You can use make it in a simple way
HTML
add this jquery cdn
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<button type="button">Click Here</button>
<div class="appendDiv">
</div>
Js
$(document).ready(function (){
var button = document.getElementsByTagName('button');
var appendDiv = document.getElementsByClassName('appendDiv');
var key = 1;
var descKey = 1;
$('button').click(function(event){
event.preventDefault();
$(appendDiv).append('<div class="child"><div class="grand-child"><label>Key Form :'+ ' '+(++key)+'</label><input type="text" value=""/></div><div class="grand-child"></div><label>Description :'+ ' '+(++descKey )+'</label><input type="text" value=""/></div>');
})
})

Change value of <input> to include a superscript, using Javascript

The following code works correctly for me, in HTML.
<input type = "text" name = "var_1" id = "i_var_1" value = "x&sup8">
The following, using Javascript, also works:
<p id = "p1"><input type = "text" name = "var_1" id = "i_var_1" value = "0"></p>
<script....>
q1 = document.getElementById("p1");
q1.innerHTML = '<INPUT TYPE = "text" name = "var_1a" id = "i_var_1a" value = "x&sup8">';
</script>
However I need to add in the superscript when a button is pressed. So I have something like:
<p id = "p1"><input type = "text" name = "var_1" id = "i_var_1" value = "0"></p>
<input type = "button" id = "i_button" value = "Add the superscript" onclick="Add_Superscript()";>
<script.....>
function Add_Superscript()
{
q1 = document.getElementById("p1");
b1 = document.getElementById("i_var_1");
c1 = b1.value.toString() + "&sup8";
q1.innerHTML = '<INPUT TYPE = "text" name = "var_1a" id = "i_var_1a" value = c1.value>';
}
</script>
The above code does not reproduce the superscript properly.
Anyone any ideas? Thanks in advance for comments.
Not sure this is what you want, but it adds &sup8 to whatever is in the input box.
function Add_Superscript() {
q1 = document.getElementById("p1");
b1 = document.getElementById("i_var_1");
c1 = b1.value.toString() + "&sup8";
q1.innerHTML = '<INPUT TYPE = "text" name = "var_1a" id = "i_var_1a" value = "' + c1 + '">';
}
<p id="p1">
<input type="text" name="var_1" id="i_var_1" value="0">
</p>
<input type="button" id="i_button" value="Add the superscript" onclick="Add_Superscript()" ;>
I don't know what you're trying to do but maybe it's because of the c1.value ! Try:
q1.innerHTML = '<INPUT TYPE = "text" name = "var_1a" id = "i_var_1a" value =' + c1 + '>';
You have several typos in your code and a lot of unnecessary code as well. You just need to set up a click event handler on the button that populates the value of the pre-existing input. No need to create a new input.
A few notes:
When you were trying to create the new input element (which it turns out you don't need to do in the first place), you had the entire thing as a string. You need to inject the dynamic value into that string, by terminating the string, concatenating the new value in and then concatenating the closing of the string, like this:
q1.innerHTML = '<input type="text" name="var_1a" id="i_var_1a" value=' + c1.value + '>';
Next, it's best to use good naming conventions for elements and variables. Prefix an id and name with something that describes the "type" of thing the element is. Use btn (button), txt (textbox), chk (checkbox), rad (radio button), etc. And don't use _ (that's a very old convention). Instead use "camelCase". Further, with form elements, you need to give them a name for form submission purposes, but it is also a good idea to give them and id for CSS and JavaScript purposes. Use the same id that you used for name so that you don't have two different names for the same thing.
Lastly, don't configure your HTML elements to event handlers via HTML attributes (onclick, onmouseover, etc.). Doing this creates global anonymous functions that alter the this binding in the callback function, it creates "spaghetti code" that is hard to scale and debug and it doesn't follow the W3C DOM Event specification. Instead, do all the work in JavaScript and use .addEventListener() to connect functions to events.
// Get references to the relevant DOM elements
var btn = document.getElementById("btnGo");
var input = document.getElementById("txtInput");
// Set up a click event handling function
btn.addEventListener("click", add_Superscript);
function add_Superscript(){
// Create a new value that is the old value plus a "superscript" value
var newVal = input.value + "&sup8";
// Update the input with the new value:
input.value = newVal;
}
<p>
<input type="text" name="txtInput" id="txtInput" value="0">
</p>
<input type = "button" id="btnGo" value="Add the superscript">

Add element works but clears input value

I have a script below that adds an element to my form, another text input field. It adds the new text input field but if I type something into the first one then add a new field it removes the input text from the first one.
I cant see where im going wrong here, im fairly new to JavaScript so please go easy :)
function addAnother() {
var id = 1;
var elemebt = document.getElementById('quest');
var number = elemebt.getElementsByTagName('*').length;
var add = number + 1;
var element = '<input type="text" name="question[]" id="quest'+ add +
'" placeholder="Example: What previous experiance do you have?" class="form-control" id="cloan"><a id="name'+
add +'" onClick="removeEle('+ add +')">Remove</a>';
document.getElementById('quest').innerHTML += element;
}
In JavaScript, the following two statements are practically identical:
str = str + ' more text ';
str += ' more text ';
The key point here is that in the end, the value of str is COMPLETELY OVERWRITTEN.
In your case, that means the innerHTML of the "quest" element is overwritten and the browser completely recreates it's children nodes, thus reseting any state and input values.
To overcome this, you can use the appendChild method but you first need to create the element to append. The easiest way to do that given you have a string of your HTML is to inject that string into a dummy element using the innerHTML property:
var target = document.getElementById('target');
var tDiv = document.createElement('div');
var htmlString = '<input type="text"></input>';
tDiv.innerHTML = htmlString;
target.appendChild(tDiv.children[0]);
<div id="target">Keep my content safe!</div>

How can I dynamically generate input fields with Javascript and then use their values?

I'd like to be able to find the number value of the courseAmount input field upon submit, and then generate new input fields (into the hourForm form underneath the initialForm) through the onsubmit method in javascript, and then retrieve the value from each of the generated input fields upon the submission of the hourForm form and place those values into an array.
However, I'm having difficulty with actually generating the input fields with javascript, and I suspect that I'm having difficulty with retrieving the value of the courseAmount input and porting that to my createInput() function, but I'm not exactly sure if that's the issue.
Here's my HTML:
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<form id="initialForm" method="post" onsubmit="createInput()" action="">
<label>Number of hours for which you would like to study</label>
<input type="number" name="overallHours" id="overallHours" class="stored" min="1" max="20" step="1" value="1"/>
<label>Number of courses you would like to study for</label>
<input type="number" name="courseAmount" id="courseAmount" class="stored" min="1" max="20" step="1" value="1"/>
<input type="submit" class="submitStudy" value="Submit"/>
</form>
<form id="hourForm" method="post" onsubmit="calcHours">
<label>State the desired time spent working in each course</label>
</form>
</body>
And here's my Javascript:
var notedOverallHours = document.getElementById("overallHours").value * 60;
var courseNumberTotal = document.getElementById("courseAmount").value;
var counter = 0;
function createInput() {
var newForm = document.getElementById("hourForm");
document.getElementById("initialForm").style.display = "none";
document.getElementById("hourForm").style.display = "block";
for (i = 0; i <= courseNumberTotal; i++) {
newForm.innerHTML = "<label>Course #" + (counter + 1) + "</label>" + "<input type='number' name='courseHours' class='newInputs' min='1' max='9' step='1' value='1'/>";
counter++;
}
newForm.innerHTML = "<input type='submit' value='submit'/>";
}
Can someone help me figure this Javascript out? My JSFiddle attempts have been futile because JSFiddle does not take kindly to forms reloading the page.
Thank you!
From the mdn page about innerHTML: "Removes all of element's children, parses the content string and assigns the resulting nodes as children of the element." https://developer.mozilla.org/en-US/docs/Web/API/Element.innerHTML
Generally speaking you do not want to use innerHTML at all. There is almost always a better approach. In this case this will be createElement and appendChild.
Furthermore, there is no such thing as "onsubmit" method. What you are calling like that is an HTML attribute which registers a handler for the submit event. http://www.quirksmode.org/js/introevents.html
However using html attributes has its serious drawbacks: http://www.quirksmode.org/js/events_advanced.html
Considering all that, here is what I would do: http://jsfiddle.net/ashnur/rwod4z1d/
HTML:
<form id="initialForm" method="post" action="">
<label>Number of hours for which you would like to study</label>
<input type="number" name="overallHours" id="overallHours" class="stored" min="1" max="20" step="1" value="1" /><hr>
<label>Number of courses you would like to study for</label>
<input type="number" name="courseAmount" id="courseAmount" class="stored" min="1" max="20" step="1" value="1" /><hr>
<input type="submit" class="submitStudy" value="Submit" />
</form>
<form id="hourForm" method="post" >
<label>State the desired time spent working in each course</label><hr>
</form>
js:
var notedOverallHours = document.getElementById("overallHours").value * 60;
var courseNumberTotal = document.getElementById("courseAmount").value;
var counter = 0;
var initialForm = document.getElementById("initialForm");
var hourForm = document.getElementById("hourForm");
initialForm.addEventListener('submit', createInput);
hourForm.addEventListener('submit', calcHours);
function calcHours() {}
function createInput(ev) {
ev.preventDefault(); // this is not needed if you are using a bare button and the click event
var newForm = document.getElementById("hourForm");
initialForm.style.display = "none";
hourForm.style.display = "block";
for (i = 0; i <= courseNumberTotal; i++) {
addControl(newForm, "Course #" + (counter + 1));
counter++;
}
var submit = document.createElement('input');
submit.type = 'submit';
submit.value = 'submit';
newForm.appendChild(submit);
}
function addControl(form, labelText) {
var label = document.createElement('label');
var input = document.createElement('input');
var hr = document.createElement('hr');
input.type = 'number';
input.name = 'courseHours';
input.classname = 'newInputs';
input.min = '1';
input.max = '9';
input.step = '1';
input.value = '1';
label.textContent = labelText;
form.appendChild(label);
form.appendChild(input);
form.appendChild(hr);
}
As Tobias correctly pointed out, your form submission event is allowed to continue which results in a page refresh and a "reset" of all plain JavaScript data. Furthermore, you are not capturing your values (notedOverallHours and courseNumberTotal) on form submission (after the user has entered an amount), but rather when your page initializes (before the user has input anything).
So, to go about fixing this, first a tiny modification to your HTML:
...
<form id="initialForm" method="post" action="">
...
Notice that I deleted the onsubmit attribute from your form. We can capture that with an event in JavaScript itself.
Next attach an event listener to your form which prevents it from submitting and calls your createInput() function:
document.getElementById("initialForm").addEventListener('submit', function (e) {
e.preventDefault();
createInput();
});
This will attach an eventListener that listens to the submit event on your initialForm element. The first parameter is the type of event you want to listen for (submit in this case), the second is the callback you want to have fired.
The callback function always gets the event passed in (the e argument). By calling preventDefault on this event we can stop it from bubbling up and actually causing a page refresh.
Next we call the createInput() function which, after some modifications, looks like this:
function createInput() {
var notedOverallHours = document.getElementById("overallHours").value * 60;
var courseNumberTotal = document.getElementById("courseAmount").value;
var newForm = document.getElementById("hourForm");
document.getElementById("initialForm").style.display = "none";
document.getElementById("hourForm").style.display = "block";
// Add our elements
for (i = 1; i <= courseNumberTotal; i++) {
var child = document.createElement('li');
child.innerHTML = "<label>Course #" + (i) + "</label>" + "<input type='number' name='courseHours-"+ i+"' class='newInputs' min='1' max='9' step='1' value='1'/>";
newForm.appendChild(child);
}
// Add our button
var button = document.createElement('li');
button.innerHTML = "<input type='submit' value='submit'/>";
newForm.appendChild(button);
}
As you can see, I capture the notedOverallHours and courseNumberTotal variables inside the createInput() function, so they will carry whichever value was set during the form submission event.
Then we iterate over each course number. Instead of replacing the innerHTML, we first create an element (li in our case) and fill that element with a HTML string. Next we append this child element to the parent form.
Inside the loop I have removed the counter variable as you can simply use the value of i inside the loop, no need to create an extra variable. I also appended the name attribute for each child with i, so not to get any name clashes.
At the end of our function we simply create and append a new li element containing the submit button.
You can optimize this further by actually creating the label and input elements with the createElement function and set its attributes and text individually with plain JavaScript setters, instead of dumping everything inside li elements as I've done here to keeps things a bit more simple for now. I`ll leave that up as an exercise :)
I have created a rough JSFiddle with this exact code here.
When the createInput() function is called you are not having the desired results because you are reseting the newForm.innerHTML in each iteration of the loop and then again at the end. Rather than using = you should be using += to append the desired text rather than replace the existing text.
// Replacing the contents of newForm.innerHTML
newForm.innerHTML = "foo";
// Appending to newForm.innderHTML (You want to do this)
newForm.innerHTML += "foo";
Another problem is that when you press submit the page is reloading before createInput() is able to have the desired result. You most likely want to stop the page actually submitting and thus reloading when you press the submit button. To do this you can change the onsubmit attribute for the form to "return createInput()" and then add the line return false; to the end of the createInput() function to indicate to the browser that you do not wish to submit the form.

pass a variable name and evaluate it to that variable's value

I have a form with many buttons all of which print a value in the relevant textbox. the problem is the value is a fairly long text string and I would like to create a shorter variable eg. 'text' and make that variable equal to eg. 'some long sentence that I only want to type once'. any idea how I can edit this code to make this possible
function setInput(button, setValue) {
var buttonVal = button.value,
textbox = document.getElementById('input_' + buttonVal);
textbox.value = setValue;
<html>
<input type='submit' name='submit_a' value="a"
onclick="setInput(this,'make_me_a_variable'); return false;">
</html>
var textLookup = {
btnName1: "Long text",
btnName2: "Longer text"
};
// inside your function
var buttonText = ...,
inputText = textLookup[buttonText];
// do stuff with inputText;
Instead of defining the event handler in the HTML code, you could also create the event handler with javascript. You need to do that in another event handler for document.onload. When you do it earlier, the input HTML element might not have been parsed and created yet, so no event handler for it can be added.
<script>
// store your text in a variable
var inputText = 'make_me_a_variable';
// define some code which is executed when the page is loaded:
document.addEventListener("load",function(event){
// get the input by the id property I added to the HTML below.
var input = document.getElementById('submit_a');
// add an event handler for the click event (replaces the onclick HTML property)
input.addEventListener("click",function(event) {
setInput(this, inputText);
return false;
});
});
</script>
[...]
<input id="submit_a" type='submit' name='submit_a' value="a" >
You can create a variable and assign your long text to the variable and use it where ever you want.
Modified code
var longText = 'long text here'.
function setInput(button) {
var buttonVal = button.value,
textbox = document.getElementById('input_' + buttonVal);
textbox.value = longText ;
}
Html:
<input type='submit' name='submit_a' value="a"
onclick="setInput(this); return false;">

Categories