Setting threshold for maximum number of selected / activated classes when clicking multiple div / ids

I was working on a skill tree and I had an interesting problem.

I have my code setting allowing the user to click a talent to show that a specific talent is selected up to a maximum of 4 talents. After you have selected 4 talents, you need to deselect the talent to select another.

My problem comes up when I duplicate the talent tree for a second talent tree on the same page (for a second hero / class per essence or a second member from your side). I can't figure out how to do the same "max 4 talent threshold" on other skill trees separately. It happens that they all have the same threshold for all trees. I tried to make each separate identifier and even change the variable names in each function.

var skillTotal = 0;
var skillSelected = 0;

$( "#selectable01>li.skill-slot" ).bind( "click", function ( e ) {
				var threshold = 4;
        var price = 1;
        if ($(this).hasClass('selected')) {
                skillTotal = skillTotal - 1;
                skillSelected--;
                $(this).toggleClass('selected');
        }
        else if (price + skillTotal <= threshold) {
                skillTotal = skillTotal + price;
                skillSelected++;
                $(this).toggleClass('selected');
        }
});

$( "#selectable02>li.skill-slot" ).bind( "click", function ( e ) {
				var threshold = 4;
        var price = 1;
        if ($(this).hasClass('selected')) {
                skillTotal = skillTotal - 1;
                skillSelected--;
                $(this).toggleClass('selected');
        }
        else if (price + skillTotal <= threshold) {
                skillTotal = skillTotal + price;
                skillSelected++;
                $(this).toggleClass('selected');
        }
});

/* NOT USING THIS CURRENTLY 
$( "#campSelectable>li.camp-slot" ).bind( "click", function ( e ) {
				var campThreshold = 3;
        var campPrice = 1;
        if ($(this).hasClass('selected')) {
                campTotal = campTotal - campPrice;
                selectedCamp--;
                $(this).toggleClass('selected');
        }
        else if (campPrice + campTotal <= campThreshold) {
                campTotal = campTotal + campPrice;
                selectedCamp++;
                $(this).toggleClass('selected');
        }
}); */
      

.skill-slot, .camp-slot{
  border:2px solid black;
  width:100px;
  margin: 5px;
  opacity: .4;
}

.skill-slot:hover, .camp-slot:hover {
  opacity: 1;
}

.raffle-slot.taken{
  background:red;
}
.selected{
  background: rgb(255, 128, 128);
  opacity: 1;
}
      

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="calc">
<ol class="roster" id="selectable01">
<li class="skill-slot">1</li>
<li class="skill-slot">2</li>
<li class="skill-slot">3</li>
<li class="skill-slot">4</li>
<li class="skill-slot">5</li>
<li class="skill-slot">6</li>
<li class="skill-slot">7</li>
</ol>

<ol class="roster" id="selectable02">
<li class="skill-slot">1</li>
<li class="skill-slot">2</li>
<li class="skill-slot">3</li>
<li class="skill-slot">4</li>
<li class="skill-slot">5</li>
<li class="skill-slot">6</li>
<li class="skill-slot">7</li>
</ol>

</div>
      

Run code


Here's what I tried: Initially my ID was: $( "#calc>ol>li.skill-slot" ).on

so I started adding an additional ID to expand further and make sure my functions were targeting specific divs, so I went to this: $( "#calc>#selectable01>li.skill-slot" ).on

and$( "#calc>#selectable02>li.skill-slot" ).on

The reason I don't want to customize the second id is because I will be using templates added to the #calc div, effectively replacing the current list with the new one. I also did this for testing to see if I could fix the problem by making them my own custom IDs which didn't work.

+3


source to share


3 answers


The simplest approach is using event delegation. Switch .selected

to deactivate the current one .skill-slot

or activate it if this group has less than 4 .selected.skill-slot

.



$('#selectable01, #selectable02').on('click', '.skill-slot', function(e){
  if($(this).hasClass('selected') || $('.selected.skill-slot', e.delegateTarget).length < 4){
    $(this).toggleClass('selected');
  }
});
      

.skill-slot, .camp-slot{
  border:2px solid black;
  width:100px;
  margin: 5px;
  opacity: .4;
}

.skill-slot:hover, .camp-slot:hover {
  opacity: 1;
}

.raffle-slot.taken{
  background:red;
}
.selected{
  background: rgb(255, 128, 128);
  opacity: 1;
}
      

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="calc">
<ol class="roster" id="selectable01">
<li class="skill-slot">1</li>
<li class="skill-slot">2</li>
<li class="skill-slot">3</li>
<li class="skill-slot">4</li>
<li class="skill-slot">5</li>
<li class="skill-slot">6</li>
<li class="skill-slot">7</li>
</ol>

<ol class="roster" id="selectable02">
<li class="skill-slot">1</li>
<li class="skill-slot">2</li>
<li class="skill-slot">3</li>
<li class="skill-slot">4</li>
<li class="skill-slot">5</li>
<li class="skill-slot">6</li>
<li class="skill-slot">7</li>
</ol>

</div>
      

Run code


+2


source


Since you are using globals for count and total, this obviously leads to a global limit. To make the constraint local to each of the groups, you can use the data attributes of these elements ol

, so they work independently of each other. With some other small improvements, your code might look like this:



$("#selectable01, #selectable02").data("skillTotal", 0).data("skillSelected", 0);

$("#selectable01>li.skill-slot,#selectable02>li.skill-slot").on("click", function () {
    var threshold = 4, 
        price = 1,
        sign = $(this).hasClass('selected') ? -1: 1,
        $p = $(this).parent(),
        newPrice = $p.data("skillTotal") + sign*price;
    if (newPrice > threshold) return; 
    $p.data("skillTotal", newPrice)
      .data("skillSelected", $p.data("skillSelected") + sign);
    $(this).toggleClass('selected');
});
      

.skill-slot, .camp-slot{
  border:2px solid black;
  width:100px;
  margin: 5px;
  opacity: .4;
}

.skill-slot:hover, .camp-slot:hover {
  opacity: 1;
}

.raffle-slot.taken{
  background:red;
}
.selected{
  background: rgb(255, 128, 128);
  opacity: 1;
}
      

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="calc">
<ol class="roster" id="selectable01">
<li class="skill-slot">1</li>
<li class="skill-slot">2</li>
<li class="skill-slot">3</li>
<li class="skill-slot">4</li>
<li class="skill-slot">5</li>
<li class="skill-slot">6</li>
<li class="skill-slot">7</li>
</ol>

<ol class="roster" id="selectable02">
<li class="skill-slot">1</li>
<li class="skill-slot">2</li>
<li class="skill-slot">3</li>
<li class="skill-slot">4</li>
<li class="skill-slot">5</li>
<li class="skill-slot">6</li>
<li class="skill-slot">7</li>
</ol>

</div>
      

Run code


+2


source


You keep skillSelected

outside of the event handlers so that each event handler reads this variable. You may want to get the total of all selected each time an event handler is fired.

+1


source







All Articles