🎉 Black Friday deal! 25% off your first year of CodyHouse Pro →

Projects

Progress value is 30%

Filter

A plugin to filter/sort items in a grid.

Copy: View demo

Dependencies

All components are based on CodyFrame.

How To

The Filter component is used to filter and sort a gallery of items.


🔍 On this page:

  1. Gallery
  2. Controls
  3. Filtering
  4. Sorting
  5. Fallback Message
  6. Additional Options
  7. Initial Status
  8. Custom Sorting/Filtering functions

Create a gallery using CodyFrame's grid utility classes: use the .grid and .grid-gap-{size} classes on the gallery container, and the .col-{number} and .col-{number}@{breakpoint} classes on the grid items.

Read more about these classes on the Grid & Layout documentation page.

Make sure to add the .js-filter class to the gallery container and the .js-filter__item to each item of the gallery.

Add an ID attribute to the .js-filter element (more info about this in the Controls section).

<ul class="grid grid-gap-md js-filter" id="filter-gallery">
  <li class="col-6 [email protected] js-filter__item">
    <!-- // content here -->
  </li>

  <li class="col-6 [email protected] js-filter__item">
    <!-- // content here -->
  </li>

  <!-- additional items -->
</ul>

Controls #

Each list of controls (e.g., 'Filter by category', 'Sort by Index') needs to have an aria-controls attribute equal to the ID value of the .js-filter element.

<fieldset>
  <legend>Filter by Category</legend>

  <ul aria-controls="filter-gallery">
    <!-- list of categories -->
  </ul>
</fieldset>

<fieldset>
  <legend>Sort by Index</legend>

  <ul aria-controls="filter-gallery">
    <!-- list of Index Sorting options -->
  </ul>
</fieldset>

Filtering #

You can use the following filtering controls:

  • a list of radio input (one selected option at a time);
  • a list of checkbox input (multiple selected options at a time);
  • a list of buttons (customizable to have one selected option or multiple options at a time);
  • a <select> element (one selected option at a time).

You can use multiple filtering controls of different type for the same gallery.

Filtering - Radio/Checkbox Buttons #

Add a data-filter equal to the filter value (e.g., category-1) to each input element. If you include an All/Reset option, set its data-filter equal to *:

<!-- List of radio input -->
<fieldset>
  <legend>Filter by Category</legend>

  <ul aria-controls="filter-gallery">
    <li>
      <input type="radio" name="radioCategory" id="radioCategoryAll" data-filter="*">
      <label for="radioCategoryAll">All</label>
    </li>

    <li>
      <input type="radio" name="radioCategory" id="radioCategory1" data-filter="category-1">
      <label for="radioCategory1">Category 1</label>
    </li>

    <li>
      <input type="radio" name="radioCategory" id="radioCategory2" data-filter="category-2">
      <label for="radioCategory2">Category 2</label>
    </li>

    <!-- all other category options -->
  </ul>
</fieldset>

<!-- List of checkbox input -->
<fieldset>
  <legend>Filter by Color</legend>

  <ul aria-controls="filter-gallery">
    <li>
      <input type="checkbox" id="checkboxBgPrimary" data-filter="bg-primary">
      <label for="checkboxBgPrimary">Primary</label>
    </li>

    <li>
      <input type="checkbox" id="checkboxBgAccent" data-filter="bg-accent">
      <label for="checkboxBgAccent">Accent</label>
    </li>

    <!-- all other color options -->
  </ul>
</fieldset>

To each item in your gallery, add a data-filter equal to the list of filters that apply to that element:

<ul class="grid grid-gap-sm js-filter" id="filter-gallery">
  <li class="col-4 js-filter__item" data-filter="category-1 bg-accent">
    <!-- content here -->
  </li>

  <li class="col-4 js-filter__item" data-filter="category-2 category-3 bg-primary">
    <!-- content here -->
  </li>

  <!-- other gallery items -->
</ul>

Filtering - Group of Buttons #

Add a data-filter to each button element (same as with radio/checkbox buttons). 

To each item in your gallery, add a data-filter equal to the list of filters that apply to that element. 

You can customize the behaviour of a button control adding the following attributes to the control list element:

  • data-selected-class: pass the list of classes you want to add to the button element when it is selected (e.g., btn--selected);
  • data-filter-checkbox: set this to "true" if you want more buttons to be selectable at the same time.
