I'm working on a challenge that requires I only use Javascript (no jQuery). I created an HTML with twelve different buttons and an heading at the bottom. I want to switch the heading with the buttons text on click but mostly receive the error "Uncaught TypeError: Cannot set property 'innerHTML' of null/undefined."
I included the whole script, and I know my createHTML function could use some cleaning up, but I only included it so you can see how I added the click handler. switchHeading function is at the bottom.
function createHTML(){
var container = document.getElementsByClassName("container");
//add div "row"
var row = document.createElement("div");
row.className = "row";
container[0].appendChild(row);
//add div "col"
var col = document.createElement("div");
col.className = "col-md-12";
row.appendChild(col);
//add star button
var starButton = document.createElement("button");
starButton.className = "btn btn-default btn-lg";
starButton.setAttribute("type", "button");
starButton.onclick = switchHeading();
col.appendChild(starButton);
starButton.appendChild(document.createTextNode("Star"));
//add hr
var hr = document.createElement("hr");
col.appendChild(hr);
//add div
var div = document.createElement("div");
col.appendChild(div);
//add btn group
var btnGroup = document.createElement("div");
btnGroup.className = "btn-group";
div.appendChild(btnGroup);
//add num btns
for(var i=1; i<5; i++){
var numButton = document.createElement("button");
numButton.className="btn btn-default";
numButton.setAttribute("type", "button");
numButton.onclick = switchHeading();
btnGroup.appendChild(numButton);
numButton.appendChild(document.createTextNode(i));
}
//add btn group2
var btnGroup2 = document.createElement("div");
btnGroup2.className = "btn-group";
div.appendChild(btnGroup2);
//add some more num buttons
for(var i=5; i<8; i++){
var numButton = document.createElement("button");
numButton.className="btn btn-default";
numButton.setAttribute("type", "button");
numButton.onclick = switchHeading();
btnGroup2.appendChild(numButton);
numButton.appendChild(document.createTextNode(i));
}
//add 8 button
var btnGroup3 = document.createElement("div");
btnGroup3.className ="btn-group";
div.appendChild(btnGroup3);
var ochoButton = document.createElement("button");
ochoButton.className = "btn btn-default";
ochoButton.setAttribute("type", "button");
ochoButton.onclick = switchHeading();
btnGroup3.appendChild(ochoButton);
ochoButton.appendChild(document.createTextNode(8));
//2nd hr
var hr2 = document.createElement("hr");
col.appendChild(hr2);
//Anotha div
var anotherDiv = document.createElement("div");
col.appendChild(anotherDiv);
//last btn group
var btnGroupLg = document.createElement("div");
btnGroupLg.className = "btn-group btn-group-lg";
anotherDiv.appendChild(btnGroupLg);
//LMR buttons
var LButton = document.createElement("button");
LButton.className = "btn btn-default";
LButton.setAttribute("type", "button");
LButton.onclick = switchHeading();
btnGroupLg.appendChild(LButton);
LButton.appendChild(document.createTextNode("Left"));
var MButton = document.createElement("button");
MButton.className = "btn btn-default";
MButton.setAttribute("type", "button");
MButton.onclick = switchHeading();
btnGroupLg.appendChild(MButton);
MButton.appendChild(document.createTextNode("Middle"));
var RButton = document.createElement("button");
RButton.className = "btn btn-default";
RButton.setAttribute("type", "button");
RButton.onclick = switchHeading();
btnGroupLg.appendChild(RButton);
RButton.appendChild(document.createTextNode("Right"));
//add h3
var h3 = document.createElement("h3");
h3.id = "heading";
anotherDiv.appendChild(h3);
h3.appendChild(document.createTextNode("Click a Button!"));
};
createHTML();
function switchHeading() {
var content = this.innerHTML;
var h3 = document.getElementsByTagName('h3');
h3[0].innerHTML = content;
}
Make sure you've got h3 tag on your page and get rid of parentheses in
RButton.onclick = switchHeading();
The parentheses make function switchHeading() run immediately wich leads to undefined result since switchHeading() has no return value. This works:
<html>
<div class="container"></div>
<h3>Hello</h3>
<script>
function createHTML(){
var container = document.getElementsByClassName("container");
//add div "row"
var row = document.createElement("div");
row.className = "row";
container[0].appendChild(row);
//add div "col"
var col = document.createElement("div");
col.className = "col-md-12";
row.appendChild(col);
//add star button
var starButton = document.createElement("button");
starButton.className = "btn btn-default btn-lg";
starButton.setAttribute("type", "button");
starButton.onclick = switchHeading;
col.appendChild(starButton);
starButton.appendChild(document.createTextNode("Star"));
//add hr
var hr = document.createElement("hr");
col.appendChild(hr);
//add div
var div = document.createElement("div");
col.appendChild(div);
//add btn group
var btnGroup = document.createElement("div");
btnGroup.className = "btn-group";
div.appendChild(btnGroup);
//add num btns
for(var i=1; i<5; i++){
var numButton = document.createElement("button");
numButton.className="btn btn-default";
numButton.setAttribute("type", "button");
numButton.onclick = switchHeading;
btnGroup.appendChild(numButton);
numButton.appendChild(document.createTextNode(i));
}
//add btn group2
var btnGroup2 = document.createElement("div");
btnGroup2.className = "btn-group";
div.appendChild(btnGroup2);
//add some more num buttons
for(var i=5; i<8; i++){
var numButton = document.createElement("button");
numButton.className="btn btn-default";
numButton.setAttribute("type", "button");
numButton.onclick = switchHeading;
btnGroup2.appendChild(numButton);
numButton.appendChild(document.createTextNode(i));
}
//add 8 button
var btnGroup3 = document.createElement("div");
btnGroup3.className ="btn-group";
div.appendChild(btnGroup3);
var ochoButton = document.createElement("button");
ochoButton.className = "btn btn-default";
ochoButton.setAttribute("type", "button");
ochoButton.onclick = switchHeading;
btnGroup3.appendChild(ochoButton);
ochoButton.appendChild(document.createTextNode(8));
//2nd hr
var hr2 = document.createElement("hr");
col.appendChild(hr2);
//Anotha div
var anotherDiv = document.createElement("div");
col.appendChild(anotherDiv);
//last btn group
var btnGroupLg = document.createElement("div");
btnGroupLg.className = "btn-group btn-group-lg";
anotherDiv.appendChild(btnGroupLg);
//LMR buttons
var LButton = document.createElement("button");
LButton.className = "btn btn-default";
LButton.setAttribute("type", "button");
LButton.onclick = switchHeading;
btnGroupLg.appendChild(LButton);
LButton.appendChild(document.createTextNode("Left"));
var MButton = document.createElement("button");
MButton.className = "btn btn-default";
MButton.setAttribute("type", "button");
MButton.onclick = switchHeading;
btnGroupLg.appendChild(MButton);
MButton.appendChild(document.createTextNode("Middle"));
var RButton = document.createElement("button");
RButton.className = "btn btn-default";
RButton.setAttribute("type", "button");
RButton.onclick = switchHeading;
btnGroupLg.appendChild(RButton);
RButton.appendChild(document.createTextNode("Right"));
//add h3
var h3 = document.createElement("h3");
h3.id = "heading";
anotherDiv.appendChild(h3);
h3.appendChild(document.createTextNode("Click a Button!"));
};
createHTML();
function switchHeading() {
var content = this.innerHTML;
var h3 = document.getElementsByTagName('h3');
h3[0].innerHTML = content;
}
</script>
</html>
Related
I am trying to create buttons for each letter in alphabet. When the button is pressed, it will alert the letter written on the button. But i think since i create them i a for loop, js can't keep their reference because when i open the browser, on the each button 'undefined' is written. I also tried to add the buttons to an array then append them to the container, but the result was same. Is there any way to fix this problem? Thanks.
function CreateButtons()
{
var letters = "ABCDEFGHJKLMNOPRSTUVYZQWXI";
var frame = document.getElementById('buttons'); //container.
for (var i = 0; i < letters.length;i++)
{
document.addEventListener('DOMContentLoaded', function() {
var button = document.createElement('button');
button.type = 'button';
button.innerHTML = letters[i];
button.className = 'btn-styled';
button.style.padding = "20px";
button.style.marginTop = "10px";
button.style.lineHeight = "30px";
button.style.fontWeight = "bold";
button.style.padding = "0 30px";
button.style.background = "salmon";
button.style.border = "none";
button.style.color ="blue";
button.onclick = function() {
alert(letters[i]); //when the button is pressed, it will alert the letter at i. position.
};
frame.appendChild(button);
}, false);
}
}
You need to create a closure. Because loop will finish its execution and the button created will never know the value of letter[i]
function CreateButtons() {
var letters = "ABCDEFGHJKLMNOPRSTUVYZQWXI";
var frame = document.getElementById('buttons'); //container.
for (var i = 0; i < letters.length; i++) {
(function(z) {
document.addEventListener('DOMContentLoaded', function() {
var button = document.createElement('button');
button.type = 'button';
button.innerHTML = z;
button.className = 'btn-styled';
button.style.padding = "20px";
button.style.marginTop = "10px";
button.style.lineHeight = "30px";
button.style.fontWeight = "bold";
button.style.padding = "0 30px";
button.style.background = "salmon";
button.style.border = "none";
button.style.color = "blue";
button.onclick = function() {
alert(z); //when the button is pressed, it will alert the letter at i. position.
};
frame.appendChild(button);
}, false);
}(letters[i]))
}
}
CreateButtons()
<div id='buttons'></div>
Alternatively instead of var use let
function CreateButtons() {
var letters = "ABCDEFGHJKLMNOPRSTUVYZQWXI";
var frame = document.getElementById('buttons'); //container.
for (let i = 0; i < letters.length; i++) {
document.addEventListener('DOMContentLoaded', function() {
var button = document.createElement('button');
button.type = 'button';
button.innerHTML = letters[i];
button.className = 'btn-styled';
button.style.padding = "20px";
button.style.marginTop = "10px";
button.style.lineHeight = "30px";
button.style.fontWeight = "bold";
button.style.padding = "0 30px";
button.style.background = "salmon";
button.style.border = "none";
button.style.color = "blue";
button.onclick = function() {
alert(letters[i]); //when the button is pressed, it will alert the letter at i. position.
};
frame.appendChild(button);
}, false);
}
}
CreateButtons()
<div id='buttons'></div>
I have the following code:
JS :
i.addEventListener("click", function () {
var br1 = document.createElement("br");
var div1 = document.createElement("div");
div1.className = "input-group";
var ipt1 = document.createElement("input");
ipt1.type = "text";
ipt1.className = "form-control";
var span = document.createElement("span");
span.className = "input-group-addon";
var ipt2 = document.createElement("input");
ipt2.type = "text";
ipt2.className = "form-control";
div1.appendChild(ipt1);
div1.appendChild(span);
div1.appendChild(ipt2);
divdiv.appendChild(div1);
divdiv.appendChild(br1);
});
document.getElementById('modal2body').appendChild(divdiv);
However, when there are multiple <i>s, the divdiv is appended to the last one.
This is all in a for loop, which adds an <i> for each element in a list.
The list might look like ['customers','employees','managers','night-shifts']
There needs to be an option to add the input-group to each one of these. (the i is a FontAwesome 'plus' icon).
The problem I have, is that clicking any of the icons, it will add the input-group to the night-shift list.
I thought I might need to use dynamic variables to fix this.
If it happens that this is the most effective solution, how can I achieve this?
Or is there a better way to do this ?
Screenshot :
In this screenshot, I clicked the + to the right of Customers
This code creates the original 4 input-groups (1 for each section) :
var divdiv = document.createElement('div');
divdiv.id = 'd' + d;
var div1 = document.createElement('div')
div1.className = 'input-group';
var ipt1 = document.createElement('input');
ipt1.type = 'text';
ipt1.className = 'form-control'
var span = document.createElement('span');
span.className = 'input-group-addon';
var ipt2 = document.createElement('input');
ipt2.type = 'text';
ipt2.className = 'form-control'
var div2 = document.createElement('div');
var t = document.createElement('t');
t.className = 'helv-b grey'
t.style.fontSize = '15px';
t.textContent = inputstext[d];
div2.appendChild(t);
var i = document.createElement('i');
i.className = 'fa fa-plus';
i.style.float = 'right'
i.style.fontSize = '20px';
i.style.marginTop= '5px'
i.onmouseenter = i.style.opacity = "60%";
i.onmouseleave = i.style.opacity = "100%";
div2.appendChild(i);
var br1 = document.createElement('br');
var br2 = document.createElement('br');
divdiv.appendChild(div2);
divdiv.appendChild(br1);
div1.appendChild(ipt1);
div1.appendChild(span);
div1.appendChild(ipt2);
divdiv.appendChild(div1);
divdiv.appendChild(br2);
divdiv.id = 'f' + d;
(inputstext = ['Customers','Employees','Managers','Night-Shifts'])
HTML :
<div class="modal-body" id="modal2body">
</div>
###Update
Screenshots :
I can't figure out how to fix these alignment issues and make them look like my original screenshot.
Also, how do I have 1 input-group already displayed for each section ?
The problem is that the code which adds is event-driven, which means that it will run when the user clicks the add icon. So when the add icon is click the value of divdiv will be the last element of array "Night-Shifts".
Here is a way of doing it using arrays.
var inputstext = ['customers', 'employees', 'managers', 'night-shifts']
var divdivArray = [];
var mainDiv = document.getElementById("modal2body");
for (var d = 0; d < inputstext.length; d++) {
var divdiv = document.createElement('div');
divdiv.id = 'd' + d;
var div1 = document.createElement('div')
div1.className = 'input-group';
var ipt1 = document.createElement('input');
ipt1.type = 'text';
ipt1.className = 'form-control'
var span = document.createElement('span');
span.className = 'input-group-addon';
var ipt2 = document.createElement('input');
ipt2.type = 'text';
ipt2.className = 'form-control'
var div2 = document.createElement('div');
var t = document.createElement('t');
t.className = 'helv-b grey'
t.style.fontSize = '15px';
t.textContent = inputstext[d];
div2.appendChild(t);
var i = document.createElement('i');
i.className = 'fa fa-plus';
i.style.float = 'right'
i.style.fontSize = '20px';
i.style.marginTop = '5px'
i.onmouseenter = i.style.opacity = "60%";
i.onmouseleave = i.style.opacity = "100%";
i.setAttribute("index", d)
div2.appendChild(i);
var br1 = document.createElement('br');
var br2 = document.createElement('br');
divdiv.appendChild(div2);
divdiv.appendChild(br1);
div1.appendChild(ipt1);
div1.appendChild(span);
div1.appendChild(ipt2);
divdiv.appendChild(div1);
divdiv.appendChild(br2);
divdiv.id = 'f' + d;
mainDiv.appendChild(divdiv)
divdivArray.push(divdiv);
i.addEventListener("click", function() {
var br1 = document.createElement("br");
var div1 = document.createElement("div");
div1.className = "input-group";
var ipt1 = document.createElement("input");
ipt1.type = "text";
ipt1.className = "form-control";
var span = document.createElement("span");
span.className = "input-group-addon";
var ipt2 = document.createElement("input");
ipt2.type = "text";
ipt2.className = "form-control";
div1.appendChild(ipt1);
div1.appendChild(span);
div1.appendChild(ipt2);
var index = this.getAttribute("index");
divdivArray[index].appendChild(div1);
divdivArray[index].appendChild(br1);
});
}
<html>
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<div class="modal-body" id="modal2body" style="display: inline-block;">
</div>
<html>
Here I save every divdiv inside the array. And also add an index attribute to the <i> element so when it is clicked you can know which divdiv you want to edit.
I hope someone will help me to solve this little problem with javascript. I did create a javascript function to render automatically 2 different forms according to the value selected by the user from a selectbox. The function is triggered when the user click on a button. The problem is that the forms are not generated instead i'm getting an error message: "Uncaught ReferenceError: addFields is not defined".
Html Code:
<div class="form-group " style="margin-left: 80%">
<div class="col-sm-10">
<button type="button" class="btn btn-success btn-lg" onclick="addFields()">Formular erstellen</button>
</div>
</div>
Javascript code:
<script type="text/javascript">
function addFields() {
// Number of inputs to create
var number = document.getElementById("anzahlFragen").value;
// Type of Quiz
var type = document.getElementById("quizTyp");
var selectedType = type.options[type.selectedIndex].text;
// Container <div> where dynamic content will be placed
var myContainer = document.getElementById("myContainer");
// Clear previous contents of the container
while (myContainer.hasChildNodes()) {
myContainer.removeChild(myContainer.lastChild);
}
if (selectedType === "Multiple choices") {
for (i = 1; i <= number; i++) {
var div1 = document.createElement("div");
div1.className = "form-group";
var div2 = document.createElement("div");
div2.className = "col-sm-9";
var labelFr = document.createElement("label");
var tFr = document.createTextNode("Frage Nr " + i);
labelFr.appendChild(tFr);
labelFr.className = "col-sm-2 control-label";
div1.appendChild(labelFr);
var inputFr = document.createElement("input");
inputFr.type = "text";
inputFr.name = "frage" + i;
inputFr.className = "form-control round-form";
div2.appendChild(inputFr);
div2.appendChild(document.createElement("br"));
for (j = 1; j <= 4; j++) {
var labelAn = document.createElement("label");
var tAn = document.createTextNode("Antwort Nr " + i + j);
labelAn.appendChild(tAn);
div2.appendChild(labelAn);
var inputAn = document.createElement("input");
inputAn.type = "text";
inputAn.name = "antwort" + i + j;
inputAn.className = "form-control round-form";
div2.appendChild(inputAn);
var labelRichtig = document.createElement("label");
var tRichtig = document.createTextNode("Richtig " + i + j);
labelRichtig.appendChild(tRichtig);
div2.appendChild(labelRichtig);
var richtigAn = document.createElement("input");
richtigAn.type = "radio";
richtigAn.name = "Richtig" + i;
div2.appendChild(richtigAn);
div2.appendChild(document.createElement("br"));
div2.appendChild(document.createElement("br"));
}
div1.appendChild(div2);
myContainer.appendChild(div1);
myContainer.appendChild(document.createElement("br"));
}
} else {
for (i = 1; i <= number; i++) {
var div1 = document.createElement("div");
div1.className = "form-group";
var div2 = document.createElement("div");
div2.className = "col-sm-9";
var labelFr = document.createElement("label");
var tFr = document.createTextNode("Frage Nr " + i);
labelFr.appendChild(tFr);
labelFr.className = "col-sm-2 control-label";
div1.appendChild(labelFr);
var inputFr = document.createElement("input");
inputFr.type = "text";
inputFr.name = "frage" + i;
inputFr.className = "form-control round-form";
div2.appendChild(inputFr);
div2.appendChild(document.createElement("br"));
for (j = 1; j <= 4; j++) {
var labelAn = document.createElement("label");
var tAn = document.createTextNode("Antwort Nr " + i + j);
labelAn.appendChild(tAn);
div2.appendChild(labelAn);
var inputAn = document.createElement("input");
inputAn.type = "text";
inputAn.name = "antwort" + i + j;
inputAn.className = "form-control round-form";
div2.appendChild(inputAn);
var profilAn = document.createElement("select");
profilAn.name = "profil" + i + j;
div2.appendChild(profilAn);
optionAn1 = document.createElement("option");
optionAn1.setAttribute("value", "1"),
var optionT1 = document.createTextNode("Profil 1");
optionAn1.appendChild(optionT1);
optionAn2 = document.createElement("option");
optionAn2.setAttribute("value", "2"),
var optionT2 = document.createTextNode("Profil 2");
optionAn2.appendChild(optionT2);
optionAn3 = document.createElement("option");
optionAn3.setAttribute("value", "3"),
var optionT3 = document.createTextNode("Profil 3");
optionAn3.appendChild(optionT3);
optionAn4 = document.createElement("option");
optionAn4.setAttribute("value", "4"),
var optionT4 = document.createTextNode("Profil 4");
optionAn4.appendChild(optionT4);
document.getElementsByTagName("select").appendChild(optionAn1);
document.getElementsByTagName("select").appendChild(optionAn2);
document.getElementsByTagName("select").appendChild(optionAn3);
document.getElementsByTagName("select").appendChild(optionAn4);
div2.appendChild(document.createElement("br"));
div2.appendChild(document.createElement("br"));
}
div1.appendChild(div2);
myContainer.appendChild(div1);
myContainer.appendChild(document.createElement("br"));
}
}
}
</script>
You have placed commas instead of semicolon at the end of the lines above the declaration of the variables optionT1, optionT2, optionT3and optionT4.
I'm trying to dynamically create a div for each user's campaign.
What I'd really like to see is a "show details" button inside the div that redirects to the campaign details. I tried to run this code, but it only takes the last index.
for (var i = utente.campagne.length - 1; i >= 0; i--) {
var appended = document.createElement("DIV");
appended.className = "jumbotron";
var nome = document.createElement("p");
nome.innerHTML = "Campaign Name: " + utente.campagne[i].nome;
appended.appendChild(nome);
var button = document.createElement("INPUT");
button.type = "button";
var index = i;
button.addEventListener('click', function () {
window.location = "ShowDetails.jsp?indexcampagna=" + index;
});
button.value = "show details";
button.className = "btn btn-primary btn-sm";
appended.appendChild(button);
var col = document.createElement("DIV");
col.className = "col-lg-4 col-sm-6 text-center";
col.appendChild(appended);
document.getElementById("boxes").appendChild(col);
}
I have developed a mobile webpage using HTML5+JS. I added a button dynamically to webpage. But when i added onclick functionality to that button, it's not working.
My Html code is;
<head><script>
var myarray = ['a','b','c','d','e','f'];
var arr = document.getElementById('content');
for(i=0;i<myarray.length;i++)
{
var table = document.createElement('table');
table.className = 'table';
var tr = document.createElement('tr');
var td = document.createElement('td');
var Btn = document.createElement('input');
Btn.type = 'button';
Btn.className = 'Btn';
Btn.value = 'VOTE';
Btn.id = myarray[i];
Btn.onclick = function(){
alert("You have Selected" + " " + this.id);
};
td.appendChild(Btn);
tr.appendChild(td);
table.appendChild(tr);
arr.appendChild(table);
}
</script>
<style>
.table { width:100%;height:70px;}
.Btn { margin-top:3px;border-radius:0;font-size:15px;height:30px;width:100px; color:#FFFFFF; margin-left:auto;margin-right:auto;display:block; }
</style></head>
<body><section id='content'></section></body>
It's not the onclick that's the problem. The problem is you are trying to get the #content element before it is loaded/rendered.
The solution is to wrap the code in window.onload which ensures the code will only execute when the elements in the page are loaded and ready for use:
window.onload = function () {
var myarray = ['a', 'b', 'c', 'd', 'e', 'f'];
var arr = document.getElementById('content');
for (i = 0; i < myarray.length; i++) {
var table = document.createElement('table');
table.className = 'table';
var tr = document.createElement('tr');
var td = document.createElement('td');
var Btn = document.createElement('input');
Btn.type = 'button';
Btn.className = 'Btn';
Btn.value = 'VOTE';
Btn.id = myarray[i];
Btn.onclick = function () {
alert("You have Selected" + " " + this.id);
};
td.appendChild(Btn);
tr.appendChild(td);
table.appendChild(tr);
arr.appendChild(table);
}
};
The problem is your code is not running on dom ready
window.onload = function (){
var myarray = ['a','b','c','d','e','f'];
var arr = document.getElementById('content');
for(i=0;i<myarray.length;i++)
{
var table = document.createElement('table');
table.className = 'table';
var tr = document.createElement('tr');
var td = document.createElement('td');
var Btn = document.createElement('input');
Btn.type = 'button';
Btn.className = 'Btn';
Btn.value = 'VOTE';
Btn.id = myarray[i];
Btn.onclick = function(){
alert("You have Selected" + " " + this.id);
};
td.appendChild(Btn);
tr.appendChild(td);
table.appendChild(tr);
arr.appendChild(table);
}
}
Demo: Plunker