С какими элементами имеем дело, какие классы будем им переключать, как ограничено количество одновременно активных:
const itemSelector = '.product';
const activeClass = 'checked';
const disabledClass = 'unchecked';
const activeLimit = 3;
Делегирование, обработчик клика назначаем один раз для всех элементов:
document.addEventListener('click', e => {
const cl = e.target.closest(itemSelector)?.classList;
if (cl && !cl.contains(disabledClass)) {
cl.toggle(activeClass);
updateDisabled();
}
});
updateDisabled();
function updateDisabled() {
const [ notActive, active ] = Array.prototype.reduce.call(
document.querySelectorAll(itemSelector),
(acc, n) => (acc[+n.classList.contains(activeClass)].push(n), acc),
[ [], [] ]
);
const limitReached = activeLimit <= active.length;
notActive.forEach(n => n.classList.toggle(disabledClass, limitReached));
}
Или, назначаем обработчик клика каждому элементу индивидуально:
const items = [...document.querySelectorAll(itemSelector)];
let activeCount = 0;
items.forEach(n => n.addEventListener('click', onClick));
updateDisabled(items.filter(n => n.classList.contains(activeClass)).length);
function onClick({ currentTarget: { classList: cl } }) {
if (!cl.contains(disabledClass)) {
updateDisabled(cl.toggle(activeClass) ? 1 : -1);
}
}
function updateDisabled(change) {
const limitReached = (activeCount += change) >= activeLimit;
for (const { classList: cl } of items) {
cl.toggle(disabledClass, !cl.contains(activeClass) && limitReached);
}
}