Как написать JS скрипт, присваивающий классы после нескольких кликов?

Есть html код, примерно такой:

<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>

Нужно сделать, что бы при клике по элементу box присваивался дополнительный класс opened, а по третьему клику присваивался класс bonus, и после этого скрипт заканчивал работу, после 3-го клика классы больше не присваиваются. Так же, элементу с классом opened не может быть присвоен класс bonus, т.е. классы присваиваются элементу только один раз. Помогите пожалуйста реализовать!


Ответы (4 шт):

Автор решения: highpassion

let items = document.querySelectorAll('.container .box'),
i = 0;
items.forEach((item) => {

   item.addEventListener('click', (event) => {
        i++;
        if (i < 3) event.target.classList.add('opened');
        else if (i == 3 && !(event.target.classList.contains('opened'))) {
          event.target.classList.add('bonus');
        }
   });
});
.box {
  background: red;
  box-sizing: border-box;
  padding: 42px;
  width: 100px;
  height: 100px;
  text-align: center;
  margin-bottom: 10px;
}

.opened {
  background: green;
}

.bonus {
  background: orange;
}
<div class="container">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
</div>

→ Ссылка
Автор решения: Dmitrii Sedov

ну, если я правильно всё понял. Надо что-то типо такого:

UPD дополнил ответ

const boxes = document.getElementsByClassName('box');
let countClick = 0;
[...boxes].map(box => {
  box.addEventListener('click', function(e) {
    if (countClick === 3 || this.classList.contains('opened')) return;
    this.classList.add(countClick === 2 ? 'bonus' : 'opened');
    countClick++;
  });
})
.opened {
  background: red;
}

.bonus {
  background: blue;
}
<div class="container">
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
</div>

→ Ссылка
Автор решения: UModeL

Как вариант, использовать делегирование, без лишних циклов:

document.querySelector('.container').addEventListener('click', function(ev) {
  let classes = ev.target.classList;
  if (this.querySelector('.bonus') || !classes.contains('box') || classes.contains('open')) return;
  classes.add(((this.querySelectorAll('.open').length < 2) ? 'open' : 'bonus'));
});
.box { border: 1px dashed #080; }
.open { background-color: #fa0; }
.bonus { background-color: #f00;}
<div class="container">
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
</div>

→ Ссылка
Автор решения: Pavel Nazarian

const bonus = function(e){
   const t = e.target;
   if (t.classList.contains('box')) {
     if (this.querySelectorAll('.box.opened').length == 2){
       t.className = 'box bonus';
       this.removeEventListener('click',bonus);
     } else t.className = 'box opened';
   }
}
document.querySelector('.container').addEventListener('click',bonus)
.box {
  border: 1px solid black;
  margin: 10px;
  height: 30px;
  width: 30px;
}
.opened {
  background: green;
  pointer-events: none;
}

.bonus {
  background: purple;
  pointer-events: none;
}
<div class="container">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>

→ Ссылка