Installing Extensions

Premium extensions are downloaded from your KunkaLabs account after purchase and are not publicly available via GitHub or NPM. Once downloaded they can be included in your project in a directory of your choosing, and then required as modules, or globally via a script tag.

Alternatively, premium extensions can also be hosted in your organization's private NPM or Github account. You may then run npm install using that repository's path.

Script Tag

If using a script tag, you simply need to load the multifilter distribution script (i.e. mixitup-multifilter.min.js) after mixitup, and the extension will automatically detect the mixitup global variable and install itself.

...

        <script src="/path/to/mixitup.min.js"></script>
        <script src="/path/to/mixitup-multifilter.min.js"></script>
    </body>
</html>

Module Import

If you are building a modular JavaScript project with Webpack, Browserify, or RequireJS, you will need to require both the MixItUp core and the MultiFilter extension into your module. Then call mixitup.use() with the extension passed in as an argument. Your extension will be installed and made available to all MixItUp instances throughout your project.

// ES2015

import mixitup from 'mixitup'; // loaded from node_modules
import mixitupMultifilter from '../path/to/mixitup-multifilter'; // loaded from a directory of your choice within your project

// Call the mixitup factory's .use() method, passing in the extension to install it

mixitup.use(mixitupMultifilter);
// CommonJS

var mixitup = require('mixitup');
var mixitupMultifilter = require('../path/to/mixitup-multifilter');

mixitup.use(mixitupMultifilter);
// AMD

require([
    'mixitup',
    '../path/to/mixitup-multifilter'
], function(
    mixitup,
    mixitupMultifilter
) {
    mixitup.use(mixitupMultifilter);
});

You need only call the .use() function once per project, per extension, as module loaders will cache a single reference to MixItUp inclusive of all changes made.

Using MultiFilter

MixItUp MultiFilter extends MixItUp's API and configuration object with various new methods and properties, and adds the ability to query and index groups of filter controls, known as "filter groups".

By default, multifilter functionality is disabled so that you can use MixItUp as normal, even with the extension installed. To enable multifilter functionality for a mixer, you simply need set the multifilter.enable configuration option to true.

var mixer = mixitup(containerEl, {
    multifilter: {
        enable: true // enable the multifilter extension for the mixer
    }
});

Filtering Dimensions

MixItUp MultiFilter is designed to be used with content requiring filtering by multiple distinct attributes or "dimensions". Taking a clothing store as an example, some dimensions might include type (e.g. sweaters, shirts, jackets), color (red, green, blue), and size (small, medium, large).

Another example is our sandbox demo which uses the dimensions of shape (e.g. square, triangle, circle), color, and size.

MixItUp MultiFilter allows us to combine filter selectors within each of these dimensions, using a variety of logic. To learn more about MixItUp filter logic, you may wish to read the Filtering with MixItUp tutorial before continuing.

Filter Group UI

Filter groups are an essential part of a multifilter-enabled mixer and are defined in your markup. Each group represents a particular dimension, and can contain a many different types of UI within it. Filter groups are queried by MixItUp based on the presence of a data-filter-group attribute. You may use any outer element as a filter group, but <fieldset> makes sense semantically, particularly when using inputs like checkboxes or radios within it.

You can think of your entire multifilter UI as a <form> with which to interact with your mixer.

<form>
    <fieldset data-filter-group>
        <button type="button" data-filter=".jacket">Jackets</button>
        <button type="button" data-filter=".sweater">Sweaters</button>
        <button type="button" data-filter=".shirt">Shirts</button>
    </fieldset>

    <fieldset data-filter-group>
        <button type="button" data-toggle=".red">Red</button>
        <button type="button" data-toggle=".blue">Blue</button>
        <button type="button" data-toggle=".green">Green</button>
    </fieldset>
</form>

Wrapping filter groups in a parent <form> is optional, but provides the ability to use submit and reset buttons as part of your UI.

In the example above, filter control buttons are used in the first group, and toggle control buttons are used in the second group. To recap the Filtering with MixItUp tutorial, filter controls allow one active control at a time, and toggle controls allow multiple active controls simultaneously. This behavior is also true when using filter groups, but is confined to within the group. Therefore, the UI above would allow us to select one type of clothing, but multiple colors.

Filter and toggle controls are just two example of the different types of UI available in MixItUp MultiFilter. Let's take a look at what else is available:

Radios
<fieldset data-filter-group>
    <label>Red</label>
    <input type="radio" name="color" value=".red"/>

    <label>Blue</label>
    <input type="radio" name="color" value=".blue"/>

    <label>Green</label>
    <input type="radio" name="color" value=".green"/>
</fieldset>

Providing the same functionality as MixItUp's filter controls (one active input at a time), radios provide a more form-like UI with a smaller footprint.

Checkboxes
<fieldset data-filter-group>
    <label>Red</label>
    <input type="checkbox" value=".red"/>

    <label>Blue</label>
    <input type="checkbox" value=".blue"/>

    <label>Green</label>
    <input type="checkbox" value=".green"/>
</fieldset>

Providing the same functionality as MixItUp's toggle controls (multiple active inputs at a time), checkboxes also provide a more form-like UI with a smaller footprint.

