BX Slider doesn't show when opened in Foundation reveal?

605 Views Asked by At

Basically, I have a BX Slider that will show up on a pop-up via Zurb Foundation's reveal. However, when I click on a button to show the modal (with the bx slider inside it), it doesn't show up. The weird thing is, when I resize the window, the carousel suddenly appears.

Modal Trigger Button:

<a class="button" data-open="modal-product-detail">Show Modal</a>

Modal HTML:

<div class="reveal" id="modal-product-detail" data-reveal>

              <ul class="bxslider">
                <li class="">

                    <img src="images/img_product_popup_detail.jpg">

                </li>
                <li class="">

                    <img src="images/img_product_popup_detail.jpg">

                </li>
                <li class="">

                    <img src="images/img_product_popup_detail.jpg">

                </li>
              </ul>

              <button class="reveal-close" data-close aria-label="Close modal" type="button">
              </button>

JS code:

$(document).ready(function(){

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

});

Here's a simulation of the problem:

Think it has something to do with the modal being hidden initially.

https://jsfiddle.net/5s6nowaq/

2

There are 2 best solutions below

0
On BEST ANSWER

The Bx-slider needs to be instantiated,after the modal dialog is shown.

Currently your instantiating bx-slider on document.ready(), but since modal dialog is hidden, it is getting destroyed. so when the modal dialog is shown again, bx-slider does not come up on screen.

JS code:

$(document).ready(function() {
   //$(".modal1").hide();

   $(".sampleclick").on('click', function() {
     $(".modal1").show();
     $('.bxslider').bxSlider({
        auto: true,
        controls: false,
        pager: false
     });
    });
  });

CSS code:

.modal1 {
   display: none;
 }

Working Demo @ JSFiddle

There are couple of other changes which I have done in your code Note:

  • Always place all the jQuery related code inside document.ready(), so that you don't get any surprises before your page is loaded completely on screen.
  • When hiding elements/images on page during initial load, better to do it using CSS than using JS/jQuery code, as you would see the images appear and then disappear on screen.
2
On

Think it has something to do with the modal being hidden initially.

You are correct. Timing during load is critical and it's moreso with bxSlider as it does it's calculations before DOM is even ready (an observation, don't know for sure, but that would explain why bxSlider may end up with a partial height at times). Although bxSlider seems to be destroyed having been instantiated into a modal that yet exists, it is there but it's calculations are based on it's current content which at the time of DOMReady is null...undefined...0? Whatever it is at that time, we can all agree it's not what we expect.

Using only the bxSlider API and JavaScript/jQuery there are 3 possible ways we can rectify this problem:

  1. There is a poorly documented method called .redrawSlider(). This method has a specific use case as to when bxSlider is hidden, the redrawSlider() method will redraw after bxSlider is unhidden. This method will resize the viewport which triggers a reflow (which is all we need most of the time), but from that reflow, it calculates height and neglects width. This is ok as long as the content isn't a block element. Perhaps this method will work in version 5 or better yet have the height bug fixed.
  2. Cause a reflow thereby forcing bxSlider to recalculate viewport. A reflow needs to be guided in this circumstance since bxSlider does not recalculate everything on every reflow. Changing the height of .bx-viewport and/or .bx-wrapper usually works. If not, we could use a callback onSliderResize.
  3. We can re-instantiate bxSlider as @dreamweiver had suggested when bxSlider emerges from display:none state to display:{ANYTHING OTHER THAN NONE}. bxSlider API has a method .reloadSlider() that , you guessed it reloads bxSlider.

The following Snippet uses the 3rd option, review it in Full page mode and test it's responsiveness by resizing the browser.

SNIPPET

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1, user-scalable=no">
  <title>00A00</title>
  <link href='https://cdn.jsdelivr.net/bxslider/4.2.5/jquery.bxslider.css' rel='stylesheet'>
  <style>
    html,
    body {
      height: 100%;
      width: 100%;
      background: #111;
      color: #eee;
      font: 400 16px/1.428 Verdana;
    }
    main {
      padding: 4em;
    }
    .bx-wrapper {
      background: none;
    }
    img {
      margin: 0 auto;
      display: block;
    }
    section.off {
      display: none;
    }
    section.on {
      display: block;
    }
    button {
      display: inline-block;
      border-radius: 4px;
      border: 1px solid cyan;
      line-height: 1.2;
      font-size: 1.25rem;
    }
    button.off {
      color: cyan;
      background: none;
    }
    button.off::before {
      content: 'Reveal ';
    }
    button.on {
      color: black;
      background: cyan;
    }
    button.on::before {
      content: 'Conceal ';
    }
  </style>
</head>

<body>
  <main>
    <button id="btn1" class="off">BX</button>

    <section id='sec1' class="off">

      <ul class="bxslider">
        <li class='slide'>
          <img src='https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png'>
        </li>
        <li class='slide'>
          <img src='https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png'>
        </li>
        <li class='slide'>
          <img src='https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png'>
        </li>
        <li class='slide'>
          <img src='https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png'>
        </li>
        <li class='slide'>
          <img src='https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png'>
        </li>
      </ul>

    </section>
  </main>
  <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.5/jquery.bxslider.min.js'></script>
  <script>
    $(function() {
      var bx = $('.bxslider').bxSlider({
        pager: false
      });

      /*  This part is optional...
      |...If you want to change your...
      |...options during reload...
      |
      */ // 1. Create an object literal
      /*ex: var cfg = {pager:false};
       */
      //// 2. Pass this object:
      /*ex: bx.reloadSlider(cfg)
       */
      // Follow the directions with 

      /* Add a '/' to the beginning of this line
      var cfg = {
        mode: 'vertical',
        maxSlides: 2,
        minSlides: 2,
        shrinkItems: true,
        pager:false
      };
      //*/

      $('#btn1').on('click', function() {
        $(this).toggleClass('on off');
        $('#sec1').toggleClass('on off');
        /* Add a '/' at strat of line
        bx.reloadSlider(cfg);
        //*/
        //* Remove the first '/' of line
        bx.reloadSlider();
        //*/
      });
    });
  </script>
</body>

</html>

As a bonus, I have added a demonstration of how to use the .reloadSlider() method to change options on the fly.