tmarois
tmarois

Reputation: 2470

jQuery Multiselect - Select All and with Filtered Search

When you use the search feature, and then use the select_all it does not work together, it selects "everything" as if the search made no change, but the search itself "hides" the elements. It should only select all to the items that are visible

Wondering if someone else has had this issue or knows a solution to it. Thanks again if anyone can be of assistance!

Using the jQuery MultiSelect Plugin: http://loudev.com

This is the code I'm currently using, the search utilizes the quicksearch js

$('.multiSelect').multiSelect({
  selectableHeader: "<div><a href='#' id='select-all'>select all</a></div><input type='text' class='search-input form-control' autocomplete='off' placeholder='search' style='margin-bottom:5px'>",
  selectionHeader: "<div><a href='#' id='deselect-all'>deselect all</a></div><input type='text' class='search-input form-control' autocomplete='off' placeholder='search' style='margin-bottom:5px'>",
  afterInit: function(ms){
    var that = this,
        $selectableSearch = that.$selectableUl.prev(),
        $selectionSearch = that.$selectionUl.prev(),
        selectableSearchString = '#'+that.$container.attr('id')+' .ms-elem-selectable:not(.ms-selected)',
        selectionSearchString = '#'+that.$container.attr('id')+' .ms-elem-selection.ms-selected';

    that.qs1 = $selectableSearch.quicksearch(selectableSearchString)
    .on('keydown', function(e){
      if (e.which === 40){
        that.$selectableUl.focus();
        return false;
      }
    });

    that.qs2 = $selectionSearch.quicksearch(selectionSearchString)
    .on('keydown', function(e){
      if (e.which == 40){
        that.$selectionUl.focus();
        return false;
      }
    });
  },
  afterSelect: function(){
    this.qs1.cache();
    this.qs2.cache();
  },
  afterDeselect: function(){
    this.qs1.cache();
    this.qs2.cache();
  }
});


$('#select-all').on('click',function(){
  $('.multiSelect').multiSelect('select_all');
  return false;
});

$('#deselect-all').on('click',function(){
  $('.multiSelect').multiSelect('deselect_all');
  return false;
});

jsfiddle for demonstration: http://jsfiddle.net/b8ygzqca/6/

Upvotes: 4

Views: 6575

Answers (2)

Rubioli
Rubioli

Reputation: 680

I had the same issue and based on my tests, you don't need to change the source code.

Simply in your afterInit do prev() & find(), as below:

selectableHeader: "<div class='myDiv'><input type='text autocomplete='off'></div>"

$selectableSearch = that.$selectableUl.prev().find('input'),
$selectionSearch = that.$selectionUl.prev().find('input'),

Keep in mind for each div you have before the input, you need to do prev(). For instance:

selectableHeader: "<div class='mydDiv'><input type='text'autocomplete='off'><a href='#' id='select-all'>Add All</a></div><div class='myExtraDiv'></div>

You would need to do:

$selectableSearch = that.$selectableUl.prev().prev().find('input')

Since the first prev(), would get <div class='myExtraDiv'></div> and your 2nd prev() would fetch the correct input.

Tips: Run console.log($selectableSearch); to see what you've selected with prev()

Hope this help someone!

Upvotes: 0

Kevin Hicks
Kevin Hicks

Reputation: 21

I ran into the same issue yesterday. I too looked around for solution, but only found your post. So here is my solution. Please note that I actually updated the source code to get my solution to work. I modified the 'select_all' function:

'select_all': function () {
        var that = this,
            ms = this.$element,
            values = ms.val(),
            selectables = this.$selectableUl.find('.ms-elem-selectable').filter(':not(.' + this.options.disabledClass + ')').filter(':visible');

        ms.find('option:not(":disabled")')
            .filter(function (index) {
                var it = this,
                    msValue = selectables
                        .filter(function () {
                            return $(this).data('ms-value') === it.value;
                        })
                        .data('ms-value');
                return msValue === this.value;
            })
            .prop('selected', true);
        selectables.addClass('ms-selected').hide();
        this.$selectionUl.find('.ms-optgroup-label').show();
        this.$selectableUl.find('.ms-optgroup-label').hide();
        this.$selectionUl
            .find('.ms-elem-selection')
            .filter(':not(.' + this.options.disabledClass + ')')
            .filter(function (index) {
                return that.$selectableUl.find('#' + $(this).attr('id').replace('-selection', '-selectable') + '.ms-selected' ).length === 1;
            })
            .addClass('ms-selected')
            .show();
        this.$selectionUl.focus();
        ms.trigger('change');
        if (typeof this.options.afterSelect === 'function') {
            var selectedValues = $.grep(ms.val(), function (item) {
                return $.inArray(item, values) < 0;
            });
            this.options.afterSelect.call(this, selectedValues);
        }
    },

I added a 'that' var and then added extra filter calls on this.$selectableUl and this.$selectionUl. I also updated how the options on ms are selected. Hopefully this will work for you too.

Upvotes: 1

Related Questions