3
\$\begingroup\$

I wrote this code for checking checkboxes. There are two groups of checkbox: each group's checkboxes have one common class all_perks and one individual class perks and perks_admin.

When any checkbox is clicked:

  • It will check for same amount checkbox in same group and check them, search for same amount of checkbox in other group and check them, if not found then it will look for nearest and lower amount possible and check all having same amount.
  • The amount is described as data-amount='10' and unique id is defined as data-id='1'.

$(document).ready(function() {

  $('.all_perks').click(function() {

    var clicked_perk_id = $(this).data('id');
    var clicked_perk_amount = $(this).data('amount');
    var type = ($(this).hasClass('perks')) ? 'camp' : 'admin';

    var perks = [];
    var perks_id = [];

    var admin_perks = [];
    var admin_perks_id = [];

    $('.perks').each(function() {
      perks.push($(this).data('amount'));
    });
    $('.perks_admin').each(function() {
      admin_perks.push($(this).data('amount'));
    });

    $('.perks').each(function() {
      perks_id.push($(this).data('id'));
    });
    $('.perks_admin').each(function() {
      admin_perks_id.push($(this).data('id'));
    });

    if ($(this).is(':checked')) {
      var checked = 0;
      $('.perks').each(function() {
        current_perk_id = $(this).data('id');
        current_perk_amount = $(this).data('amount');
        if (clicked_perk_amount == current_perk_amount) {
          $(this).attr('checked', true);
          if (type == 'admin') checked++;
        }
      });

      $('.perks_admin').each(function() {
        current_perk_id = $(this).data('id');
        current_perk_amount = $(this).data('amount');
        if (clicked_perk_amount == current_perk_amount) {
          $(this).attr('checked', true);
          if (type == 'camp') checked++;
        }

      });
      console.log(checked);
      if (checked == 0) {
        var _compare = [];
        var _compare_id = [];

        var selector = (type == 'admin') ? '.perks' : '.perks_admin';

        $(selector).each(function() {
          current_perk_id = $(this).data('id');
          current_perk_amount = $(this).data('amount');

          if (clicked_perk_amount > current_perk_amount) {
            _compare.push($(this).data('amount'));
            _compare_id.push($(this).data('id'));
          }


        });

        max_val_perk = Math.max.apply(Math, _compare);
        max_val_perk_id = _compare.indexOf(max_val_perk);
        max_val_perk_id = _compare_id[max_val_perk_id];

        $('[data-id="' + max_val_perk_id + '"]').attr('checked', true);

        $(selector).each(function() {

          current_perk_id = $(this).data('id');
          current_perk_amount = $(this).data('amount');

          if (max_val_perk == current_perk_amount) {
            $(this).attr('checked', true);
          }

        });
      }

      $('.all_perks').each(function() {
        $(this).attr('disabled', true);
      });
    }
  });

  $('#reset_form').click(function() {
    $('.all_perks').each(function() {
      $(this).attr('disabled', false);
      $(this).attr('checked', false);
    });
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<button id="reset_form">Reset</button>
<br>
<br>Group1:
<br>

<input name="perks[]" data-id="1" data-amount="5" type="checkbox" class="perks all_perks">$ 5
<br>

<input name="perks[]" data-id="2" data-amount="5" type="checkbox" class="perks all_perks">$ 5
<br>

<input name="perks[]" data-id="3" data-amount="10" type="checkbox" class="perks all_perks">$ 10
<br>

<input name="perks[]" data-id="4" data-amount="17" type="checkbox" class="perks all_perks">$ 17
<br>

<input name="perks[]" data-id="5" data-amount="25" type="checkbox" class="perks all_perks">$ 25
<br>

<input name="perks[]" data-id="6" data-amount="49" type="checkbox" class="perks all_perks">$ 49

<br>
<br>Group 2:
<br>
<input name="perks_admin[]" data-id="21" data-amount="10" type="checkbox" class="perks_admin all_perks">$ 10
<br>

<input name="perks_admin[]" data-id="22" data-amount="15" type="checkbox" class="perks_admin all_perks">$ 15
<br>

<input name="perks_admin[]" data-id="23" data-amount="15" type="checkbox" class="perks_admin all_perks">$ 15
<br>

<input name="perks_admin[]" data-id="24" data-amount="25" type="checkbox" class="perks_admin all_perks">$ 25
<br>

<input name="perks_admin[]" data-id="25" data-amount="50" type="checkbox" class="perks_admin all_perks">$ 50
<br>

<input name="perks_admin[]" data-id="26" data-amount="100" type="checkbox" class="perks_admin all_perks">$ 100
Can this be optimized?

\$\endgroup\$
  • \$\begingroup\$ Can you post a snippet or a link to a jsfiddle or jsbin so we can see an example in action? It would make it easier to understand the idea \$\endgroup\$ – Flambino Feb 18 '15 at 17:33
  • \$\begingroup\$ Here it is: JS Fiddle \$\endgroup\$ – Viral Feb 19 '15 at 7:51
2
\$\begingroup\$

It certainly seems like there's too much going on. If I understand correctly, clicking a checkbox does 2 things:

  1. Checks any other checkboxes in the same list, that have the same data-amount
  2. Checks any checkboxes in the other list that have the same amount, or the ones that are closest to that but below.

However this can be redefined as just one task:

  1. Within a given group of checkboxes, check those closest or equal to a given amount.

Here's a snippet, which uses that approach.

$(function () { // shorthand for $(document).ready()

  // get all checkboxes
  var allCheckboxes = $(".perk:checkbox");
  
  // group them by name for later
  var groups = {};
  allCheckboxes.each(function () {
    groups[this.name] || (groups[this.name] = []);
    groups[this.name].push(this);
  });
  
  // hook up event handling
  allCheckboxes.on("change", function (event) {
    // reset all checkboxes (easier than having to reset)
    allCheckboxes.each(function () { this.checked = false });
    
    // get the clicked checkbox and its amount
    var selected = $(this).prop("checked", true);
    var amount = selected.data("amount");
    
    // process each group of checkboxes
    for(var name in groups) {
      if(!groups.hasOwnProperty(name)) { continue }
      
      var group = $(groups[name]);
      
      // get those checkboxes in the group that have an equal or lower amount
      var matching = group.filter(function () {
        return $(this).data("amount") <= amount;
      });
      
      // get the maximum within that
      var amounts = matching.map(function () {
        return $(this).data("amount");
      }).get();
      
      var maxAmount = Math.max.apply(null, amounts);
      
      // now check those that have that amount
      group.filter("[data-amount='" + maxAmount + "']").prop("checked", true);
    }
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Group1:<br>
<input class="perk" name="perks[]" type="checkbox" data-amount="5">$ 5<br>
<input class="perk" name="perks[]" type="checkbox" data-amount="5">$ 5<br>
<input class="perk" name="perks[]" type="checkbox" data-amount="10">$ 10<br>
<input class="perk" name="perks[]" type="checkbox" data-amount="17">$ 17<br>
<input class="perk" name="perks[]" type="checkbox" data-amount="25">$ 25<br>
<input class="perk" name="perks[]" type="checkbox" data-amount="49">$ 49<br>
    
<br>
        
Group 2:<br>
<input class="perk" name="perks_admin[]" type="checkbox" data-amount="10">$ 10<br>
<input class="perk" name="perks_admin[]" type="checkbox" data-amount="15">$ 15<br>
<input class="perk" name="perks_admin[]" type="checkbox" data-amount="15">$ 15<br>
<input class="perk" name="perks_admin[]" type="checkbox" data-amount="25">$ 25<br>
<input class="perk" name="perks_admin[]" type="checkbox" data-amount="50">$ 50<br>
<input class="perk" name="perks_admin[]" type="checkbox" data-amount="100">$ 100<br>

I've simplified the HTML; since the name attributes already divide the checkboxes into different groups, there's little need for the all_perks/admin_perks. Instead all checkboxes simply share a basic perk class, and are then grouped by their name.

I've also skipped disabling the checkboxes, but that's simple to add.

\$\endgroup\$
  • \$\begingroup\$ Seems i am not aware of much JQuery function, you have made it far more simpler :) \$\endgroup\$ – Viral Feb 19 '15 at 15:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.