danik
danik

Reputation: 191

Bxslider not appearing in tab

I have accordion tabs on my website and I am trying to use bxslider within them for my slides. The issue is that when the slides open up it shows the slider as having a height of 0.

I have tried using the reload function given by bxslider but it keeps telling me it is not a function - I may be doing something wrong.

I have also tried to add a static height to the viewport but that just messes up the images. I have created a JSFiddle

$(document).ready(function(){  
    $('.bxslider').bxSlider({
        auto: 'true',
        pager: 'false',
    });

    $('#accordion').find('.accordion-toggle').click(function (){
        $(this).parent().toggleClass('active');
        //Hide the other panels
        $('#accordion section').not($(this).parent()).removeClass('active');
    });
});

Note: I manually copy pasted the scripts and CSS for bxslider into the JSFiddle because I was unable to figure out how to add them without doing so. My script can be found below the bxslider script

Upvotes: 3

Views: 3554

Answers (2)

zer00ne
zer00ne

Reputation: 43910

This issue is resolved by using the redrawSlider() method. It is specifically for when bxSlider is unhidden. It requires a repaint. This is only documented here. Unfortunately, it's usage seems inaccurate, so I came up with something that actually works very well.

I placed anchors inside each of the .accordion-toggle and delegated a click event on the anchors. Originally, I tried to place the method within the accordion's function, but it wasn't working. The redrawSlider() wasn't working at first and after a little research I found nothing...so I guessed that it must be the timing, BINGO!

Btw, I know it isn't documented, but if you have multiple sliders, each one must be uniquely referenced. So even if your sliders share a common class, add a unique class for each of them or an id is good also. Each slider should have it's own setup even if they are identical.

Also, Booleans are not Strings, and sometimes JavaScript auto type conversion doesn't always catch it. So be mindful when using true and false values and leave them unquoted. If quoted, it is technically a String.

$('a.trig1').on('click', function(e) {
    e.preventDefault();
    setTimeout(function() {
      bx1.redrawSlider();
    }, 0);
});

$('a.trig2').on('click', function(e) {
    e.preventDefault();
    setTimeout(function() {
      bx2.redrawSlider();
    }, 0);
}); 

SNIPPET

<!doctype html>
<html>

<head>
  <meta charset="utf-8">
  <title>Hidden bxSliders</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/bxslider/4.2.5/jquery.bxslider.css">
  <style>
    #accordion section .accordion-content {
      display: none;
      padding: 0 30px 30px 30px;
    }
    #accordion section.active .accordion-content {
      display: block;
    }
    .bx img {
      margin: 0 auto;
      display: block;
    }
  </style>
</head>

<body>
  <div id="accordion">
    <section>
      <h2 class="accordion-toggle"><a href="#" class="trig1">Test 1</a></h2>
      <div class="accordion-content">
        <p>slider 1</p>
        <ul class="bxslider1 bx">
          <li>
            <img src="http://ichef.bbci.co.uk/images/ic/640x360/p02scs5q.jpg">
          </li>
          <li>
            <img src="https://d2v9y0dukr6mq2.cloudfront.net/video/thumbnail/EhSddnV/black-and-white-tunnel-effect-turning-left-zoomed-video-background-for-a-transition-or-luma-key-spinning-left-tunnel-effect-zoomed-tunnel-hole-visual-effect_41rgnb8w__M0000.jpg">
          </li>
          <li>
            <img src="https://i.vimeocdn.com/video/541094548_640x360.jpg">
          </li>
        </ul>
      </div>
    </section>
    <section>
      <h2 class="accordion-toggle"><a href="#" class="trig2">Test 2</a></h2>
      <div class="accordion-content">
        <p>slider 2</p>
        <ul class="bxslider2 bx">
          <li>
            <img src="http://cache1.asset-cache.net/xd/513331420.jpg?v=1&c=IWSAsset&k=2&d=2DF30557A92EF68A79FB2FAE5DFF30DA4E7679DD01108BC64BBAD824103B0C3B9D10438B022685F4">
          </li>
          <li>
            <img src="http://www.rantsports.com/clubhouse/files/2015/03/Arianny-Celeste-7.jpg">
          </li>
          <li>
            <img src="http://breakingenergy.com/wp-content/uploads/sites/2/2013/04/72410727.jpg">
          </li>
        </ul>
      </div>
    </section>
  </div>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
  <script src="https://cdn.jsdelivr.net/bxslider/4.2.3/jquery.bxslider.min.js"></script>

  <script>
    var bx1 = $('.bxslider1').bxSlider({
      auto: true,
      pause: 2000,
      autoHover: true,
      pager: false
    });

    var bx2 = $('.bxslider2').bxSlider({
      auto: true,
      pause: 2000,
      autoHover: true,
      pager: false
    });

    $('a.trig1').on('click', function(e) {
      e.preventDefault();
      setTimeout(function() {
        bx1.redrawSlider();
      }, 0);
    });

    $('a.trig2').on('click', function(e) {
      e.preventDefault();
      setTimeout(function() {
        bx2.redrawSlider();
      }, 0);
    });


    $('.accordion-toggle').click(function(e) {
      e.preventDefault();
      $(this).parent().toggleClass('active');
      $('#accordion section').not($(this).parent()).removeClass('active');
    });
  </script>
</body>

</html>

Upvotes: 4

Mikey
Mikey

Reputation: 6766

According to this comment,

the bxSlider interface is only available on jQuery selectors that match a single element

Using his example, I came up with this solution.

$(function() {
  var bxConfig = {
    auto: 'true',
    pager: 'false'
  };

  // cache elements that we will be re-using
  var $accordion = $('#accordion'), 
      $sections = $accordion.find('section'),
      $sliders = [];

  // initialize sliders
  $('.bxslider').each(function (i) {
      $sliders[i] = $(this).bxSlider(bxConfig);
  });

  $accordion.find('.accordion-toggle').on('click', function() {
    var $current = $(this).closest('section');  
    // close other sections
    $sections.not($current).removeClass('active');
    // toggle current section
    $current.toggleClass('active');
    // check if section is active
    if ($current.hasClass('active')) {
      // get the position of the current section among his siblings
      var index = $sections.index($current);
      // reload slider at the given position
      $sliders[index].reloadSlider();
    }
  });
});

Here is a demo I shrunk the images just to make it easier to see.

I am using the index of the section to determine which slider to reload. Therefore, this solution will not work if you have 2 or more sliders within each section OR if not all sections have sliders. Another way is to loop through all sliders and reload them whenever you open a section -- but that's wasteful.

Upvotes: 1

Related Questions