Adding Click Event Listener to Elements with the Same Class

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.

  1. Select an element
  2. Find all the .grid-item elements
  3. Define a function that creates grid-item
  4. 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



Leave a reply



Submit