Using a loop to simplify DOM manipulation Vanilla JS - javascript

I have the following JS code in which I'm trying to append these elements to the DOM. I've done so, however I'm trying to figure out how to use a loop to append these to follow DRY principles. I can only use vanilla JS.
var divOne = document.getElementById('buttonHolder');
var btnGroupOne = document.createElement('div')
btnGroupOne.className = 'btn-group';
divOne.appendChild(btnGroupOne);
var btnOne = document.createElement('button');
var textOne = document.createTextNode('1');
btnOne.appendChild(textOne);
btnOne.className = 'btn btn-default';
btnGroupOne.appendChild(btnOne);
var btnTwo = document.createElement('button');
var textTwo = document.createTextNode('2');
btnTwo.appendChild(textTwo);
btnTwo.className = 'btn btn-default';
btnGroupOne.appendChild(btnTwo);
var btnThree = document.createElement('button');
var textThree = document.createTextNode('3');
btnThree.appendChild(textThree);
btnThree.className = 'btn btn-default';
btnGroupOne.appendChild(btnThree);
var btnFour = document.createElement('button');
var textFour = document.createTextNode('4');
btnFour.appendChild(textFour);
btnFour.className = 'btn btn-default';
btnGroupOne.appendChild(btnFour);
<div id="buttonHolder"></div>

Try to abstract away as much code as you can, Andy is right a function is best for this sort of task:
function buttonMaker(textnode) {
var btnOne = document.createElement('button');
var textOne = document.createTextNode(textnode);
btnOne.appendChild(textOne);
btnOne.className = 'btn btn-default';
return btnOne;
}
var numberOfButtons = 4;
var btnHolder = document.createElement('div');
// in a loop you can then do this:
for (var i = 1; i <= numberOfButtons; i++) {
btnHolder.appendChild(buttonMaker(i));
}
document.getElementById('btnBox').appendChild(btnHolder);
<div id="btnBox"></div>

Related

Javascript function not looping properly over items

This is my JS that adds evenet listeners to every ideanode:
var ideanodes = [...document.querySelectorAll('.ideanode')];
ideaNodesListRefresh();
function ideaNodesListRefresh(){
ideanodes = [...document.querySelectorAll('.ideanode')];
console.log("refreshed")
ideanodes.forEach(ideanode => {
var maintxt = ideanode.querySelector(".maintext");
var titleArrow = ideanode.querySelector(".title-arrow");
var mainArrow = ideanode.querySelector(".maintxt-arrow");
var comments = ideanode.querySelector(".comments");
titleArrow.addEventListener('click', function() {
maintxt.classList.toggle("hidden");
mainArrow.classList.toggle("hidden");
if (comments.classList.contains("hidden")) {;
} else {
comments.classList.toggle("hidden");
};
});
mainArrow.addEventListener("click", function() {
comments.classList.toggle("hidden");
});
});
};
the function gets fired at the end of the creation of a new ideanode:
function createNeed(user) {
if (user==user1) {
var newNeed = document.createElement('div');
newNeed.className = "ideanode";
var newNeedHeader = document.createElement('div');
newNeedHeader.className = "ideanodeheader";
var newNeedHeaderText = document.createTextNode('Need');
newNeedHeader.appendChild(newNeedHeaderText);
newNeed.appendChild(newNeedHeader);
var newNeedContent = document.createElement('div');
newNeedContent.className = "content";
newNeed.appendChild(newNeedContent);
var needTitle = document.createElement('div');
needTitle.className="title";
var needTitleH3 = document.createElement('h2');
var titleText = document.createTextNode('Title');
needTitleH3.appendChild(titleText);
needTitleH3.setAttribute('onclick', 'this.focus();');
needTitleH3.setAttribute('contenteditable', 'True');
newNeedContent.appendChild(needTitleH3);
var downArrow0 = document.createElement('i');
downArrow0.classList = 'fas fa-sort-down title-arrow';
newNeedContent.appendChild(downArrow0);
var maintext = document.createElement('div');
maintext.classList = 'maintext hidden';
textareaMain = document.createElement("textarea");
textareaMain.className = "maintextinput";
textareaMain.setAttribute('placeholder', 'Text');
maintext.appendChild(textareaMain);
newNeedContent.appendChild(maintext);
var downArrow1 = document.createElement('i');
downArrow1.classList = 'fas fa-sort-down maintxt-arrow hidden';
newNeedContent.appendChild(downArrow1);
var comments = document.createElement('div');
comments.classList = "comments hidden";
textareaComments = document.createElement("textarea");
textareaComments.className = "commentsinput";
textareaComments.setAttribute('placeholder', 'Comments');
comments.appendChild(textareaComments);
newNeedContent.appendChild(comments);
newNeed.appendChild(newNeedContent);
var container = document.querySelector('#needsuser1');
var lastNeed = document.querySelector(".ideanode:last-child");
lastNeed.parentNode.insertBefore(newNeed, lastNeed.nextSibling);
ideaNodesListRefresh();
} else {
console.log("user2")
}
}
But when I add a new ideanode the function doesn't work properly and the eventlisteners only work for the newest ideanode.
This is a codepen of what I'm doing: https://codepen.io/ricodon1000/pen/PoPeXJL
I would like to simply add eventlisteners to the arrows of the new ideanode and have all of the arrows of all of the ideanodes work.

