JavaScript click event listener on class
This should work. getElementsByClassName
returns an Array-like object (see below) of the elements matching the criteria.
var elements = document.getElementsByClassName("classname");
var myFunction = function() {
var attribute = this.getAttribute("data-myattribute");
alert(attribute);
};
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', myFunction, false);
}
jQuery does the looping part for you, which you need to do in plain JavaScript.
If you have ES6 support you can replace your last line with:
Array.from(elements).forEach(function(element) {
element.addEventListener('click', myFunction);
});
Note: Older browsers (like IE6, IE7, IE8) don´t support getElementsByClassName
and so they return undefined
.
Details on getElementsByClassName
getElementsByClassName
doesn't return an array, but a HTMLCollection
in most, or a NodeList
in some browsers (Mozilla ref). Both of these types are Array-Like, (meaning that they have a length property and the objects can be accessed via their index), but are not strictly an Array or inherited from an Array (meaning other methods that can be performed on an Array cannot be performed on these types).
Thanks to user @Nemo for pointing this out and having me dig in to fully understand.
Adding click event listener to elements with the same class
You should use querySelectorAll
. It returns NodeList, however querySelector
returns only the first found element:
var deleteLink = document.querySelectorAll('.delete');
Then you would loop:
for (var i = 0; i < deleteLink.length; i++) {
deleteLink[i].addEventListener('click', function(event) {
if (!confirm("sure u want to delete " + this.title)) {
event.preventDefault();
}
});
}
Also you should preventDefault only if confirm === false
.
It's also worth noting that return false/true
is only useful for event handlers bound with onclick = function() {...}
. For addEventListening
you should use event.preventDefault()
.
Demo: http://jsfiddle.net/Rc7jL/3/
ES6 version
You can make it a little cleaner (and safer closure-in-loop wise) by using Array.prototype.forEach iteration instead of for-loop:
var deleteLinks = document.querySelectorAll('.delete');
Array.from(deleteLinks).forEach(link => {
link.addEventListener('click', function(event) {
if (!confirm(`sure u want to delete ${this.title}`)) {
event.preventDefault();
}
});
});
Example above uses Array.from and template strings from ES2015 standard.
Event listener on multiple elements with the same class
Is it possible that JavaScript detects only one (first in HTML code) .close div?
Yes, document.querySelector
returns the first matching element it finds in the DOM. If you want to add your listeners to every .close
on the page, either loop through the NodeList returned by document.querySelectorAll
:
const closeList = document.querySelectorAll('.close');
closeList.forEach(element => {
element.addEventListener('click', () => closeSlide('about'));
element.addEventListener('click', () => closeSlide('work'));
element.addEventListener('click', () => closeSlide('contact'));
};
or add a listener to an element containing all of your .close
elements that only takes action if a .close
was clicked:
document.querySelector('#some-container').addEventListener('click', evt => {
if (!evt.target.closest('.close')) return;
closeSlide('about');
closeSlide('work');
closeSlide('contact');
});
add event listener to multiple divs with same class in a container
Look at your logic.
- Select an element
- Find all the .grid-item elements
- Define a function that creates grid-item
- Call the function that creates grid-item
So with that logic, you are clearly not going to find any elements. You need to create the grid-item elements before you select them. You also are not adding the class to the element correctly
So changing the order:
function myFunc() {
console.log("hello", this);
}
const container = document.querySelector(".container");
makeGrid(16, 16);
const gridItem = document.querySelectorAll(".grid-item").forEach(gridItem => gridItem.addEventListener("click", myFunc));
function makeGrid(rows, cols) {
container.style.setProperty("--grid-rows", rows);
container.style.setProperty("--grid-cols", cols);
for (let i = 0; i < (rows * cols); i++) {
const gridItem = document.createElement("div");
gridItem.classList.add("grid-item");
gridItem.textContent = i + 1;
container.appendChild(gridItem)
}
}
.container {
--grid-cols: 2;
display: grid;
grid-template-columns: repeat(var(--grid-cols), 1fr);
gap: .1em;
}
.grid-item {
border: 1px solid #CCC;
padding: .2em;
text-align: center;
}
<div class="container"></div>
Binding an event listener to multiple elements with the same class
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>
How to apply an eventListener to multiple elements with the same class and have each element respond independently
In the first version you are executing the pickSelection
function instead of passing its reference, the addEventListener
expects a function reference as a callback when the particular event is triggered.
But since you passed return value of the pickSelection
function which is undefined
(as you are not returning anything from the pickSelection
so by default it is returning undefined
) it is not working.
In the second version you are actually passing the function reference to the addEventListner
, which being a arrow function syntax.
This following would also work, by simply passing the reference pickSelection
, but this time it will receive the event
object.
const selection = document.querySelectorAll(".zone");selection.forEach(element => { element.addEventListener('click', pickSelection)})function pickSelection(event) { //getting the event object from the callback, target refers to the current element clicked. console.log(event.target.textContent)}
<div class='container'> <div class="zone green">lt;/div> <div class="zone red">lt;/div> <div class="zone blue">lt;/div> <div class="zone yellow">lt;/div> <div class="zone purple">lt;/div> <div class="zone brown">lt;/div> <div class="zone green">lt;/div> <div class="zone red">lt;/div> <div class="zone blue">lt;/div> <div class="zone yellow">lt;/div> <div class="zone purple">lt;/div> <div class="zone brown">lt;/div></div>
How to make click event work for multiple elements with the same class?
Consider this Codepen for a pure javascript solution.
<p class="target">flip me</p>
<p class="target">flip me</p>
<p class="target">flip me</p>
.flipped {
color: red;
}
const targets = document.getElementsByClassName('target');
for (var i = 0; i < targets.length; i++) {
targets[i].addEventListener('click', function(){
this.classList.toggle("flipped");
})
}
Or consider this for a jQuery solution.
<p class="target">flip me</p>
<p class="target">flip me</p>
<p class="target">flip me</p>
.flipped {
color: red;
}
$('.target').on('click', function() {
$(this).toggleClass('flipped');
});
EDIT:
After looking at your given code I just realized that you position absolute divs via very large paddings which is not the correct way to do. Rather use top|right|bottom|left
for positioning (see here for docs). After changing the css your example works fully even with the messy javascript. Look here
Related Topics
How to Get the Scrollbar Position with JavaScript
JavaScript % (Modulo) Gives a Negative Result for Negative Numbers
Jquery How to Bind Onclick Event to Dynamically Added HTML Element
Get the Element with the Highest Occurrence in an Array
How to Perform a Dns Lookup (Hostname to Ip Address) Using Client-Side JavaScript
Defining a JavaScript Prototype
Jquery's Jquery-1.10.2.Min.Map Is Triggering a 404 (Not Found)
Working with Select Using Angularjs's Ng-Options
How to Access the First Property of a JavaScript Object
How to Format Time Since Xxx E.G. "4 Minutes Ago" Similar to Stack Exchange Sites
Prevent Double Submission of Forms in Jquery
How to Cancel an Http Fetch() Request
What Is the Meaning of "$" Sign in JavaScript
Empty Arrays Seem to Equal True and False at the Same Time
Jquery Click/Toggle Between Two Functions
How to Synchronize a Sequence of Promises
How to Check for an Undefined or Null Variable in JavaScript