0

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!

  • I don't understand the question, it looks like you just know and did what you want to do – Marco Salerno Jul 10 '17 at 13:14
  • Well i have tried to write some similar code to my page, but it does not work... –  Jul 10 '17 at 13:15
  • @LukasMittunAlexanderGuldstv show the code you tried :) – treyBake Jul 10 '17 at 13:16
  • document.getElementByClassName("settings-opslag").addEventListener("click",function(){ document.getElementByClassName("settings-opslag").style.background = "red"; });
    –  Jul 10 '17 at 13:17
  • 1
    Read the answers to this question, I think the problem is likely to be related: https://stackoverflow.com/questions/34896106/attach-event-to-dynamic-elements-in-javascript; that and the fact you have a typo in `getElementsByClassName()` (missing the 's' from 'Elements'), and the fact that a NodeList doesn't have an `addEventListener()` method. – David Thomas Jul 10 '17 at 13:17

5 Answers5

2

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.

kind user
  • 40,029
  • 7
  • 67
  • 77
  • When i use this code i get this error in my browser: unexpected token '>' –  Jul 10 '17 at 17:40
1

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>
trincot
  • 317,000
  • 35
  • 244
  • 286
1

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:

Bibliography:

David Thomas
  • 249,100
  • 51
  • 377
  • 410
  • First of all your answer answers topics which OP didn't ask for, secondly - wouldn't be it better to just share some link to official docs? :P – kind user Jul 10 '17 at 14:22
  • From my understanding of the question, as written at the time I read it (I haven't checked the edit history, so I'm unsure as to how it may have changed since) I answered the question posted by the OP, that of "*how can I add [functionality to dynamically added elements]?*" The other portions of my answer are intended to address the reasons why the shown JavaScript wasn't working, and couldn't work. As for sharing links to the documentation, without context what good would that do anyone, now or in future? If you feel I haven't usefully answered the question then you can, of course, down-vote. – David Thomas Jul 10 '17 at 14:27
  • I didn't say that your answer is not useful, it's just too broad imo. But I respect your dedication. Cheers – kind user Jul 10 '17 at 14:28
0

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");
   });
});
Yash
  • 3,438
  • 2
  • 17
  • 33
0

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.

NorS
  • 168
  • 3
  • 14