I'm trying to give a button inside all my class .why-text. I selected them by document.querySelectorAll('.why-text'); And use the loop "for" to append button to all the class. But it doesn't working. This is my code:
var btnAddCart = document.createElement("button");
btnAddCart.innerHTML = "Add";
var WhyTxt = document.querySelectorAll('.why-text');
for (let i = 0; i < WhyTxt.length; i++) {
WhyTxt[i].appendChild(btnAddCart);
}
You create only one button, then keep appending that very same button to n locations, so it ends up in the last of those. Appending an element that is already in the DOM effectively moves that element.
You need to create the button in the loop to have individual buttons:
const WhyTxt = document.querySelectorAll('.why-text');
for (let i = 0; i < WhyTxt.length; i++) {
const btnAddCart = document.createElement("button");
btnAddCart.textContent = "Add";
WhyTxt[i].appendChild(btnAddCart);
}
That being said, your code can also be simplified by alot:
for (let el of document.querySelectorAll(".why-text")) {
el.append(Object.assign(document.createElement("button"),{textContent:"Add"}));
}
You have to create the element each time, within the loop. It could be made outside the looped and cloned within it but you are only making one element in the current structure so it can only be added once.
This working snippet uses the simple approach of making a new button element inside each loop of the parent collection.
var WhyTxt = document.querySelectorAll('.why-text');
console.log(WhyTxt.length);
for (let i = 0; i < WhyTxt.length; i++) {
var btnAddCart = document.createElement("button");
btnAddCart.innerHTML = "Add";
WhyTxt[i].appendChild(btnAddCart);
}
div {
height: 2em;
background: yellow;
}
<div class="why-text"></div><br>
<div class="why-text"></div><br>
<div class="why-text"></div><br>
<div class="why-text"></div><br>
<div class="why-text"></div><br>
Related
As the title says, can I use javascript to create a button on a html page for every item in a list of size n.
If it is, could anyone give me an example of how this may be done? Thank you.
If you're just using JS without any frameworks, you can append a button to a container, and run it multiple times. Use document.createElement() to make the button, and element.appendChild() to append it.
const container = document.getElementById("my-container");
const amountOfButtons = 5;
for (let i = 1; i <= amountOfButtons; i++) {
const button = document.createElement("button");
button.textContent = "Button #" + i; // add text to the button
container.appendChild(button); // append the button
}
<div id="my-container">
<!-- Buttons will go here -->
</div>
Edit: If you have a list rather than an "amount of buttons", you loop through each list item using a for...of loop or similar, like so:
const container = document.getElementById("my-container");
const myList = [
"list item 1",
"list item 2",
"thanks for coming to my ted talk",
"goodbye"
];
for (const listItem of myList) {
const button = document.createElement("button");
button.textContent = listItem;
container.appendChild(button); // append the button
}
<div id="my-container">
<!-- Buttons will go here -->
</div>
Create a for loop for i < list.length and create a new button each iteration, appending as you would like.
var list = document.getElementsBy(...); // Choose a method for selecting your items
for(var i = 0; i < list.length; i++) {
var button = document.createElement("button");
// Probably set the innerHTML/textContent and maybe class
element.append(button); // Append to the element of your choice
}
I am trying to get the index value of a particular element that is clicked on from a for loop array. What i would like to do is then use this index value and pass it to a variable called indexValue which will then determine a specific div to show. The div it will show will be the one with the same index value that was passed to the variable. I hope this makes sense, I am just not to sure how to achieve this?
The markup would be something like this
HTML
<div class="button"></div>
<div class="button"></div>
<div class="button"></div>
<div class="button"></div>
CSS
.test {
display: none;
}
.show {
display: block;
}
JS
var button = document.querySelectorAll('.button');
for (var i = 0; i < button.length; i++) {
button[i].addEventListener('click', function () {
var indexValue: //Get index value from clicked element
var test = document.querySelectorAll('.test');
test[indexValue].classlist.add('show');
}
}
You can put your eventListener in a closure that takes a parameter from your loop. The alert is only so that when you click it in the fiddle you can see the result of the index
var button = document.querySelectorAll('.button');
for (var i = 0; i < button.length; i++) {
button[i].addEventListener('click', ((j) => {
return function() {
alert(j)
}
})(i))
}
http://jsfiddle.net/cbpw61ur/20/
I'm trying to apply the onclick event with JavaScript to the following elements:
<div class="abc">first</div>
<div class="abc">second</div>
<div class="abc">third</div>
If I click on the first element (with index [0]) then this works, but I
need this event applicable for all classes:
document.getElementsByClassName('abc')[0].onclick="function(){fun1();}";
function fun1(){
document.getElementsByClassName('abc').style.color="red";
}
.onclick does not expect to receive a string, and in fact you don't need an extra function at all.
However, to assign it to each element, use a loop, like I'm sure you must have learned about in a beginner tutorial.
var els = document.getElementsByClassName('abc');
for (var i = 0; i < els.length; i++) {
els[i].onclick = fun1;
}
function fun1() {
this.style.color = "red";
}
<div class="abc">first</div>
<div class="abc">second</div>
<div class="abc">third</div>
To expand on the solution provided by #rock star I added two small additions to the function. First it is better to add / reemove a class (with an associated style rule) to an element than directly applying the stylerule to the element.
Secondly - on the click event - this will now remove the red class (and therefore style) from the previously selected element and add it to the new element. This will allow only one element to be red at a time (in the original solution any element that was clicked would become red).
var els = document.getElementsByClassName('abc');
for (var i = 0; i < els.length; i++) {
els[i].onclick = fun1;
}
function fun1() {
var oldLink = document.getElementsByClassName('red')[0];
if(oldLink) {oldLink.classList.remove('red')};
this.classList.add('red');
}
.red {
color:red;
}
<div class="abc">first</div>
<div class="abc">second</div>
<div class="abc">third</div>
This works:
<body>
<div class="abc">first</div>
<div class="abc">second</div>
<div class="abc">third</div>
<script>
var elements = document.getElementsByClassName('abc');
for(var i = 0, max = elements.length; i < max; i += 1) {
var clickedElement = elements[i];
clickedElement.onclick=function (){
fun1(this);
};
}
function fun1(element){
element.style.color="red";
}
</script>
</body>
I'm attempting to add data-webpart attributes to all the anchors within a document, but populate their values with the data attributes of their containing divs.
However the code I wrote appears to be populating all of the anchors with only one of the data attributes (or rather, adding the first one to all, then adding the second).
Any help would be much appreciated!
HTML
<body>
<div data-webpart="form">
Test Link
Test Link
Test Link
</div>
<div data-webpart="icon-grid">
Test Link
Test Link
Test Link
</div>
</body>
JavaScript
// data attributer
var webParts = document.querySelectorAll("[data-webpart]");
var webPartAnchors = document.querySelectorAll("[data-webpart] > a");
function addDataAttr() {
var closestWebPartAttr;
for (i = 0; i < webPartAnchors.length; i++) {
for (e = 0; e < webParts.length; e++) {
closestWebPartAttr = webParts[e].getAttribute("data-webpart");
webPartAnchors[i].setAttribute("data-web-part", closestWebPartAttr);
}
}
}
window.onload = function() {
if (webParts !== null) { addDataAttr(); }
};
Your nested loops are copying the data attribute from every DIV to every anchor, because there's nothing that relates each anchor to just their parent. At the end they all have the last data attribute.
Since the anchors are direct children of the DIV, you don't need to use querySelectorAll() to get them, you can just use .children() within the loop.
function addDataAttr() {
for (var i = 0; i < webParts.length; i++) {
var webpart = webParts[i].dataset.webpart;
var children = webParts[i].children;
for (var j = 0; j < children.length; j++) {
children[j].dataset.webpart = webpart;
}
}
}
I am trying to toggle multiple classes onclick using vanilla Javascript. What i am trying to do is when a btn is clicked two classes to toggle with another two classes. I have 5 classes in total which are: .menu_btn , .main_nav, .btn_active, .container, .container_active. When i press the .menu_btn i would like the classes .main_nav to toggle with .btn_active and at the same time i would like to have the .container to toggle with .container_active. The class .container is the only one that has 5 elements of that class, the others are single. I have done this using jQuery but i would like to know the way using vanilla Javascript. Hopefully someone can help.
One thing to point out is when i console.log the .btn_active and .container_active i get back [ ] an empty array. Those 2 css classes are not assigned to any element of my project. They are existing only in the css and their purpose is for toggle.
Thanks
jQuery Code:
$(function(){
$(".menu_btn").on("click", function(){
$(".main_nav").toggleClass("btn_active");
$(".container").toggleClass("container_active");
});
});
Vanilla Javascript Code:
var menuBtn = document.getElementsByClassName("menu_btn");
var mainNav = document.getElementsByClassName("main_nav");
var btnActive = document.getElementsByClassName("btn_active");
var container = document.getElementsByClassName("container");
var containerActive = document.getElementsByClassName("container_active");
menuBtn.onclick = function(){
mainNav.classList.toggle(btnActive);
for ( index = 0; index <= container.lenght -1; index++ ){
container[index].classList.toggle(containerActive);
}
};
I have modified your script and created a fiddle so you see how it works: https://jsfiddle.net/eyrpdsc2/
The toggle accepts a string as a parameter, not a Node. So you need to pass 'btn_active' instead of btnActive. Also keep in mind that querySelectorAll returns a NodeList (not an array) so you cannot use forEach.
var menuBtn = document.querySelectorAll(".menu_btn");
var mainNav = document.querySelectorAll(".main_nav");
var container = document.querySelectorAll(".container");
for (var i = 0; i < menuBtn.length; ++i) {
menuBtn[i].addEventListener('click', toggleClasses);
}
function toggleClasses() {
var i = 0;
for (i = 0; i < mainNav.length; ++i) {
mainNav[i].classList.toggle('btn_active');
}
for (i = 0; i < container.length; ++i) {
container[i].classList.toggle('container_active');
}
}