Why Is a "for" Loop Needed to Make This Onclick Mechanism Work? - javascript

The code is supposed to create two buttons that produce a paragraph once clicked. Although the function to create a paragraph works, the buttons do not trigger the function.
The HTML is as follows, which I believe is correct.
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<title>Apply JavaScript example</title>
<script src="scripts/t.js" defer></script>
</head>
<body>
<button>Click 1</button>
<br>
<button>Click 2</button>
</body>
</html>
JS#1:
`function createParagraph() {
let paragraph = document.createElement('p');
paragraph.textContent = 'text';
document.body.appendChild(paragraph);
}
const buttons = document.querySelectorAll('button');
buttons.onclick = createParagraph();
`
JS#2: After seeing that it did not work, I changed the last line to buttons.addEventListener('click', createParagraph);, which led to no solution.
This document suggests the following code
`for(let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', createParagraph);
}`
, the complexity/length of which led me to seek a simpler approach.
I do not understand how the last code works but JS#1 and JS#2 do not.
You can see the entire (working) code in action below:
function createParagraph() {
let paragraph = document.createElement('p');
paragraph.textContent = 'text';
document.body.appendChild(paragraph);
}
const buttons = document.querySelectorAll('button');
for(let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', createParagraph);
}
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<title>Apply JavaScript example</title>
<script src="scripts/t.js" defer></script>
</head>
<body>
<button>Click 1</button>
<br>
<button>Click 2</button>
</body>
</html>

querySelectorAll() returns a NodeList so you need to iterate through all of them in order to call the addEventListener method of every element.
You cannot call method addEventListener on a NodeList.

Related

Buttons disappearing after clicking on them Js/html

