0

In a jQuery datatable I have checkbox column multi-select filters. I've a 'Select All / None' checkbox at the top of each filter. I can select all checkboxes, but problem is I can't seem to confine the selection to the active container only - in other words all the checkboxes in the other columns get checked too. The fiddle shows some of the alternatives I've tried on the basis of researching other posts on this for a few hours, but I'm suspecting the structure of the dropdowns is complicating things in this particular case. Anyone any ideas? Fiddle:https://jsfiddle.net/Lxytynm3/

    <table id="example" class="display" cellspacing="0" width="100%">
  <thead>
    <tr>
      <th>Name</th>
      <th>Position</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Tiger Nixon</td>
      <td>System Architect</td>
    </tr>
    <tr>
      <td>Garrett Winters</td>
      <td>Accountant</td>
    </tr>
    <tr>
      <td>Ashton Cox</td>
      <td>Junior Technical Author</td>
    </tr>
  </tbody>
</table>

.

    $(document).ready(function() {
  function cbDropdown(column) {
    return $('<ul>', {
      'class': 'cb-dropdown'
    }).appendTo($('<div>', {
      'class': 'cb-dropdown-wrap'
    }).appendTo(column));
  }

  $('#example').DataTable({
    initComplete: function() {
      this.api().columns().every(function() {
        var column = this;
        var ddmenu = cbDropdown($(column.header()))

          // -------------------------------------------------------

          .on('change', ':checkbox', function() {
            var active;
            var vals = $(':checked', ddmenu).map(function(index, element) {
              active = true;
              return $.fn.dataTable.util.escapeRegex($(element).val());
            }).toArray().join('|');

            column
              .search(vals.length > 0 ? '^(' + vals + ')$' : '', true, false)
              .draw();

            // -------------------------------------------------------
            // Highlight the current item if selected.
            if (this.checked) {
              $(this).closest('li').addClass('active');

              // If 'Select all / none' clicked ON
              if ($(this).val() === "1") {

                $('ul.cb-dropdown').find('input[type="checkbox"]').prop('checked', this.checked)
                //$(".cb-dropdown li").prop('checked', true);
                //$('.cb-dropdown').closest('li').find('input[type="checkbox"]').prop('checked', true);
                // $('this input[type="checkbox"]').prop('checked', true);    works!
                // $( 'input[type="checkbox"]' ).prop('checked', this.checked);
                // $(this).find('input[type="checkbox"]').prop('checked', this.checked)
                //$('div.cb-dropdown-wrap.active').children().find('input[type="checkbox"]').prop('checked', this.checked)

              }
            } else // 'Select all / none' clicked OFF

            {
              $(this).closest('li').removeClass('active');
              // test if select none
              if ($(this).val() === "1") {
                // code to untick all
              }
            }

            // Highlight the current filter if selected.
            var active2 = ddmenu.parent().is('.active');
            if (active && !active2) {
              ddmenu.parent().addClass('active');

              // Change Container title to "Filter on" and green
              //$(this).parent().find('.cb-dropdown li:nth-child(n+1)').css('color','red');   
              $('active2 li label:contains("Filter OFF")').text('Yeees');

            } else if (!active && active2) {
              ddmenu.parent().removeClass('active');
            }
          });

        // -------------------------------------------------------
        var mytopcount = '0'; // Counter that ensures only 1 entry per container

        // loop to assign all options in container filter
        column.data().unique().sort().each(function(d, j) {

          // Label
          var $label = $('<label>'),
            $text = $('<span>', {
              text: d
            }),

            // Checkbox
            $cb = $('<input>', {
              type: 'checkbox',
              value: d
            });


          $text.appendTo($label);
          $cb.appendTo($label);

          ddmenu.append($('<li>').append($label));


          // -----------------
          // Add 'Select all / none' to each dropdown container
          if (mytopcount == '0') // Counter that ensures only 1 entry per container
          {
            $label = $('<label>'), $text = $('<span>', {
                text: "Select all / none"
              }),

              $cb = $('<input>', {
                type: 'checkbox',
                value: 1
              });

            $text.prependTo($label).css('margin-bottom', '6px');
            $cb.prependTo($label);
            ddmenu.prepend($('<li>').prepend($label).css({
              'border-bottom': '1px solid grey',
              'margin-bottom': '6px'
            }));

            mytopcount = '1' // This stops this section running again in container 

          }

        });

      });
    }
  });

});

.

.cb-dropdown-wrap {
  max-height: 80px;
  position: relative;
  height: 219px;
  /* Temporary to fix dropdown */
}

.cb-dropdown,
.cb-dropdown li {
  margin: 0;
  padding: 0;
  list-style: none;
  transition: 0.2s 0.23s height ease-in-out;
}

.cb-dropdown {
  position: absolute;
  z-index: 1;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: white;
  border: 1px solid red;
}

.cb-dropdown-wrap:hover .cb-dropdown {
  height: 100px;
  overflow: auto;
  transition: 0.15s 0.1s height ease-in-out;
}

.cb-dropdown li.active {
  background: lightgreen;
}

.cb-dropdown li label {
  display: block;
  position: relative;
  cursor: pointer;
  line-height: 19px;
}

.cb-dropdown li label>input {
  position: absolute;
  left: 0;
  top: 0;
  width: 16px;
}

.cb-dropdown li label>span {
  display: block;
  margin-left: 24px;
  /* At least, width of the checkbox. */
  font-family: sans-serif;
  font-size: 12px;
  font-weight: normal;
  text-align: left;
}

.cb-dropdown li:hover {
  background: lightgrey;
}

table.dataTable thead .sorting,
table.dataTable thead .sorting_asc,
table.dataTable thead .sorting_desc,
table.dataTable thead .sorting_asc_disabled,
table.dataTable thead .sorting_desc_disabled {
  background-position: 100% 10px;
}

1 Answer 1

1

You already have the object that contains the checkboxes in the variable ddmenu

Instead of this:

$('ul.cb-dropdown').find('input[type="checkbox"]').prop('checked', this.checked)

Use this:

$(ddmenu).find('input[type="checkbox"]').prop('checked', this.checked)

Don't forget to add the code to untick them:

$(ddmenu).find('input[type="checkbox"]').prop('checked', false)

See: https://jsfiddle.net/Lxytynm3/2/

Sign up to request clarification or add additional context in comments.

2 Comments

I could kick myself! Much appreciated @AaronBC. Only problem is that I was expecting to see all the table entries showing - in other words the equivalent to each checkbox ticked individually. Any idea why this doesn't work?
It's OK - I've sorted it out. Just needed to move this code higher up before the regex.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.