I wanted to log the elements of the clicked button to the console, but it only worked for "CLICK ME 1." It did not work for another button.
var testLog = (function(){
var getButton = document.querySelector('.button__');
getButton.addEventListener('click', checkPlease);
function checkPlease(event){
console.log(event.target);
}
})();
<section class="product">
<div class="product__wrapper">
<div class="item">
<button class="button__">CLICK ME 1</button>
<button class="button__">CLICK ME 2</button>
</div>
</div>
</section>
Please use querySelectorAll to get all the elements and then forEach on the returned nodelist to attach addEventListener to each element
var getButtonList = document.querySelectorAll('.button__');
getButtonList.forEach(el => el.addEventListener('click', checkPlease));
you get only first button, because of document.querySelector in your code. Use document.querySelectorAll instead
Attach your event listener to all elements, using loop, like this:
var getButton = document.querySelectorAll('.button__');
getButton.forEach(el => el.addEventListener('click', checkPlease))
Try this: you need to use querySelectorAll:
var getButton = document.querySelectorAll(".button__");
if (getButton && getButton.length > 0) {
getButton.forEach((element) => {
element.addEventListener("click", checkPlease);
});
}
function checkPlease(event: any) {
console.log(event.target);
}
Instead of adding a listener per button, you can use event delegation by adding a single listener to the parent element and differentiating by target details.
const testLog = (function(){
const buttonContainer = document.querySelector('.item');
buttonContainer.addEventListener('click', checkPlease);
function checkPlease(event){
console.log(event.target);
}
})();
<section class="product">
<div class="product__wrapper">
<div class="item">
<button class="button__">CLICK ME 1</button>
<button class="button__">CLICK ME 2</button>
</div>
</div>
</section>
Related
I'm trying to make a copy of the original container div with the cloneNode method in javascript inside the container there are 3 buttons with btn class, when I make a copy of the original one the last only the last element in the copied item is only printing hello in the console, any ideas?
let add = document.querySelector('.add-button');
const item = document.querySelector('.container');
let btn = document.querySelectorAll('.btn');
add.addEventListener('click', function() {
makecopy();
});
btn.forEach(el => {
el.addEventListener('click', function() {
console.log("hello")
})
});
function makecopy() {
let copiedItem = item.cloneNode(true);
item.parentNode.insertBefore(copiedItem, item);
}
<div class="add-panel">
<button type="button" class="add-button">Create new</button>
</div>
<div class="container">
<div>
<button type="button" class="btn">+</button>
</div>
<div>
<button type="button" class="btn">+</button>
</div>
<div>
<button type="button" class="btn">+</button>
</div>
You are only setting up event listeners on the first set of buttons, not the cloned ones. Instead of setting up listeners on each button, use "event delegation" to allow the event to "bubble" up to a common ancestor and handle the event there. This way, all the newly added elements will immediately work without needing their own handler and there is only one handler that needs to be set up instead of many.
You've also got some redundant code and code that will no longer be needed when you take this approach.
// No need to set up an anonymous handler that calls the real one. Just
// register the real one
document.querySelector('.add-button').addEventListener('click', makecopy);
const item = document.querySelector('.container');
function makecopy() {
let copiedItem = item.cloneNode(true);
item.parentNode.insertBefore(copiedItem, item);
}
// Listen for clicks on the document:
document.addEventListener('click', function(event) {
// Check to see if it was a button that was clicked:
if(event.target.classList.contains("btn")){
console.log("hello");
};
});
<div class="add-panel">
<button type="button" class="add-button">Create new</button>
</div>
<div class="container">
<div>
<button type="button" class="btn">+</button>
</div>
<div>
<button type="button" class="btn">+</button>
</div>
<div>
<button type="button" class="btn">+</button>
</div>
</div>
Just appears you weren't adding new listeners when you made new buttons. Some adjustments.
let add = document.querySelector('.add-button');
const item = document.querySelector('.container');
let btn = document.querySelectorAll('.btn');
add.addEventListener('click', function() {
makecopy();
});
btn.forEach(el => {
el.addEventListener('click', function() {
console.log("hello")
})
});
function makecopy() {
let copiedItem = item.cloneNode(true);
item.parentNode.insertBefore(copiedItem, item);
copiedItem.addEventListener('click', function() {
console.log("hello")
})
}
<div class="add-panel">
<button type="button" class="add-button">Create new</button>
</div>
<div class="container">
<div>
<button type="button" class="btn">+</button>
</div>
<div>
<button type="button" class="btn">+</button>
</div>
<div>
<button type="button" class="btn">+</button>
</div>
I want to be able to modify/output to the content of particular header tag with the id attribute value of whichever anchor/link is clicked.
Currently, i am able to only change the text "City" with the value of the first id ("New York", in the below example) - because the text is outside of the nested div tags, but still within the anchor tags. so the first link works, but the 2nd and 3rd links pass empty strings/give no output. i want to the text/content to remain within the div tags as in the 2nd and 3rd links.
<base target=splash>
<H3 id=myTitle onclick="myFunction()">City</H3>
<a class="clickable" href="myPage.htm?id=108" id="New+York">New York
<div class=cityWrap>
<DIV class=cityNo>108</DIV>
<DIV class=cityName>New York</DIV>
<DIV class=country>USA</DIV>
</div>
</a>
<a class="clickable" href="myPage.htm?id=110" id="Shanghai">
<div class=cityWrap>
<DIV class=cityNo>110</DIV>
<DIV class=cityName>Shanghai</DIV>
<DIV class=country>China</DIV>
</div>
</a>
<a class="clickable" href="myPage.htm?id=112" id="Damascus">
<div class=cityWrap>
<DIV class=cityNo>112</DIV>
<DIV class=cityName>Damascus</DIV>
<DIV class=country>Syria</DIV>
</div>
</a>
<IFRAME src="myPage.htm" name=splash></IFRAME>
<script>
window.addEventListener('load', () => {
let myFunction = event => {
let clickedElem = event.target;
document.getElementById('myTitle').innerHTML = clickedElem.id;
};
for (let elem of document.getElementsByClassName('clickable')) elem.addEventListener('click', myFunction);
});
</script>
Step 1: Add listeners to all required elements
You have a couple of options.
You could exhaustively list all clickable ids in your javascript:
let ids = [ 'New York', 'Shanghai', 'Damascus' /* ... */ ];
for (let id of ids) document.getElementById(id).addEventListener('click', myFunction);
You could target the clickable elements by the fact that they are all a elements:
for (let elem of document.getElementsByTagName('a')) elem.addEventListener('click', myFunction);
You could attach a common class for all desired a elements, and use document.getElementsByClassName:
html:
<a class="clickable" href="myPage.htm?id=New York" id="New York">New York</A>
<a class="clickable" href="myPage.htm?id=Shanghai" id="Shanghai">Shanghai</A>
<a class="clickable" href="myPage.htm?id=Damascus" id="Damascus">Damascus</A>
js:
for (let elem of document.getElementsByClassName('clickable')) elem.addEventListener('click', myFunction);
Step 2: Determine which element was clicked inside of myFunction:
Now the same function, myFunction, gets called no matter which element is clicked. We have to figure out which specific element was clicked, to determine which id to display.
Fortunately Event.target does this for us. We can rewrite myFunction to look like this:
let myFunction = event => {
// Get the <a> element that was clicked
let clickedElem = event.target;
// Apply that element's id as the innerHTML of the #myTitle element
document.getElementById('myTitle').innerHTML = clickedElem.id;
};
Final code
Could look something like this:
window.addEventListener('load', () => {
let myFunction = event => {
let clickedElem = event.target;
document.getElementById('myTitle').innerHTML = clickedElem.id;
event.preventDefault(); // Important to prevent page navigation
};
for (let elem of document.getElementsByTagName('a')) elem.addEventListener('click', myFunction);
});
[href$="=108"], [href$="=108"] * { background-color: #ffa0a0; }
[href$="=110"], [href$="=110"] * { background-color: #a0ffa0; }
[href$="=112"], [href$="=112"] * { background-color: #a0a0ff; }
a > div { pointer-events: none; }
<h3 id=myTitle>City</H3>
<a href="myPage.htm?id=108" id="New+York">New York
<div class=cityWrap>
<DIV class=cityNo>108</DIV>
<DIV class=cityName>New York</DIV>
<DIV class=country>USA</DIV>
</div>
</a>
<a href="myPage.htm?id=110" id="Shanghai">
<div class=cityWrap>
<DIV class=cityNo>110</DIV>
<DIV class=cityName>Shanghai</DIV>
<DIV class=country>China</DIV>
</div>
</a>
<a href="myPage.htm?id=112" id="Damascus">
<div class=cityWrap>
<DIV class=cityNo>112</DIV>
<DIV class=cityName>Damascus</DIV>
<DIV class=country>Syria</DIV>
</div>
</a>
you can try something like this for each of the links
<a onclick="getElementById('myTitle').innerHTML = your title here">your value here</a>
else try searching for w3schools onclick event
hope this helps :>
I want to run a function anytime one of a series of elements are clicked and want to target these elements using a partial ID. Currently, only the first element responds when clicked upon. What have I done wrong? My code:
HTML:
<div>
<a id="selector-0">Zero</a>
</div>
<div>
<a id="selector-1">One</a>
</div>
<div>
<a id="selector-2">Two</a>
</div>
JS:
document.querySelector('[id^="selector-"]').onclick = function(){
var id_selector = this.getAttribute('id');
alert('ID: ' + id_selector);
}
I have attempted changing the querySelector to include 'a[id^="selector-"]', but only the first element ever wants to respond on click.
Use *= selector with id as attribute and document.querySelectorAll.
Then add the onclick to all the elements of the given array of retrieved elements.
const els = Array.from(document.querySelectorAll('[id*=selector-]'));
console.log(els.length);
els.forEach(el => el.onclick = () => console.log('Clicked el:', el));
<div>
<a id="selector-0">Zero</a>
</div>
<div>
<a id="selector-1">One</a>
</div>
<div>
<a id="selector-2">Two</a>
</div>
I'm trying to add an event to multiple elements. For now, I have this code and it works. But, I want to use Event Delegation and move the listener to the parent element (deck). I've tried so many solutions found here on Stack, but none of them it's working.
Question, which will be the best way to delegate the event?
HTML
<section class="deck">
<div class="card">
<div class="front"></div>
<div class="back">
<img src="#" alt="">
</div>
</div>
<div class="card">
<div class="front"></div>
<div class="back">
<img src="#" alt="">
</div>
</div>
...
JavaScript
var card = document.querySelectorAll(".card");
var len = card.length;
for (let i = 0; i <= len; i++) {
card[i].onclick = function () {
this.classList.add("foo");
}
}
Simple event delegation could look like this in your case:
var deck = document.querySelector(".deck");
deck.addEventListener('click', function (e) {
var target = e.target
if (target.classList.contains('card')) {
target.classList.add('foo')
}
})
Note, this check target.classList.contains('card') is necessary so that you add class foo only to elements with class .card.
var deck = document.querySelector('.deck');
deck.onclick = function(clickevent)
{
if (clicked.target.closest('.card'))
clickevent.target.closest('.card').classList.add('foo');
}
The element that is clicked (the target of the click event) might be the img for example. You want to add foo to the card element that is an ancestor of the target. The closest() method finds that element.
I have 4 Button with class of active and now I wanna remove all of those class and then only add 1 class to the one I clicked on.
<button class="active btn">btn1</button>
<button class="active btn">btn2</button>
<button class="active btn">btn3</button>
<button class="active btn">btn4</button>
here is code I wrote so far:
let buttonOptions = document.querySelectorAll(".btn");
for (let i=0; i< buttonOptions.length; i++) {
buttonOptions.addEventListener('click', function() {
buttonOptions[i].classList.add("active");
});
}
but I don't know how should I remove those active class.
and also I wanna know there is a way to avoid using for specifically for removing class?
var buttons = document.getElementsByClassName("btn");
function removeAllActive() {
[].forEach.call(buttons, function(el) {
el.classList.remove("active");
});
}
removeAllActive();
[].forEach.call(buttons, function(el) {
el.addEventListener("click", function() {
removeAllActive();
el.classList.add("active");
});
});
.active {
background-color: red;
}
<button class="active btn">btn1</button>
<button class="active btn">btn2</button>
<button class="active btn">btn3</button>
<button class="active btn">btn4</button>
You could avoid using a for loop, but you'd still have to iterate, so there's really no point. I'll use forEach as it's supported on querySelector and looks a little cleaner, but a for loop is fine as well
Same goes for binding the event handler, you have to iterate and target each element
let buttonOptions = document.querySelectorAll(".btn");
buttonOptions.forEach( el =>
el.addEventListener('click', function() {
buttonOptions.forEach( els => els.classList.remove('active') )
this.classList.add("active");
})
)
.active {color : red}
<button class="active btn">btn1</button>
<button class="btn">btn2</button>
<button class="btn">btn3</button>
<button class="btn">btn4</button>
document.getElementById('buttons').addEventListener('click', function(evt) {
if (evt.target.classList.contains('btn')) {
Array.from(document.querySelectorAll('.btn', this)).forEach(x => {
x.classList.toggle('active', x == evt.target)
});
}
});
.active {
color: red;
}
<div id="buttons">
<button class="active btn">btn1</button>
<button class="btn">btn2</button>
<button class="btn">btn3</button>
<button class="btn">btn4</button>
</div>
Attaching a listener to each button is wasteful. I attach a listener to a containing element, then wait for the event to bubble up to it. If the click originated from one of the btn-classed elements, then I find all the btn-classed elements within it and switch their active class based on whether they are the clicked button or not.
Here is the easiest way to resolve the mentioned issue,
$(function){
$(document).on("click",".btn",function(){
$(".btn").removeClass("active");
$(this).addClass("active");
});
});
If you are allowed to use jquery, it will be much easier for you. Please have a look on the below code,it may help you
<script>
$( document ).ready(function() {
$('.btn').removeClass('active');
$('.btn').click(function(e) {
$('.btn').removeClass('active');
$(this).addClass('active');
});
});
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<button class="active btn">btn1</button>
<button class="active btn">btn2</button>
<button class="active btn">btn3</button>
<button class="active btn">btn4</button>
Try this one:
$(document).on("click",".btn",function(){
$(".btn").removeClass("active");
$(this).addClass("active");
});