onclick toggle between various text

I want to toggle between multiple text when i click button.I have created a solution but i would to see a better solution and at end of last click event function i want it to continue to start from beginning.
var qarray = ['canada', 'india', 'america']
var btn = document.querySelector('button');
btn.style.background = 'green';
btn.style.fontSize = '25px';
btn.style.color = 'white';
btn.addEventListener('click', function quotes() {
var textselect = document.querySelector('h2');
var one = textselect.textContent = qarray[0];
btn.addEventListener('click', function quoteone() {
var two = textselect.textContent = qarray[1];
btn.addEventListener('click', function() {
var three = textselect.textContent = qarray[2];
})
})
})
<h2>Shows 3 Country onclick</h2>
<button>Change</button>
When you define a new event listener, you're not removing the old one. So eventually all the listeners run, and they keep adding more each time you click.
Just use a single event listener that uses a global variable to hold the current array index.
var qarray = ['canada', 'india', 'america'];
var qindex = 0;
var btn = document.querySelector('button');
btn.style.background = 'green';
btn.style.fontSize = '25px';
btn.style.color = 'white';
btn.addEventListener('click', function quotes() {
var textselect = document.querySelector('h2');
textselect.textContent = qarray[qindex];
qindex = (qindex + 1) % qarray.length;
})
<h2>Shows 3 Country onclick</h2>
<button>Change</button>
The modulus operator is used to make the index wrap around to 0 when you reach the end of the array.
var qarray = ['canada', 'india', 'america']
var btn = document.querySelector('button');
btn.style.background = 'green';
btn.style.fontSize = '25px';
btn.style.color = 'white';
var countClick =0;
btn.addEventListener('click', function quotes() {
var textselect = document.querySelector('h2');
if(qarray.length > countClick) {
textselect.textContent = qarray[countClick];
countClick++;
} else {
countClick =0;
textselect.textContent = qarray[countClick];
}
})
<h2>Shows 3 Country onclick</h2>
<button>Change</button>

Why is the function in my Javascript code executing right away but not when I click the button?