`Hello there, I'm trying to write a counter code in which I have two buttons (Increase and Decrease), I created the functions, and it works but the buttons disappear.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Buttons practice</title>
<script src="/JavaScript/buttons_practice.js" defer></script>
</head>
<body>
<button id="todo-button" onclick="DoneChange()">Changing Text</button>
<div id="counter">0
<button id="up">Up</button>
<button id="down">Down</button>
</div>
<div id="counter">0</div>
</body>
</html>
const Counter = document.getElementById('counter');
const Up = document.getElementById('up');
const Down = document.getElementById('down');
let count = 0;
Up.addEventListener('click', function Increase(){
count = count + 1;
UpdateCounter();
});
Down.addEventListener('click', function Decrease() {
count = count -1;
UpdateCounter();
});
function UpdateCounter() {
Counter.innerText= count;
}
I was reading some similar questions, but I couldn't figure it out. Some answers aimed to the InnerText to be the Issue, however I can see this code works, I'm basically using the event listener so I can have Html exclusive to Html, it's modular and better at reading the code I think.
<div id="counter">0</div>
<button onclick="countUp()">Up</button>
<button onclick="countDown()">Down</button>
<script>
let count = 0;
function countUp() {
count = count + 1;
updateCount();
}
function countDown() {
count = count - 1;
updateCount();
}
function updateCount() {
let counter = document.getElementById('counter');
counter.innerText = count;
}
</script>
The buttons are inside the counter. Consequently, when you rewrite the contents of the counter (with innerText) you replace the buttons.
Don’t put the buttons inside the counter.
You have two elements with id counter in this block:
<div id="counter">0
<button id="up">Up</button>
<button id="down">Down</button>
</div>
<div id="counter">0</div>
When you do
Counter.innerText= count;
you override everything that you have within the first counter div that contains buttons, and as a result, they disappear.

cannot change css property of desired amount of elements using eventListener due to elements being created by javascript

I am attempting to change the backgroundColor of "gridElement" once "button" is clicked.
What was attempted, changing the way the elements are created to later include the event:
cloneNode() // doesn't work with eventListeners unless you use eventDelegation, in this case there is no parentElement to delegate the event too.
jQuery.clone() // the event is not tied directly to "gridElement" rather it is tied to "button" so jQuery.clone() would not be deep copying any associated events.
Also, attempting to make references to all gridElements:
used window.globalVarRef = localVar. // only references the first element and not all.
How can I modify the code so that the eventListener will change all "gridElement" and not just the first?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="CSS/main.css">
<title> Method 1 // appendChild() </title>
</head>
<body>
<div id="container">
<div id="gridContainer"></div>
</div>
<script>
const gridContainer = document.getElementById('gridContainer');
function createPixels(){
let pixels = 256;
for(let k=0;k<pixels;k++) {
const gridElement = document.createElement('div');
gridElement.classList.add('gridElement');
gridContainer.appendChild(gridElement);
window.allGridElements = gridElement;
}
}
createPixels();
const button = document.createElement('button');
button.classList.add('button');
button.textContent = 'button';
gridContainer.appendChild(button);
function changeBkg(){
window.allGridElements.style.backgroundColor = 'blue';
}
button.addEventListener('click', changeBkg);
</script>
</body>
</html>
The problem lies in your changeBkg function. To select all of the elements with the class of "gridElement", you want to use a for loop to find those elements and then change their styles. I added some basic css to the grid element so we can see the color change in action. Does that solve your issue?
.gridElement {
width: 100px;
height: 100px;
background: red;
display: inline-block;
margin-right: 10px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="CSS/main.css">
<title> Method 1 // appendChild() </title>
</head>
<body>
<div id="container">
<div id="gridContainer"></div>
</div>
<script>
const gridContainer = document.getElementById('gridContainer');
function createPixels(){
let pixels = 256;
for(let k=0;k<pixels;k++) {
const gridElement = document.createElement('div');
gridElement.classList.add('gridElement');
gridContainer.appendChild(gridElement);
window.allGridElements = gridElement;
}
}
createPixels();
const button = document.createElement('button');
button.classList.add('button');
button.textContent = 'button';
gridContainer.appendChild(button);
function changeBkg(){
var items = document.getElementsByClassName('gridElement');
for (let i=0; i < items.length; i++) {
items[i].style.backgroundColor = 'blue';
}
}
button.addEventListener('click', changeBkg);
</script>
</body>
</html>

HTML Button not creating alert

I know I am probably missing something very simple, but why isn't the alert showing up when the button is clicked? Is it something to do with the function within the "addEventListener"?
Thanks!
const button = document.getElementsByTagName("button");
button.addEventListener("click", function(event){
alert("Heyyyy!")
})
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<p>
<button type="button">Click Me!</button>
</p>
<script src=Test.js></script>
</body>
</html>
check your console you probably have "addEventListener is not a function" error and that's because
document.getElementsByTagName("tag-name")
returns an array of DOM elements since a tag name isn't unique across the DOM elements like the id.
so you have two options give the button an id and use
document.getElementById("button-id")
or just get the first item in the array
const button = document.getElementsByTagName("button")[0];
button.addEventListener("click", function(event){
alert("Heyyyy!")
})
You can simply use only a function and the onclick property, like this:
HTML
<button id="myButton" onclick="var msg='message'; alertFunction(msg);">Click Me!</button>
JS
function alertFunction(msg) { alert(msg); }
The reason is because getElementsByTagName(tagName) returns an Array so you must loop through it to add the event listener.
But if you only needs to add to a specific button, then use id to reference the button.
E.g
To assign to every button:
const button = document.getElementsByTagName("button");
Array.from(button).forEach((el) => {
el.addEventListener("click", function(event){
alert("Heyyyy!")
})
});
The need for Array.from(element) is because HTML element is an array-like not a pure array.
To assign to a specific button:
Simply:
buttonId.addEventListener('click', function(){})
const button = document.getElementsByTagName("button");
button.addEventListener("click", function(event){
alert("Heyyyy!")
})
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<p>
<button type="button">Click Me!</button>
</p>
<script src=Test.js></script>
</body>
</html>
Try window.addEventListener();

Vanilla JS ForEach element and assigning ascending variable

I'm trying to make a simple one month calendar using Vanilla JS. I read that PHP can be used to create multiple repeating elements but I was wondering whether doing it the I'm trying is possible. I'm creating buttons and using a for loop to make 31 of them to fill up my month. I'm also trying to make it so the button contains the day number using the variable day. Not sure how to do that, I was thinking for loop and using i as the value for day, but then it would just end on whatever the last i value was.
Since it's not working I'm coming here for help, I'd like to solve this using Vanilla JS if possible. Thank you.
TLDR: For loop to make buttons and variable to assign ascending value to each.
<!DOCTYPE html>
<html>
<head>
<title>Calendar</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
<script type="text/javascript">
var day;
function dateMaker() {
for (i = 0; i < 31; i++) {
var btn = document.createElement("button");
btn.className("date");
btn.innerHTML = day;
document.body.appendChild(btn);
}
}
</script>
</head>
<body>
<h1>July 2020</h1>
<div id="calendar">
<script>
dateMaker();
</script>
</div>
</body>
</html>
You need to add use classList.add to add class to your dynamic elements. Couple of mistakes and fixes which i have hightlighted below
Also, ideally use .textContent intead of .innerHTML
You can appendChild and display you days in the calendar
Use classList to add classes to your dynamic elements
You are declaring day variable but not using it in your code.
Run Snippet below.
function dateMaker() {
for (i = 1; i < 31; i++) {
var btn = document.createElement("button");
btn.classList.add("date");
btn.textContent = i;
document.getElementById('calendar').appendChild(btn) ;
}
}
dateMaker();
<!DOCTYPE html>
<html>
<head>
<title>Calendar</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
<script type="text/javascript">
var day;
</script>
</head>
<body>
<h1>July 2020</h1>
<div id="calendar"></div>
<script>
</script>
</div>
</body>
</html>

Cannot read property 'getElementById' of null

I'm writing a simple Cat Clicker app with HTML and JS, but this code keeps spitting 'Cannot read property 'getElementById' of null' error.
What's wrong with it??
<!DOCTYPE html>
<html>
<head>
<title>Cat Clicker</title>
<script>
'use strict'
var cat = document.getElementById("cat");
var counter = document.getElementById("counter");
var meter = 0;
function incClick() {
meter++;
counter.innerHTML = meter;
};
cat.addEventListener('click', incClick);
</script>
</head>
<body>
<p id="counter" >0</p>
<img id="cat" src="img/cat1.jpg" alt="cat">
</body>
</html>
I've corrected a few issues below. You need to use document rather than document.body. You need to ensure the dom has completed loading so I added a content loaded event listener.
<!DOCTYPE html>
<html>
<head>
<title>Cat Clicker</title>
<script>
'use strict'
document.addEventListener("DOMContentLoaded", function() {
var cat = document.getElementById("cat");
var counter = document.getElementById("counter");
var meter = 0;
function incClick() {
meter++;
counter.innerHTML = meter;
};
cat.addEventListener('click', incClick);
});
</script>
</head>
<body>
<p id="counter" >0</p>
<h1 id="cat" src="img/cat1.jpg" alt="cat"></h1>
</body>
</html>
You need to include <script> Tags after the body of the HTML DOC or at least at the very end of your HTML content.
This is b/c how the DOM operates. It loads everything in a sequential order, thus your script it attempting to target an element which doesn't yet exist in the DOM
Just put your script tag after the body tag because I think the problem is that the DOM is rendering after the script runs.
And you can also use document.getElementById instead of document.body.getElementById
just use onclick="incClick()" in your h1 tag , or u can define it as image
<!DOCTYPE html>
<html>
<head>
<title>Cat Clicker</title>
</head>
<body>
<p id="counter">0</p>
<h1 id="cat" src="img/cat1.jpg" alt="cat"></h1>
<p class="counter">0</p>
<img class="cat" src="img/cat2.jpg" alt="cat">
<!--
You need to put the script tag at the end of the body
Because the document must first be created
-->
<script>
'use strict'
var cat = document.getElementById("cat");
var counter = document.getElementById("counter");
var meter = 0;
function incClick() {
meter++;
counter.innerHTML = meter;
};
cat.addEventListener('click', incClick);
</script>
</body>
</html>
This worked for me. You are mistakenly calling getElementById from document.body where it doesn't exist. It is document.getElementById:
<!DOCTYPE html>
<html>
<head>
<title>Cat Clicker</title>
<script>
'use strict'
var cat = document.getElementById("cat");
var counter = document.getElementById("counter");
var meter = 0;
function incClick() {
meter++;
counter.innerHTML = meter;
};
cat.addEventListener('click', incClick);
</script>
</head>
<body>
<p id="counter">0</p>
<h1 id="cat" src="img/cat1.jpg" alt="cat"></h1>
<!-- <p class="counter">0</p>
<img class="cat" src="img/cat2.jpg" alt="cat"> -->
</body>
</html>

Categories