Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multifilter and jQuery Chosen plugin #417

Closed
mungerj opened this issue Feb 6, 2018 · 15 comments
Closed

Multifilter and jQuery Chosen plugin #417

mungerj opened this issue Feb 6, 2018 · 15 comments

Comments

@mungerj
Copy link

mungerj commented Feb 6, 2018

Hi,

I'm doing some tests with MixitUp multifilter and would like to combine it with the Chosen plugin (link) that we are currently using. However using them both does not seem to work.

`$( document ).ready(function() {
$(".chosen-select").chosen();
var mixer = mixitup('ul#listIndic', {
selectors: {
target: 'li.elemIndic'
},
multifilter: {
enable: true
},
callbacks: {
onMixStart: function(state, futureState) {
console.log(futureState.activeFilter.selector);
}
}
});

});`

Multifilter is working if I comment the "chosen" line. However when combining with Mixitup multifilter, filtering won't work anymore (nothing shows in the console, so it seems it's not getting to onMixStart). If you have a working demo with multifilter, could you try to add Chosen to see what the problem could be?

@patrickkunka
Copy link
Owner

patrickkunka commented Feb 7, 2018

The multifilter extension expects a <select> element to a emit a native 'change' DOM event. When a change event is emitted from any element within a filter group, its value will be read via the element's value property.

So as your callback is not being called, it would seem that chosen is not emitting the standard change DOM event when its value changes. Many of these older jQuery plugins implement non-standard event emitters which can cause problems.

@patrickkunka
Copy link
Owner

patrickkunka commented Feb 7, 2018

I've just done a bit more digging, and it seems that as suspected, chosen does not emit native DOM events, only jQuery events. We can add a shim as follows:

var nativeSelect = document.querySelector('.chosen-select');
var blockHandler = false;

$('.chosen-select').first()
    .chosen()
    .change(function() {
        if (blockHandler) {
            blockHandler = false;

            return;        
        }

        var ev = new CustomEvent('change');

        blockHandler = true;

        nativeSelect.dispatchEvent(ev);
    });

Please let me know if that works.

@mungerj
Copy link
Author

mungerj commented Feb 8, 2018

It's not working, unfortunately.

I have two multiple select (with the chosen-select class), if it can help findig the issues. I'll run some tests to see if I can find what's going on.

@mungerj
Copy link
Author

mungerj commented Feb 8, 2018

Well it doesn't seem to be related to multifilter or multiple choices select controls. I put up a jsFiddle and we can see it doesn't work with a basic configuration, see here: http://jsfiddle.net/Lvo4rd63/

EDIT: OK, I used the code you provided in the jsFiddle and it is working! Now I'll try to see why it doesn't work in my more complex page...

@patrickkunka
Copy link
Owner

patrickkunka commented Feb 8, 2018

Apologies, I didn't realise you had multiple select elements on the page. The code I gave you only works with one. I've updated to account for many:

$('.chosen-select')
    .each(function() {
        var $select = $(this);
        var blockHandler = false;
    
        $select.chosen();
        
        $select.change(function() {
            if (blockHandler) {
                blockHandler = false;

                return;        
            }

            var ev = new CustomEvent('change');

            blockHandler = true;

            $select[0].dispatchEvent(ev);
        });
    });

@mungerj
Copy link
Author

mungerj commented Feb 8, 2018

Any idea why this code isn't working when the select allows multiple choices? http://jsfiddle.net/Lvo4rd63/3/

(Not related to Chosen, it won't work either when Chosen is disabled)

@patrickkunka
Copy link
Owner

patrickkunka commented Feb 8, 2018

The demo that you based it on is not set up to handle select multiple. If you want to adapt it you can edit the change handler function to the following:

selectFilter.addEventListener('change', function() {
    var selectors = Array.from(selectFilter.options)
        .filter(function(option) { 
            return option.selected;
        })
        .map(function(option) {
            return option.value;
        });

    mixer.filter(selectors.join(', '));
});

However, if you're using the multifilter extension, you won't need to do this as the functionality to detect whether a select is a multiple select and handle it accordingly is already built-in.

@mungerj
Copy link
Author

mungerj commented Feb 8, 2018

It kinda works, but when you have two multiple selects, the second one doesn't work.

I guess it's because the values are only picked from the first one, since document.querySelector only returns the first occurence:

var selectFilter = document.querySelector('.select-filter');

@patrickkunka
Copy link
Owner

patrickkunka commented Feb 8, 2018

Are you using MultiFilter or not? You won't need any of this code if you're using MultiFilter.

If you're just intending to use MixItUp core, but with multiple select elements to handle, you can query using querySelectorAll() (or just jQuery):

var selectFilters = Array.from(document.querySelectorAll('.select-filter'));

function bindChangeHandler(function(selectFilter) {
    selectFilter.addEventListener('change', handleChange);
});

function handleChange(e) {
    var selectors = Array.from(e.target.options)
        .filter(function(option) { 
            return option.selected;
        })
        .map(function(option) {
            return option.value;
        });

    mixer.filter(selectors.join(', '));
}

selectFilters.forEach(bindChangeHandler);

But in this case you'll need to deal with the logic of how you want to combine and concatenate their selectors, which the above code does not include as its extremely complex... this is the purpose of the MultiFilter extension. As long as you can get your chosen instances emitting native DOM events (as per my earlier comment), you're good to go and you don't need any of this.

@mungerj
Copy link
Author

mungerj commented Feb 9, 2018

Yes, I'm using multifilter, but can't load it into jsFiddle. I'll try to set up a new one, because it's not working on my own server.

@patrickkunka
Copy link
Owner

Basically you need to do two things.

First, get your MultiFilter project set up and working with plain native select options.

Then, add the following code (adjusting the '.chosen-select' selector as necessary):

$('.chosen-select')
    .each(function() {
        var $select = $(this);
        var blockHandler = false;
    
        $select.chosen();
        
        $select.change(function() {
            if (blockHandler) {
                blockHandler = false;

                return;        
            }

            var ev = new CustomEvent('change');

            blockHandler = true;

            $select[0].dispatchEvent(ev);
        });
    });

That should be it.

@mungerj
Copy link
Author

mungerj commented Feb 9, 2018

Here's a jsFiddle with an example.

It works without Chosen, but your snippet doesn't seem to solve the problem with Chosen.

@patrickkunka
Copy link
Owner

patrickkunka commented Feb 9, 2018

Ah thanks for that - I forgot that MultiFilter listens for change events on the group not the individual select, so we need to make sure that the change event bubbles up (this is normally the default behavior of a change event, but since we're faking it we have to manually specify it).

change the line:

var ev = new CustomEvent('change');

to:

var ev = new CustomEvent('change', {
    bubbles: true
});

Tested and working!

@mungerj
Copy link
Author

mungerj commented Feb 10, 2018

Works great now! Thanks!

@patrickkunka
Copy link
Owner

Great 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants