Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

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

codingchewie
codingchewie
8,763 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?