0

I understand how to implement a single click counter. However, I am struggling to figure out how to implement a button that will duplicate the click counter, while also allowing me to use the same javascript code.

My current layout for a single click counter has a div for the counter then a button for incrementing and another for decrementing. For the buttons, I am using a separate event listener for each one.

<div id="counter">0</div>
<button id="increment">+1</button>
<button id="decrement">-1</button>

Javascript:

var incr = document.getElementById('increment');
var decr = document.getElementById('decrement');
incr.addEventListener('click', ...);
decr.addEventListener('click', ...);

How would I implement another button that would copy the counter? Also, how do I approach the javascript side? My current approach does not seem to generalize well for multiple counters.

1 Answers1

0

To generate a new div you will need to create it and append it to the DOM. Something like:

const myDiv = document.createElement('div');
myDiv.id = 'id-blabla';
document.body.appendChild(div);

You can wrap that in the click handler.

Now, if you want to update several counters at the same time on a single button click, you will need to use another selector, instead of the id. Use a class or similar, like: <div class="counter"></div>, and then in the click handler get all those elements and iterate over them updating the counter value. Does that make sense to you?

(Also, this link I think it will be very helpful for you, in terms of iterating over DOM elements and other concepts).

EDIT: This other answer on DOM manipulation is going to be very useful too!


EDIT2: I understand now that what you want is to be able to generate counters (with the div and the buttons), that will have their click handlers and everything set it up correctly. You can use different approaches here, but the main purpose is to not repeat yourself:

  • You need your buttons to be able to identify the counter div target. You can achieve this using a custom data attribute in your buttons, like: <button class="increase" data-counterId="counter1"></button>. This way you would only need to write the click handler once (on all elements with "increase" or "decrease" class, and in the code extract the counterId data attribute so you would be able to edit the correct div counter.
  • You can achieve the same having some sort of common part in the id's of each block of HTML elements, like counter-1, increase-1 and decrease-1. Then each button would know which index it has, and which index the counter target should have.
  • This definitely looks like a component you could wrap in a Counter class. I don't know how familiar you are with JS UI frameworks, but depending on how complex your system is, you might want to think about using one. I recommend you to take a look to this link that explains React Components. Maybe it is out of scope of what you need, but I think it is worth to mention it.

I think with this information you have a good starting point to decide how you want to implement it, based on the size and complexity of what you want to build. I hope it helps!

elbecita
  • 2,616
  • 19
  • 28
  • I understand how to generate a new div, but how would I copy the buttons as well. I'm sorry I didn't make this clear in my previous comment. Using my current code setup, I would have to do something like incr2.addEventListener() if I named the new button incr2. However, this approach does not generalize if I want the button to create an arbitrary number of click counters. – boolean_ring Jan 15 '18 at 18:22
  • I see what you want to do now. Let me edit my answer. I see two approaches to do that in an "automated" way without repeating yourself. – elbecita Jan 15 '18 at 18:28
  • I edited my answer, I explained how you could do this. It all depends on how big and complex what you are building is. – elbecita Jan 15 '18 at 19:03
  • Thank you! I ended up turning the ids into classes and then iterating through each of the classes when adding the listeners. So, I basically used your first bullet point with an implicit counterId. – boolean_ring Jan 15 '18 at 23:04