user4906653
user4906653

Reputation:

Javascript function to class divs?

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

Answers (5)

kind user
kind user

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

David Thomas
David Thomas

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:

Bibliography:

Upvotes: 1

NorS
NorS

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

Yash
Yash

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

trincot
trincot

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

Related Questions