<!-- the .color-primary class will be added to <button> when selected -->
<ul aria-controls="filter-gallery" data-selected-class="color-primary">
  <li><button data-filter="*">All</button></li>

  <li><button data-filter="category-1">Category 1</button></li>
  
  <li><button data-filter="category-2">Category 2</button></li>
  
  <li><button data-filter="category-3">Category 3</button></li>
</ul>

<!-- you can select multiple colors -->
<ul aria-controls="filter-gallery" data-filter-checkbox="true">
  <li><button data-filter="bg-primary">Primary</button></li>
  
  <li><button data-filter="bg-accent">Accent</button></li>
  
  <li><button data-filter="bg-contrast-lower">Contrast Lower</button></li>
</ul>

Filtering - <select> element #

Add a data-filter="true" to the <select> element and set the value of the <option> equal to the filter value:

<select aria-controls="filter-gallery" data-filter="true">
  <option value="*">All</option>
  <option value="category-1">Category 1</option>
  <option value="category-2">Category 2</option>
  <option value="category-3">Category 3</option>
</select>

To each item in your gallery, add a data-filter equal to the list of filters that apply to that element (same as with radio/checkbox buttons).

Sorting #

You can use the following sorting controls:

  • a list of radio buttons;
  • a list of buttons;
  • a <select> element.

You can have one active sorting option at a time.

Sorting - Radio Buttons #

Add a data-sort equal to the sort option (e.g., name) to each input element. If you are including an All/Reset option, set its data-sort equal to *.

By default, the order used is ascendent. You can add a data-sort-order="desc" to use a descendent order.

If you are using a number as sort option (e.g, index), add a data-sort-number="true".

<fieldset>
  <legend>Sort by</legend>

  <ul aria-controls="filter-gallery">
    <li>
      <input type="radio" name="radioSort" id="radioSortNone" data-sort="*">
      <label for="radioSortNone">No sorting</label>
    </li>

    <li>
      <input type="radio" name="radioSort" id="radioSortIndex" data-sort="index" data-sort-number="true">
      <label for="radioSortIndex">Index</label>
    </li>

    <li>
      <input type="radio" name="radioSort" id="radioSortIndexDesc" data-sort="index" data-sort-number="true" data-sort-order="desc">
      <label for="radioSortIndexDesc">Index Desc</label>
    </li>

    <li>
      <input type="radio" name="radioSort" id="radioSortName" data-sort="name">
      <label for="radioSortName">Name</label>
    </li>
  </ul>
</fieldset>

To each item in your gallery, add a data-sort-{value} equal to the value of that sorting option.

For example, if sorting by index, add a data-sort-index="indexValue". If sorting by name,  add a data-sort-name="nameValue":

<ul class="grid grid-gap-sm js-filter" id="filter-gallery">
  <li class="col-6 [email protected] js-filter__item" data-sort-index="2" data-sort-name="name1">
    <!-- content here -->
  </li>

  <li class="col-6 [email protected] js-filter__item" data-sort-index="4" data-sort-name="name2">
    <!-- content here -->
  </li>

  <!--  other items -->
</ul>

Sorting - Group of Buttons #

Add a data-sort to each button element (same as with radio buttons). 

To each item in your gallery, add a data-sort-{value} equal to the value of that sorting option. 

For each <button>, you can use a data-sort-order and data-sort-number (same as with radio buttons). 

You can add to the controls list element a data-selected-class attribute equal to the class list you want to add to the <button> element when it's selected (e.g., btn--selected):

<ul aria-controls="filter-gallery" data-selected-class="color-primary">
  <li><button data-sort="index" data-sort-number="true">Index</button></li>
  
  <li><button data-sort="index" data-sort-number="true" data-sort-order="desc">Index Desc</button></li>
</ul>

Sorting - <select> element #

Add a data-sort="true" to the <select> element and set the value of the <option> equal to the sorting option.

For each <option>, you can use a data-sort-order and data-sort-number (same as with radio buttons). 

<select aria-controls="filter-gallery" data-sort="true">
  <option value="*">Reset</option>
  <option value="index" data-sort-number="true">Index</option>
  <option value="index" data-sort-order="desc" data-sort-number="true">Index desc</option>
