Reputation:
I am working on a website where content is added dynamically. I want to have the same class at each div. when you onclick this div the class is called in a javascript script where a function will run.
How shall i do this?
example:
<div class="thisclass">
HTML
</div>
<div class="thisclass">
HTML
</div>
<div class="thisclass">
HTML
</div>
<script>
document.getElementByClassName("thisclass").addEventListener("click",function(){
//do something with the specific clicked div
});
</script>
My code from my own page:
<div class="settings-opslag">
<p>‹</p>
</div>
<script>
document.getElementByClassName("settings-opslag").addEventListener("click",function(){
document.getElementByClassName("settings-opslag").style.background = "red";
});
</script>
Thanks!
Upvotes: 0
Views: 219
Reputation: 41893
You can't apply an event listener on array-like object, which getElementsByClassName
function returns. Listeners have to be applied on single elements. Iterate over it and bind it.
Array.from(document.getElementsByClassName('thisclass')).forEach(v =>
v.addEventListener('click', () => {
// do something
})
)
You can try without arrow functions and ES6 features:
const elems = document.getElementsByClassName('thisclass');
for (var i = 0; i < elems.length; i++) {
elems[i].addEventListener('click', function() {
// do something
})
}
Array#from function is used to change array-like object into an array.
Upvotes: 2
Reputation: 253318
You have a number of problems; so we'll start looking at the basics from the JavaScript you posted:
document.getElementByClassName("thisclass")
// ^- typo, the function is: getElementsByClassName
// (note the additional 's')
.addEventListener("click",function(){
// a NodeList - returned by the getElementsByCLassName()
// function has no addEventListener() method, so instead
// you have to iterate over all elements in the NodeList
// and apply the event-listener to each element individually.
//do something with the specific clicked div
});
So the above would be correctly written as:
Array.from(document.getElementsByClassName('thisclass')).forEach(
currentNode => currentNode.addEventListener('click', function(){
// do whatever
});
Or slightly more succinctly:
document.querySelectorAll('.thisclass').forEach(
currentNode => currentNode.addEventListener('click', function(){
// do whatever
});
Which takes advantage of the NodeList returned by document.querySelectorAll()
having a forEach()
method, whereas the returned Live NodeList returned by document.getElementsByClassName()
does not.
The other part of the problem is that you seem to want to add the event-listeners to those elements that do not yet exist in the document.
Because JavaScript can't directly bind event-listeners to elements that are added to the document after the event-listeners are bound, we instead have to add the event-listener to an existing ancestor element on the page rather than directly to the elements themselves.
As a simple example, making use of an added <button>
element to add new elements:
// caching references to various elements for later use:
let button = document.querySelector('button'),
ancestor = document.body;
// named function to add new elements to the page;
// the first argument is the 'event' Object,
// passed automagically from the addEventListener()
// method:
function addNewElement(event) {
// because we're using the ancestor element of
// the <button> to listen for the same 'click'
// event, here we use event.stopPropagation()
// to avoid that click bubbling up through the
// document:
event.stopPropagation();
// we find the first element matching the supplied
// selector (or if no such element exists this
// will return null; so in production it's sensible
// to check the element exists):
let newElement = document.querySelector('.thisclass')
// and then we clone that Node:
.cloneNode(true);
// this is passed automagically from the
// addEventListener() method, and refers to
// the element on which the event-listener
// was fired; here we find the <button>
// element's parentNode and use the
// parentNode.appendChild() method to add
// the newly-created element to the document:
this.parentNode.appendChild(newElement);
// here we explicitly add a class to the
// dynamically added content, just to be
// explicit that it's a newly-added element:
newElement.classList.add('dynamicallyAdded');
}
// a simple named function to demonstrate
// simple functionality:
function handleThisclassClicks(event) {
// the event.target is the Node upon which
// the listened-for event was originally
// fired:
let target = event.target;
// here we simply toggle the 'active'
// class on the clicked element:
target.classList.toggle('active');
}
// binding the named ('addNewElement()') function
// as the event-handler for the click event on
// the button Node (note the deliberate lack of
// parentheses):
button.addEventListener('click', addNewElement);
// binding the named function as the event-handler for
// the click event fired on the ancestor Node (which is,
// again, why we used event.stopPropagation() in the
// button Node's click-handler):
ancestor.addEventListener('click', handleThisclassClicks);
let button = document.querySelector('button'),
ancestor = document.body;
function addNewElement(event) {
event.stopPropagation();
let newElement = document.querySelector('.thisclass')
.cloneNode(true);
this.parentNode.appendChild(newElement);
newElement.classList.add('dynamicallyAdded');
}
function handleThisclassClicks(event) {
let target = event.target;
target.classList.toggle('active');
}
button.addEventListener('click', addNewElement);
ancestor.addEventListener('click', handleThisclassClicks);
div {
color: red;
margin-left: 0;
transition: color 0.5s linear, margin-left 1s linear;
}
div.active {
color: limegreen;
margin-left: 1em;
}
.dynamicallyAdded::after {
content: '*';
}
<button>Add another '.thisclass' element</button>
<div class="thisclass">
HTML
</div>
<div class="thisclass">
HTML
</div>
<div class="thisclass">
HTML
</div>
References:
Array.from()
.Array.forEach()
.document.getElementsByClassName()
.document.querySelector()
.document.querySelectorAll()
.Element.classList
API.Event.stopPropagation()
.Event.target
.EventTarget.addEventListener()
.Node.parentNode
.NodeList.forEach()
.Bibliography:
Upvotes: 1
Reputation: 158
An alternative to your planned implementation would be to add an onclick-attribute on each div and then track what div was clicked in the function called onclick. The code would look something like this:
<div class="thisclass" onclick="yourJavascriptFunction(this)">
HTML
</div>
The this you send as a parameter to your javascript function will be the DOM-element which can then be modified.
Upvotes: 0
Reputation: 3576
I'd be nice if you use jQuery and loop through all the divs and add an event listener to them. Example:
$(".thisclass").each(function(){
$(this).on("click",function(){
//here use the "this" reference to manipulate the clicked div
//Like
$(this).addClass("newclass");
});
});
Upvotes: 0
Reputation: 350280
There is a spelling mistake in getElementsByClassName
(it needs the s
), and you need to iterate over the nodelist that you get from it. Inside the event handler you can reference the clicked element with this
:
for (let elem of document.getElementsByClassName("thisclass")) {
elem.addEventListener("click", function () {
this.style.background = "red";
});
}
<div class="thisclass">HTML1</div>
<div class="thisclass">HTML2</div>
<div class="thisclass">HTML3</div>
Upvotes: 1