ak85
ak85

Reputation: 4264

choose up to x number of items from a list in javascript

I have a list of items where I want the user to be able to select up to three items. I have the below code.

var listItems = document.querySelectorAll('li');
var clickcnt = 0;
for(var i = 0; i < listItems.length; i++){
    listItems[i].addEventListener('click', function(event) {
      if(this.hasAttribute('class')){
        var test = document.getElementsByClassName('clicked');
        this.classList.remove('clicked');
        clickcnt--;
      }
      else if(clickcnt < 3) {
      this.classList.add('clicked');
      clickcnt++;
      }
console.log(clickcnt);
    });
}
    .clicked {
      background-color:red;
    }
<p>select up to 3 of your favourite items below.</p>
<ul id="mylist">
  <li>item 1</li>
  <li>item 2</li>
  <li>item 3</li>
  <li>item 4</li>
  <li>item 5</li>
</ul>

The issue I am having is that I am checking to see if the item has a class if so I am reducing the click count. But it keeps subtracting the items so if I for example click on item 1 4 times in a row I am then able to select the other four.

How can I set this up so the user can keep clicking on an item until they have a max of 3 selected but if they click on the same one twice it removes the item so that it is at its intial state?

Upvotes: 0

Views: 211

Answers (4)

RichieAHB
RichieAHB

Reputation: 2088

You can use clickcnt = Math.max(clickcnt - 1, 0); - this picks the maximum value of the two values. If clickcnt - 1 is below 0 it just returns 0 instead. See MDN reference.

Your checking whether there is a class or not will fail though after adding one class and remove it, as it doesn't remove the attribute, just the class. If you're using classList then you can use this.classList.contains('clicked').

See this fiddle.

var listItems = document.querySelectorAll('li');
var clickcnt = 0;
for (var i = 0; i < listItems.length; i++) {
    listItems[i].addEventListener('click', function (event) {
        if (this.classList.contains('clicked')) {
            this.classList.remove('clicked');
            clickcnt = Math.max(clickcnt - 1, 0);
        } else if (clickcnt < 3) {
            this.classList.add('clicked');
            clickcnt++;
        }
    });
}

To clean up a bit you can just use one if and the toggle method from the classList object. See this fiddle:

var listItems = document.querySelectorAll('li');
for (var i = 0; i < listItems.length; i++) {
   listItems[i].addEventListener('click', clicked);
}

function clicked() {
    var clickCount = document.getElementsByClassName('clicked').length;
    var el = this;
    if (clickCount >= 3) {
        this.classList.remove('clicked');
    } else {
        this.classList.toggle('clicked');
    }
}

To have a global variable that's you can refer to for the click count in other functions you can change the code to:

var listItems = document.querySelectorAll('li');
var clickCount = 0;

for (var i = 0; i < listItems.length; i++) {
   listItems[i].addEventListener('click', clicked);
}

function clicked() {
    var el = this;
    if (clickCount >= 3) {
        this.classList.remove('clicked');
    } else {
        this.classList.toggle('clicked');
    }
   clickCount = document.getElementsByClassName('clicked').length;
}

Upvotes: 1

user2575725
user2575725

Reputation:

var listItems = document.querySelectorAll('li');
var toggleClicked = function(event) {
  var _class = 'clicked';
  if (-1 < this.className.indexOf(_class)) {
    this.classList.remove(_class);
  } else if (3 > document.getElementsByClassName(_class).length) {
    this.classList.add(_class);
  } else {
    console.warn('Oops !');
  }
  console.log('No. elements:', document.getElementsByClassName(_class).length, 'with class:', _class);
};
for (var i = 0; i < listItems.length; i++) {
  listItems[i].addEventListener('click', toggleClicked);
}
.clicked {
  background-color: red;
}
<p>select up to 3 of your favourite items below.</p>
<ul id="mylist">
  <li>item 1</li>
  <li>item 2</li>
  <li>item 3</li>
  <li>item 4</li>
  <li>item 5</li>
</ul>

Upvotes: 3

Lesha Ogonkov
Lesha Ogonkov

Reputation: 1238

Like that?

var listItems = document.querySelectorAll('li');
var clickcnt = 0;
var myList = document.querySelector('#mylist');

myList.addEventListener('click', function(event) {
  var itemClassList, selected, canAdd;
  
  itemClassList = event.target.classList;
  canAdd = clickcnt < 3;
  
  if (itemClassList.contains('clicked')) {
    itemClassList.remove('clicked');
    clickcnt -= 1;
  } else if (canAdd) {
    itemClassList.add('clicked');
    clickcnt += 1;
  }

});
.clicked {
      background-color:red;
    }
<p>select up to 3 of your favourite items below.</p>
<ul id="mylist">
  <li>item 1</li>
  <li>item 2</li>
  <li>item 3</li>
  <li>item 4</li>
  <li>item 5</li>
</ul>

Upvotes: 1

Sumeet Patil
Sumeet Patil

Reputation: 432

Try this - > http://jsfiddle.net/sumeetp1991/nybf6kk6/

var listItems = document.querySelectorAll('li');
var clickcnt = 0;
for(var i = 0; i < listItems.length; i++){
     listItems[i].addEventListener('click', function(event) {
      if(this.className){
        this.className = "";
        clickcnt--;
      }
      else if(clickcnt < 3) {
      this.className = "clicked";
      clickcnt++;
      }
    console.log(clickcnt);
    });

}

Upvotes: 1

Related Questions