Filtering a product carousel using JQuery and Slick

11,626

Solution 1

So I managed to figure this one out by abandoning the method of looking for a specific id click and instead pulling the vendor name from the id of the list and then using that as a variable. New HTML:

<div class="container" >
    <div class="row">
        <div class="col-xs-12">
            <div class="product-carousel">
                <div class="item filter-apple"><img class="product-selector" src="images/products/product-fcp7.png"  /></div>
                <div class="item filter-apple"><img class="product-selector" src="images/products/product-fcpx.png" /></div>
                <div class="item filter-apple"><img class="product-selector" src="images/products/product-motion5.png" /></div>
                <div class="item filter-adobe"><img class="product-selector" src="images/products/product-aftereffects.png" /></div>
                <div class="item filter-adobe"><img class="product-selector" src="images/products/product-encore.png" /></div>
                <div class="item filter-adobe"><img class="product-selector" src="images/products/product-indesign.png" /></div>
                <div class="item filter-avid"><img class="product-selector" src="images/products/product-mediacomposer.png" /></div>
                <div class="item filter-adobe"><img class="product-selector" src="images/products/product-photoshop.png" /></div>
                <div class="item filter-adobe"><img class="product-selector" src="images/products/product-premierepro.png" /></div>
                <div class="item filter-davinci"><img class="product-selector" src="images/products/product-resolve.png" /></div>
                <div class="item filter-autodesk"><img class="product-selector" src="images/products/product-smoke.png" /></div>
            </div>
            <div class="vendors-wrapper">
                <ul class="vendors">
                  <li id="apple"><button class="btn btn-xs btn-primary product-button">Apple</button></li>
                  <li id="adobe"><button class="btn btn-xs btn-primary product-button">Adobe</button></li>
                  <li id="avid"><button class="btn btn-xs btn-primary product-button">Avid</button></li>
                  <li id="davinci"><button class="btn btn-xs btn-primary product-button">Davinci</button></li>
                  <li id="autodesk"><button class="btn btn-xs btn-primary product-button">Autodesk</button></li>
                </ul>
            </div>          
        </div>
    </div>

And then the function to filter the products and change the button states.

$('.product-button').on('click', function(){
    var filtername = $(this).parent('li').attr('id');
    var currentclass = $(this).attr('class');
    if(currentclass == 'btn btn-xs btn-default product-button') {
        // currently filtered, turn the others off and this on
        $('.product-carousel').slickUnfilter();
        $('.product-carousel').slickFilter('.filter-' + filtername);
        $('.product-carousel').slickGoTo(0);
        $('.product-button').attr('class', 'btn btn-xs btn-default product-button');
        $(this).attr('class', 'btn btn-xs btn-primary product-button');
    } else {
        // is this the only currently selected vendor or are they all active?
        var numberactive = $('.vendors').find('.btn-default').length;
        if(numberactive > 0) {
            // toggle them all back on
            $('.product-carousel').slickUnfilter();
            $('.product-carousel').slickGoTo(0);
            $('.product-button').attr('class', 'btn btn-xs btn-primary product-button');
        } else {
            // switch the others off
            $('.product-carousel').slickUnfilter();
            $('.product-carousel').slickFilter('.filter-' + filtername);
            $('.product-carousel').slickGoTo(0);
            $('.product-button').attr('class', 'btn btn-xs btn-default product-button');
            $(this).attr('class', 'btn btn-xs btn-primary product-button');
        }
    }
});

