Reload Owl Carousel 2 when side navigation opens or closes

Ishio picture Ishio · Apr 12, 2017 · Viewed 7.6k times · Source

I am working on a website, and it is built off a theme. In the body of the site is structured to have a left-panel div which houses the navigation and a right-panel div which houses the body content.

When the left-panel opens from a collapsed view (showing only icons) to the full view (showing the nav text), owl-carousel, since it's loaded on page load, doesn't readjust the width.

I've tried a few methods to try and reload the carousel, following their API, but am not successful. The body doesn't have a set width, such as inline styles, but instead the class left-menu-open is set, when the left menu is open.

I've also looked at several other cases of people trying to do the same thing, but none of their code examples work.

Below is my code. I am running this in a .php file, so I am able to load multiple sliders in the body content, without them rotating in relation. The carousel loads and functions fine, it's just that it begins to clip if the page is loaded with the nav open and one closes the nav, or the 3rd slide shows if the page is loaded with the nav closed and is opened.

One method I've tried is

if ( $( 'body' ).resize() { }

if ( $( 'body' ).hasClass( 'left-nav-open' ) { } else if ( !$( 'body ').resize() { }

(function($) {
  $(function() {
    var $owl = $('.owl-<?php echo $owl_widget_title; ?>');

    $owl.owlCarousel({
      // your initial option here, again.
      loop:true,
      nav:true,
      navText: ["<i class=\"fa fa-chevron-left\"></i>","<i class=\"fa fa-chevron-right\"></i>"],
      dots: false,
      lazyLoad: true,
      lazyContent: true,
      autoplaySpeed: 1000,
      autoplayTimeout: 7000,
      autoplayHoverPause: true,
      responsive : {
        0 : {
          items: 1,
          slideBy: 1,
          autoHeight:true,
        },
        992 : {
          items: <?php echo $num_of_items; ?>,
          slideBy: <?php echo $num_of_items; ?>,
        }
      }
    });

  });

})(jQuery)

I've tried destroy.owl.carousel, and then initialize.owl.carousel but neither of those seem to work or run at all.

Any and all help is appreciated! Thank you

Answer

tao picture tao · Apr 26, 2017

To update owl after resize of container one would need to call .onResize() _handler on its data. The updateOwl() function should look like this:

updateOwl = function(){
  $(".owl-carousel").each(function() {
    $(this).data('owl.carousel').onResize();
  });
};

The only thing to watch for is when exactly to call this function. I assume the sidebar is not jumping into position, but rather smoothly animating. The call to .onResize() needs to be delayed by the duration of animation, so the size of the carousel is calculated based on final content size. Delay the execution of updateOwl() by wrapping it into a setTimeout() (equal or slightly longer than the sidebar animation duration):

$(document).on('click', '.sidebarToggle', function(){
  setTimeout(function(){
    updateOwl();        
  },   321)
});

...where .sidebarToggle would be your sidebar opener.

Working example:

(function($) {
  var $owl = $('.owl-carousel'),
      updateOwl = function(){
        $owl.each(function() {
          $(this).data('owl.carousel').onResize();
        });
      };
  
  $owl.owlCarousel({
    loop: true,
    nav: true,
    navText: ['<i class="fa fa-chevron-left"></i>', '<i class="fa fa-chevron-right"></i>'],
    dots: false,
    lazyLoad: true,
    autoplaySpeed: 1000,
    autoplayTimeout: 7000,
    autoplayHoverPause: true,
    responsive: {
      0: {
        items: 1,
        slideBy: 1,
        autoHeight: true,
      },
      992: {
        items: 3,
        slideBy: 3,
      }
    }
  });
  
  $(document).on('click', '.sidebarToggle', function(){
    $('body').toggleClass('sidebarOpen'); 
    setTimeout(function(){
      updateOwl();        
    }, 321)
  });

  $(window).on('resize', updateOwl); 
  
})(jQuery)
body {
  margin: 0;
  transition: padding-left .3s cubic-bezier(.4,0,.2,1);
  }
.sidebar {
  height: 100vh;
  position: absolute;
  width: 200px;
  background-color: #888;
  left: -200px;
  top:0;
  transition: left .3s cubic-bezier(.4,0,.2,1);
  box-sizing: border-box;
}
.sidebarOpen .sidebar {
  left: 0;
}

body.sidebarOpen {
  padding-left: 200px;
}
.owl-carousel .owl-item {
  padding: 0 45px;
  box-sizing: border-box;
}
.owl-carousel .owl-item > div{
  min-height: 135px;
  width: 100%;
  border: 1px solid #ccc;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: Gainsboro;
  border-radius: 3px;
}
button {
  margin: 15px;
}
.owl-carousel {
  position: relative;
  margin: 15px 0 0;
}
.owl-nav >div {
  position: absolute;
  top: 50%;
  width: 20px;
  transform: translate(-50%, -50%);
  text-align: center;
}
.owl-prev {left: 20px}
.owl-next {left: calc(100% - 20px);}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.2.1/assets/owl.carousel.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.2.1/assets/owl.theme.default.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.2.1/owl.carousel.min.js"></script>


<div class="sidebar"></div>

<div class="owl-carousel">
  <div> Your Content </div>
  <div> Your Content </div>
  <div> Your Content </div>
  <div> Your Content </div>
  <div> Your Content </div>
  <div> Your Content </div>
  <div> Your Content </div>
</div>
<button class="sidebarToggle">SidebarToggle</button>

If the above is not working for you, I'll need to have a look at your implementation to be able to debug it.

Side note: lazyContent is currently unavailable. According to plugin author:

...lazyContent was introduced during beta tests but i removed it from the final release due to bad implementation. It is a nice options so i will work on it in the nearest feature.