Selects
<fieldset data-filter-group>
    <select>
        <option value="">Select a color</option>
        <option value=".red">Red</option>
        <option value=".blue">Blue</option>
        <option value=".green">Green</option>
    </select>
</fieldset>

Selects can be used to select one value from many values with a very small footprint. If the multiple attribute is added ( <select multiple>), selects can also be used to select multiple values.

Text
<fieldset data-filter-group>
    <input type="text" data-search-attribute="class" placeholder="Search by color"/>
</fieldset>

Text inputs can be used to search targets by a partial or complete string. A data-search-attribute must be added to the input to tell MixItUp which attribute to search. The example above searches the class attribute, consistent with the other examples. For example, entering the string 'Gree' would show any targets with the class 'green'.

The value of your text input will be converted to lowercase before searching, so ensure that the contents of the attribute you intend to search are also lowercase.

Configuring Filter Group Logic

MixItUp MultiFilter allows us to define one type of logic between filter groups and another type within them, using the configuration options multifilter.logicBetween and multifilter.logicWithin.

The most common (and default) combination of logic is 'or' within groups and 'and' between. It should be noted that this combination will suit the vast majority of multifiltering projects, but you may configure either of these properties to be 'and' and 'or' as necessary.

You may also override the multifilter.logicWithin setting on a per-group basis by adding a data-logic attribute to your filter group's markup, with a value of either 'or' or 'and':

Example: Overriding multifilter.logicWithin for a specific group

<fieldset data-filter-group data-logic="and">

To visualize what's meant by combining logic between groups, consider the following:

Show (shirts OR sweaters) AND (red OR blue) AND large

This would be an example or 'or' logic within groups, and 'and' logic between, and as noted above, is the most common combination of logic. Given this combination of active UI elements, MixItUp MultiFilter will generate the following selector string with which to filter the content of your container:

'.shirt.red.large, .shirt.blue.large, .sweater.red.large, .sweater.blue.large'

To help with debugging and development you may wish to console log the generated selector using one of MixItUp's callback functions. For example:

Example: Logging the generated filter selector using the onMixStart callback

var mixer = mixitup('.container', {
    multifilter: {
        enable: true
    },
    callbacks: {
        onMixStart: function(state, futureState) {
            console.log(futureState.activeFilter.selector);
        }
    }
});

In addition to the configuration options already mentioned, MixItUp MultiFilter also makes use of several existing configuration options from the MixItUp core. These include:

controls.toggleDefault

Defines the toggle filter state when all controls are deactivated. The available options are 'all' (default), or 'none'.

controls.scope

Defines whether multifilter UI should be isolated to a specific mixer ('local'), or global to the document ('global').

See the Configuration Object documentation page for more information about configuring MixItUp MultiFilter.

Additional Form Behavior

As mentioned previously, we can think of our multifilter UI as a <form> with which to interact with our mixer. Adding a parent <form> element to our UI also provides some additional benefits:

Reset Buttons

Reset buttons can be included within a form of filter groups to clear and reset all active UI and return the mixer to its default filter state (see controls.toggleDefault).

This is a very common UI pattern in search interfaces and allows the user to quickly return to full set of content without having to deactivate every UI element individually.

<form>
    <fieldset data-filter-group>
       ...
    </fieldset>

    <fieldset data-filter-group>
       ...
    </fieldset>

    <button type="reset">Clear filters</button>
</form>

Similarly, if we want the ability reset an individual filter group, we can use individual forms as filter group elements, and nest reset buttons within them:

<div>
    <form data-filter-group>
       ...
       <button type="reset">Clear filters</button>
    </form>

    <form data-filter-group>
       ...
       <button type="reset">Clear filters</button>
    </form>
</div>

Submit Buttons

The default behavior of MixItUp MultiFilter is to trigger a filter operation whenever a control is clicked, or an input value changes. This allows the user to see the content change in real time as they interact with the UI.

By adding a submit button and changing the value of the multifilter.parseOn configuration option from 'change' to 'submit', we can delay the filter operation until the user has made their selection and is ready to search. The filter operation will then be triggered only when the user clicks the submit button.

Example: Changing the multifilter.parseOn configuration option

var mixer = mixitup('.container', {
    multifilter: {
        parseOn: 'submit'
    }
});
<form>
    <fieldset data-filter-group>
       ...
    </fieldset>

    <fieldset data-filter-group>
       ...
    </fieldset>

    <button type="reset">Clear filters</button>
    <button type="submit">Search</button>
</form>

To prevent users from accidentally triggering an HTTP form submission by clicking submit before your application's JavaScript has loaded, you may add a disabled attribute to the submit button, and MixItUp MultiFilter will remove it once it has parsed your markup.

<button type="submit" disabled>Search</button>

Named Filter Groups

If you wish to interact with filter groups via the .setFilterGroupSelectors() API method (see Mixer API Methods), we can name our groups by providing a value to data-filter-group attribute.

<form>
    <fieldset data-filter-group="color">
        ...
    </fieldset>

    <fieldset data-filter-group="size">
        ...
    </fieldset>
</form>

We can then target that group by its name when we call the API:

mixer.setFilterGroupSelectors('color', ['.green', '.blue']);

mixer.parseFilterGroups();