Still would appreciate if anyone knows how to centre items in the slick display window. Currently always seems to be left justified (which looks a bit odd in a wide window when you've filtered down to just one product). Tried the centerMode option, but doesn't seem to do much. I may be using it incorrectly.

Solution 2

Centered the carousel items with css. https://jsfiddle.net/jnallie/hr1155fm/

body {
    background: black;
}
.vendors {
    list-style: none;
    text-align: center;
    margin: 0px;
    margin-bottom:10px;
    padding: 0px;
}
.product-carousel .item {   
    background: green;
    text-align: center;
    margin: 0 5px;    
}

.product-carousel .item img {
    margin: 0 auto;
}

.vendors li {
    display: inline-block;
}
.product-selector {
    width: 64px;
}
Share:
11,626
PeteSE4
Author by

PeteSE4

Sloppy programmer who started writing BASIC games in 1982 and was surprised to find people actually paid money for them. Now (mostly) a PHP guy who has yet to bury the barely-twitching corpse of Classic ASP since my biggest client appear to still be clinging onto it. Pet peeve is purists who say you can't use tables in HTML for presentation but haven't had to deal with the sharp end of designing an HTML email that will work across multiple clients that shrug at you when presented with a tag.

Updated on June 04, 2022

Comments

  • PeteSE4
    PeteSE4 almost 2 years

    I'm building a carousel of product which has vendor buttons below that allow you to filter them. So the initial display is all the product logos, but pressing the 'Adobe' (for example) button then filters out everything that is not an Adobe product, and pressing the button again unfilters it.

    I'm using JQuery with Slick and then a bit of custom javascript to handle the filtering. Let's start with the HTML.

    <div class="container" >
        <div class="row">
            <div class="col-xs-12">
                <div class="product-carousel">
                    <div class="item filter-apple"><img class="product" src="images/products/product-fcp7.png"  /></div>
                    <div class="item filter-apple"><img class="product" src="images/products/product-fcpx.png" /></div>
                    <div class="item filter-apple"><img class="product" src="images/products/product-motion5.png" /></div>
                    <div class="item filter-adobe"><img class="product" src="images/products/product-aftereffects.png" /></div>
                    <div class="item filter-adobe"><img class="product" src="images/products/product-encore.png" /></div>
                    <div class="item filter-adobe"><img class="product" src="images/products/product-indesign.png" /></div>
                    <div class="item filter-avid"><img class="product" src="images/products/product-mediacomposer.png" /></div>
                    <div class="item filter-adobe"><img class="product" src="images/products/product-photoshop.png" /></div>
                    <div class="item filter-adobe"><img class="product" src="images/products/product-premierepro.png" /></div>
                    <div class="item filter-davinci"><img class="product" src="images/products/product-resolve.png" /></div>
                    <div class="item filter-autodesk"><img class="product" src="images/products/product-smoke.png" /></div>
                </div>
                <div class="vendors-wrapper">
                    <ul class="vendors">
                      <li><button class="btn btn-xs btn-primary product-button" id="button-apple">Apple</button></li>
                      <li><button class="btn btn-xs btn-primary product-button" id="button-adobe">Adobe</button></li>
                      <li><button class="btn btn-xs btn-primary product-button" id="button-avid">Avid</button></li>
                      <li><button class="btn btn-xs btn-primary product-button" id="button-davinci">Davinci</button></li>
                      <li><button class="btn btn-xs btn-primary product-button" id="button-autodesk">Autodesk</button></li>
                    </ul>
                </div>          
            </div>
        </div>
    </div>
    

    As you can see, I'm using a class on the item divs so I can filter them later. Here's the Javascript:

    $(document).ready(function(){
        $('.product-carousel').slick({
          slidesToShow: 8,
          autoplay: true
        });
    });
    
    var filtered = false;
    
    $('#button-apple').on('click', function(){
      if(filtered === false) {
        $('.product-carousel').slickUnfilter();
        $('.product-carousel').slickFilter('.filter-apple');
        $('.product-carousel').slickGoTo(0);
        $('.product-button').attr('class', 'btn btn-xs btn-default product-button');
        $(this).attr('class', 'btn btn-xs btn-primary product-button');
        filtered = true;
      } else {
        $('.product-carousel').slickUnfilter();
        $('.product-button').attr('class', 'btn btn-xs btn-primary product-button');    
        filtered = false;
      }
    });
    

    This initiates the Slick slider, then listens for a click on the #button-apple. I'm using the built-in slickFilter method and then a bit of styling on the buttons to visually show that button has been selected. But as you've probably realised, creating a new Javascript function for every vendor is horribly inefficient. Is there a way for the function to know enough about what you've just clicked on for it to use the same function regardless of which one you clicked? Also, the method of setting the var filtered is also a bit flawed since clicking another vendor will (currently) just unfilter rather than unfilter then re-filter to that vendor - so the function ought to know whether the vendor button you've clicked on is already filtered and act on that.

    Supplementary question for anyone who knows slick - is there a way to centre all the items in the slider area when there are less than the number of slidesToShow?

    http://jsfiddle.net/8vLs9qp6/