Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript Callback Functions in JavaScript Callbacks and the DOM Callbacks with DOM Elements

codingchewie
codingchewie
8,764 Points

Can D.R.Y be implemented further on the callback?

I get the answer to the code challenge when asked how to add the event listener to every button with:

btn1.addEventListener ('click',spinElement);
btn2.addEventListener ('click', spinElement);
btn3.addEventListener ('click', spinElement);

but when I look at this I wonder if I can use a D.R.Y approach or rewrite it. Is there a way I could or should consolidate it further like:

buttonListener(btn1);
buttonListener(btn2);
buttonListener(btn3);

then with something like:

buttonListener(theButton => theButton.addEventListener ('click',spinElement));

Is this possible or unnecessary?

app.js
const btn1 = document.getElementById("button1");
const btn2 = document.getElementById("button2");
const btn3 = document.getElementById("button3");

function spinElement(event) {
  //Applies spinning animation to button element
  event.target.className = "spin";
}

btn1.addEventListener ('click',spinElement);
btn2.addEventListener ('click', spinElement);
btn3.addEventListener ('click', spinElement);
index.html
<!DOCTYPE html>
<html lang="en">
    <head>
        <title></title>
        <link rel='stylesheet' href='styles.css'>
    </head>
    <body>
        <section >
            <button id='button1'>Button 1</button>
            <button id='button2'>Button 2</button>
            <button id='button3'>Button 3</button>
        </section>
        <script src='app.js'></script>
    </body>
</html>
Julian French
Julian French
3,257 Points

You could use event delegation. You add the event listener to the parent event, and then use an if/else statement to make sure that the click function of the statement only applies to what you want exactly. For example:

<div id="parent">
   <input>
   <button id="btn1" class="test-button">Test</button>
   <button id="btn2" class="test-button">Test</button>
   <button id="btn3" class="test-button">Test</button>
</div>
var div = document.getElementById('parent');
div.addEventListener('click', function(event) {
   if (event.target.classList.contains('test-button') {
      spinElement(event);
      // I would also use event.target.classList.add('spin'); inside of your spinElement function
   }
});

Event delegation ---> https://javascript.info/event-delegation

1 Answer

Michel Ribbens
Michel Ribbens
18,417 Points

I was wondering the same. since these are all buttons, I thought it might be an idea to use a loop like this:

const btn1 = document.getElementById("button1");
const btn2 = document.getElementById("button2");
const btn3 = document.getElementById("button3");

const buttons = document.querySelectorAll('button');

function spinElement(event) {
  //Applies spinning animation to button element
  event.target.className = "spin";
}

buttons.forEach( button => {
  button.addEventListener('click', spinElement);
});

it works, but only once on every button... don't understand why. can anybody maybe explain to me why?