I am having trouble understanding why the text is not changing when I click the button. It is being executed right away when the page starts instead. I am not sure why this is happening because I told it to only execute when you click on the button.
<!DOCTYPE html>
<html id="all">
<head>
<head>
</head>
<title>Lab8</title>
<style></style>
</head>
<body>
<script>
var iDiv = document.createElement('div');
iDiv.id = 'block';
iDiv.className = 'block';
document.getElementsByTagName('body')[0].appendChild(iDiv);
iDiv.style.backgroundColor = "#d79365";
iDiv.style.padding = "40px";
var innerDiv2 = document.createElement('div');
innerDiv2.className = 'block-3';
iDiv.appendChild(innerDiv2);
innerDiv2.style.padding = "40px";
innerDiv2.style.textAlign = "center";
innerDiv2.innerHTML = "Here is changing the text: ";
//innerDiv2.innerHTML = "Text Change when button clicked";
//innerDiv2.style.textAlign = "center";
// Now create and append to iDiv
var innerDiv = document.createElement('div');
innerDiv.className = 'block-2';
// The variable iDiv is still good... Just append to it.
iDiv.appendChild(innerDiv);
innerDiv.innerHTML = "I'm the inner div";
innerDiv.style.padding = "40px";
innerDiv.style.backgroundColor = "#eac67a";
var ClickButton = document.createElement('button');
ClickButton.className = 'block-4';
iDiv.appendChild(ClickButton);
ClickButton.innerHTML = "Style";
ClickButton.style.margin = "auto";
ClickButton.style.display = "block";
ClickButton.style.width = "80px";
ClickButton.style.height = "50px";
ClickButton.style.top = "50px";
ClickButton.style.backgroundColor = "#233237";
ClickButton.style.color = "white";
function js_style(){
alert("hi");
document.querySelector("innerDiv2");
innerDiv2.style.fontSize = 'large';
innerDiv2.style.font = 'italic bold 20px arial,serif';
innerDiv2.style.color = "#eac67a";
};
document.getElementsByTagName('button').onclick = js_style();
</script>
</body>
The problem with your code is that getElementsByTagName returns a HTMLCollection - which behaves a little like an array, in that you can access the individual elements using array syntax like x[0]
However, as you're creating the button dynamically, you can dispense with that, and, in the process, dispense with last millennium code element.onclick=rubbish
var ClickButton = document.createElement('button');
ClickButton.addEventListener('click', js_style);
done
document.getElementsByTagName('button') returns a HTMLCollection.
Setting the 'onclick' value of the HTMLCollection does not set the 'onclick' handle of the button.
i could get the example to work by giving the button an id and retrieving the button via that id (rather than it's tag name):
https://jsfiddle.net/0L1kj3ja/
var iDiv = document.createElement('div');
iDiv.id = 'block';
iDiv.className = 'block';
document.getElementsByTagName('body')[0].appendChild(iDiv);
iDiv.style.backgroundColor = "#d79365";
iDiv.style.padding = "40px";
var innerDiv2 = document.createElement('div');
innerDiv2.className = 'block-3';
iDiv.appendChild(innerDiv2);
innerDiv2.style.padding = "40px";
innerDiv2.style.textAlign = "center";
innerDiv2.innerHTML = "Here is changing the text: ";
//innerDiv2.innerHTML = "Text Change when button clicked";
//innerDiv2.style.textAlign = "center";
// Now create and append to iDiv
var innerDiv = document.createElement('div');
innerDiv.className = 'block-2';
// The variable iDiv is still good... Just append to it.
iDiv.appendChild(innerDiv);
innerDiv.innerHTML = "I'm the inner div";
innerDiv.style.padding = "40px";
innerDiv.style.backgroundColor = "#eac67a";
var ClickButton = document.createElement('button');
ClickButton.id = 'btn';
ClickButton.className = 'block-4';
iDiv.appendChild(ClickButton);
ClickButton.innerHTML = "Style";
ClickButton.style.margin = "auto";
ClickButton.style.display = "block";
ClickButton.style.width = "80px";
ClickButton.style.height = "50px";
ClickButton.style.top = "50px";
ClickButton.style.backgroundColor = "#233237";
ClickButton.style.color = "white";
function js_style(){
alert("hi");
document.querySelector("innerDiv2");
innerDiv2.style.fontSize = 'large';
innerDiv2.style.font = 'italic bold 20px arial,serif';
innerDiv2.style.color = "#eac67a";
};
document.getElementById('btn').onclick = js_style;
instead of
document.getElementsByTagName('button').onclick = js_style();
try this :
var buttons = document.getElementsByTagName('button');
for (var i=0;i<buttons.length;i++)
{
buttons[i].onclick = js_style;
}
when you use js_style(); javascript will call that function so you should just introduce your function name to .onclick
You were attaching onclick event to collection of JS nodes. I've refactored your code and added one more class to button element to attachclick event on that.
It is always advisable to add class with js prefix to attach event handler to DOM elements. In this way,no one will mess with js-* classes.
//create outer div and apply styles
var outerDiv = document.createElement('div');
var outerDivStyle = 'background-color:#d79365;padding: 40px;';
outerDiv.id = 'block';
outerDiv.className = 'block';
document.getElementsByTagName('body')[0].appendChild(outerDiv);
outerDiv.style.cssText = outerDivStyle;
//create inner div and apply styles
var innerDiv = document.createElement('div');
innerDiv.className = 'block-3';
outerDiv.appendChild(innerDiv);
var innerDivStyle = 'padding: 40px;text-align:center;';
innerDiv.innerHTML = "Here is changing the text: ";
innerDiv.style.cssText = innerDivStyle;
//create last div and apply styles
var lastDiv = document.createElement('div');
lastDiv.className = 'block-2';
// The variable iDiv is still good... Just append to it.
outerDiv.appendChild(lastDiv);
lastDiv.innerHTML = "I'm the inner div";
var lastDivStyle = 'background-color:#eac67a;padding: 40px;';
lastDiv.style.cssText = lastDivStyle;
//create button
var clickButton = document.createElement('button');
clickButton.id = 'js-btn';
clickButton.className = 'block-4';
outerDiv.appendChild(clickButton);
var btnStyles = 'background-color:#233237;color: white;margin:auto;display:block;width: 80px; height:50px;';
lastDiv.style.cssText = lastDivStyle;
clickButton.innerHTML = "Style";
clickButton.style.cssText = btnStyles;
function jsStyle() {
alert("hi");
document.querySelector("innerDiv");
innerDiv.style.fontSize = 'large';
innerDiv.style.font = 'italic bold 20px arial,serif';
innerDiv.style.color = "#eac67a";
};
document.querySelector('#js-btn').onclick = jsStyle;

focus is not working on textarea

I am creating a page in which a user can add a question and its solution, he can delete the problem and can also edit it dynamically using DOM in javascript. I want that whenever user clicks on edit button the textbox which appears get autofocus.
This the javascript code of my page...
var questionText;
var answerText;
var questionArray=[];
var answerArray=[];
var i=0;
var j=10000;
function addProblem(){
var body = document.getElementsByTagName('body')[0];
questionText = document.getElementById('questionId').value;
answerText = document.getElementById('answerId').value;
questionArray.unshift(questionText);
answerArray.unshift(answerText);
var myContainer = document.getElementById('container');
var myDiv = document.createElement("div");
var questionLogo = document.createElement("p");
questionLogo.id = "questionLogo";
var textNode = document.createTextNode("Question:");
var question = document.createElement("p");
question.id = "question";
var questionDetail = document.createTextNode(questionArray[0]);
var deleteButton = document.createElement("button");
deleteButton.innerHTML = "Delete";
deleteButton.id = i;
var editButton = document.createElement("button");
editButton.innerHTML = "Edit";
editButton.id = j;
var answerLogo = document.createElement("p");
answerLogo.id = "answerLogo"
var ansTextNode = document.createTextNode("Answer: ");
var answer = document.createElement("p");
answer.id = "answer";
var answerDetail = document.createTextNode(answerArray[0]);
var mybr = document.createElement("br");
if(i==0){
myContainer.appendChild(myDiv);
myDiv.appendChild(questionLogo);
questionLogo.appendChild(textNode);
questionLogo.appendChild(question);
question.appendChild(questionDetail);
myDiv.appendChild(answerLogo);
answerLogo.appendChild(ansTextNode);
answerLogo.appendChild(answer);
answer.appendChild(answerDetail);
answerLogo.appendChild(mybr);
myDiv.appendChild(deleteButton);
myDiv.innerHTML += ' ';
myDiv.appendChild(editButton);
}
else if (i > 0)
{
myContainer.insertBefore(myDiv,myContainer.firstChild);
myDiv.appendChild(questionLogo);
questionLogo.appendChild(textNode);
questionLogo.appendChild(question);
question.appendChild(questionDetail);
myDiv.appendChild(answerLogo);
answerLogo.appendChild(ansTextNode);
answerLogo.appendChild(answer);
answer.appendChild(answerDetail);
answer.appendChild(mybr);
myDiv.appendChild(deleteButton);
myDiv.innerHTML += ' ';
myDiv.appendChild(editButton);
}
i++;
j++;
myDiv.childNodes[7].addEventListener("click", function(){
var deleteElement = document.getElementById(this.id);
deleteElement.parentNode.parentNode.removeChild(deleteElement.parentNode);
});
myDiv.childNodes[9].addEventListener("click",function(){
var editElement = document.getElementById(this.id);
var quesEdit = editElement.parentNode.childNodes[1];
var quesEditText = quesEdit.innerHTML;
var ansEdit = editElement.parentNode.childNodes[4];
var ansEditText = ansEdit.innerHTML;
var editDiv1 = document.createElement("div");
editDiv1.id = "editDiv1"
var quesTextArea = document.createElement("textarea");
quesTextArea.innerHTML += quesEditText;
quesTextArea.focus();
var saveButton1 = document.createElement("button");
saveButton1.innerHTML = "Save";
editDiv1.appendChild(quesTextArea);
editDiv1.innerHTML += ' ';
editDiv1.appendChild(saveButton1);
quesEdit.parentNode.replaceChild(editDiv1,quesEdit);
var editDiv2 = document.createElement("div");
editDiv2.id = "editDiv2"
var ansTextArea = document.createElement("textarea");
ansTextArea.innerHTML += ansEditText;
var saveButton2 = document.createElement("button");
saveButton2.innerHTML = "Save";
editDiv2.appendChild(ansTextArea);
editDiv2.innerHTML += ' ';
editDiv2.appendChild(saveButton2);
ansEdit.parentNode.replaceChild(editDiv2,ansEdit);
});
}
I have tried to focus the textarea using
quesTextArea.focus();
but its not working where questextArea is the name of the textarea. Please help how i can do it.
For the element could be got focused, it must be in the DOM when you invoke focus on it. You should invoke focus function after replaceChild function
editDiv1.appendChild(quesTextArea);
editDiv1.appendChild(saveButton1);
quesEdit.parentNode.replaceChild(editDiv1,quesEdit);
quesTextArea.focus();
I've created a simple sample as below link, you could check it
https://jsfiddle.net/pd9c6c7a/3/
Add autofocus attribute to the textarea element. So that whenever it is appended to the DOM, will get cursor activated in it.
The 'textarea' has not been added to window to be shown, an element must be part of the document object tree. In case that didn't work, add a 50ms delay.
setTimeout(function(){e.focus();}, 50);
Try the following approach:
var body=document.getElementsByTagName('body')[0];
var quesTextArea=document.createElement("textarea");
var button=document.createElement("button");
button.innerHTML = "click Me";
button.addEventListener("click",function(e){
e.preventDefault();
quesTextArea.focus();
});
body.appendChild(quesTextArea);
body.appendChild(button);
<html>
<body>
<body>
</html>
Try to add preventDefault.
var div = document.getElementById('parent');
var txt = document.createElement('textarea');
div.appendChild(txt);
txt.focus();
<html>
<head></head>
<body>
<div id="parent">
<input type="text" value="" />
</div>
</body>
</html>
The element must be in the DOM when you invoke the focus function. Move your focus() function after the appendChild() is invoked.
quesTextArea.innerHTML += quesEditText;
var saveButton1=document.createElement("button");
saveButton1.innerHTML="Save";
editDiv1.appendChild(quesTextArea);
quesTextArea.focus();

Replace header text with button text using JavaScript

I am using only JavaScript to create buttons and need to add click handlers to the buttons that will replace the header with the contents of the buttons. I have been trying to figure out how to do this for a while. Any help would be great! Thank you!
Below is my JavaScript code that creates the buttons and header.
var col = document.createElement('div');
col.className = 'col';
document.body.appendChild(col);
var header = document.getElementById('col');
var h = document.createElement("H3");
h.innerHTML = "Nothing clicked yet!";
col.appendChild(h);
var divOne = document.createElement('div');
col.appendChild(divOne);
var btnOne = document.getElementById('col');
var textOne = ["1", "2", "3", "4"];
textOne.forEach(function(post) {
var postDiv = document.createElement("div");
postDiv.className = 'btn btn-default';
postDiv.innerHTML = post;
col.appendChild(postDiv);
});
Add an event to your button elements, but as other answers pointed out, a good practice is to assign IDs to your elements for more accurate lookup :
var btnOne = document.getElementById('col');
var textOne = ["Left", "Middle", "Right"];
textOne.forEach(function(post) {
var btnGroupFour = document.createElement('button');
btnGroupFour.className = 'btn btn-default';
btnGroupFour.innerHTML = post;
btnGroupFour.addEventListener("click", function() {
var header = document.getElementsByTagName('H3')[0];
header.innerHTML = this.innerHTML;
}, false);
divThree.appendChild(btnGroupFour);
});
First of all, you are not creating buttons, you're creating divs, although you're using the button classes from bootstrap (I gues...).
Anyway, the way to proceed would be to add a onclick attribute with a callback function, witch takes one argument: the event itself. Then, with the target attribute of the event object, you're getting access to the event source tag and with value you will get the value.
Just like this:
<input type="button" id="button" value="Test Value!" />
<span id="output"></span>
<script>
document.getElementById("button").addEventListener('click', callback);
function callback(e) { document.getElementById("output").innerHTML = e.target.value; }
</script>
Just assign an ID for your header, and while creating the buttons in the loop. Just assign the onclick callback of the button, to get the id of the header, and replace the text
textOne.forEach(function(post) {
var btnGroupFour = document.createElement('button');
btnGroupFour.className = 'btn btn-default';
btnGroupFour.innerHTML = post;
btnGroupFour.onclick = function(){document.getElementById('headerID').innerHTML = post} ;
h.appendChild(btnGroupFour);
});
Should Work for your situation.
A short Demo
Fairly simple, just add an eventListener onto the element during creation. All I really had to add to your code was: .addEventListener("click", function(){ h.innerHTML = post;});
http://www.w3schools.com/jsref/met_element_addeventlistener.asp
<!DOCTYPE html>
<html>
<body>
<p>Hover over the checkbox to simulate a mouse-click.</p>
<script>
var divContainer = document.createElement('div');
divContainer.className = 'container';
document.body.appendChild(divContainer);
var row = document.createElement('div');
row.className = 'row';
divContainer.appendChild(row);
var col = document.createElement('div');
col.id = 'col-md-12';
row.appendChild(col);
var header = document.getElementById('col');
var h = document.createElement("H3");
h.innerHTML = "Nothing clicked yet!";
col.appendChild(h);
var star = document.createElement('div');
col.appendChild(star);
var btnStar = document.getElementById('col');
var textStar = ["Star"];
textStar.forEach(function(post) {
var postStar = document.createElement("div");
postStar.className = 'btn btn-default';
postStar.innerHTML = post;
postStar.addEventListener("click", function(){
h.innerHTML = post;});
col.appendChild(postStar);
});
var secondLine = document.createElement("HR");
document.body.appendChild(secondLine);
col.appendChild(secondLine);
var divOne = document.createElement('div');
col.appendChild(divOne);
var btnOne = document.getElementById('col');
var textOne = ["1", "2", "3", "4"];
textOne.forEach(function(post) {
var postDiv = document.createElement("div");
postDiv.className = 'btn btn-default';
postDiv.innerHTML = post;
postDiv.addEventListener("click", function(){
h.innerHTML = post;});
col.appendChild(postDiv);
});
var btnTwo = document.getElementById('col');
var textTwo = ["5", "6", "7", "8"];
textTwo.forEach(function(post) {
var btnGroupFour = document.createElement('button');
btnGroupFour.className = 'btn btn-default';
btnGroupFour.innerHTML = post;
btnGroupFour.addEventListener("click", function(){
h.innerHTML = post;});
col.appendChild(btnGroupFour);
});
var secondLine = document.createElement("HR");
document.body.appendChild(secondLine);
col.appendChild(secondLine);
var divThree = document.createElement('div');
col.appendChild(divThree);
var btnOne = document.getElementById('col');
var textOne = ["Left", "Middle", "Right"];
textOne.forEach(function(post) {
var btnGroupFour = document.createElement('button');
btnGroupFour.className = 'btn btn-default';
btnGroupFour.innerHTML = post;
btnGroupFour.addEventListener("click", function(){
h.innerHTML = post;});
divThree.appendChild(btnGroupFour);
});
</script>
</body>
</html>

Categories

Resources