</select>

Fallback Message #

If you want to show a fallback message when the filtering returns no results, create an element with a data-fallback-gallery-id equal to the ID attribute of the gallery.

<div data-fallback-gallery-id="filter-gallery">
  <p>No results</p>
</div>

Additional Options #

Add the following attributes to the .js-filter element to customize the plugin:

  • data-filter-duration: the duration of the filtering animation (in ms, e.g., 500). Default is 400;
  • data-filter-animation: you can set it to 'off' if you do not want to animate items (default is 'on').

Initial Status #

Your gallery can be filtered on load. To do that you need to:

  • if you are using a list of radio/checkbox buttons, add the checked attribute to the selected filter/sort <input>;
  • if you are using a <select> element, add the selected attribute to the selected filter/sort <option>;
  • if you are using a list of buttons, add the .js-filter-selected class to the selected filter/sort <button>.

Custom Sorting/Filtering functions #

You can customize the filter functionality using the Filter object and passing custom functions to this object.

To do that, do not add the .js-filter class to the gallery container; this way, the filter will not be initialized with the default parameters (your custom configuration will be used).

In your JS, inizialize the gallery passing your custom filtering/sorting function:

new Filter({
  element: document.getElementById('filter-gallery'), // this is your gallery element
  customFilterFn: function(items){
    // function code here
  },
  customSortFn: function(items){
    // function code here
  }
});

Custom Filtering Function #

If you want to use a custom filter function for one of your controls, set the data-filter attribute of the control equal to the function and then pass the function as configuration parameter.

Let's say that you want to only show items that have a even data-order value. We'll define the orderEven function:

<fieldset>
  <legend>Filter by</legend>

  <ul aria-controls="filter-gallery">
    <li>
      <input type="checkbox" id="checkboxOrderEven" data-filter="orderEven">
      <label for="checkboxOrderEven">Show items with even order value</label>
    </li>

    <!-- other filters -->
  </ul>
</fieldset>

<ul class="grid grid-gap-sm" id="filter-gallery">
  <li class="col-4 js-filter__item" data-order="4">
    <!--  content here-->
  </li>

  <!-- other items here -->
</ul>

<script>
  new Filter({
    element: document.getElementById('filter-gallery'), // this is your gallery element
    orderEven: function(items){ // custom filter function
      var filteredArray = [];
      for(var i = 0; i < items.length; i++) {
        filteredArray[i] = parseInt(items[i].getAttribute('data-order')) % 2 == 0;
      } 
      return filteredArray;
    }
});
</script>

The custom function has to return an array of booleans: true if the item is visible, false otherwise.

Custom Sorting Function #

If you want to use a custom sort function for one of your controls, set the data-sort attribute of the control equal to the function and then pass the function as configuration parameter.

Let's say that you want to sort items by the sum of two values (data-order and data-score). We'll define the scoreOrder function:

<fieldset>
  <legend>Sort by</legend>

  <ul aria-controls="filter-gallery">
    <li>
      <input type="radio" id="radioScoreOrder" data-sort="scoreOrder">
      <label for="radioScoreOrder">Sort by score+order sum</label>
    </li>

    <!-- other sort options -->
  </ul>
</fieldset>

<ul class="grid grid-gap-sm" id="filter-gallery">
  <li class="col-4 js-filter__item" data-order="4" data-score="5">
    <!--  content here-->
  </li>

  <!-- other items here -->
</ul>

<script>
  new Filter({
    element: document.getElementById('filter-gallery'), // this is your gallery element
    scoreOrder: function(items){ // custom score function
      items.sort(function(left, right) {
        var leftVal = parseInt(left[0].getAttribute('data-order')) + parseInt(left[0].getAttribute('data-score')),
        rightVal = parseInt(right[0].getAttribute('data-order')) + parseInt(right[0].getAttribute('data-score'));
        return leftVal > rightVal ? -1 : 1;
      });
      return items;
});
</script>

The custom function accepts as argument an array: each item of the array has, as first element, one item of the gallery and as second element the initial index of the item. The function needs to sort the array and return it.

✅ Project duplicated

✅ Project created

There was an error while trying to export your project. Please try again or contact us