Cómo solucionar la incompatibilidad del display:none con jCarousel

El otro día desarrollando la web para un cliente me topé con una incompatibilidad que no conocía con la popular librería para crear carruseles jCarousel. Os explico el proceso. Quería implementar una paginación inline mediante la ocultación de elementos. Es decir, mostraba cuatro elementos y cuando el usuario pulsará el botón “Ver más” se mostrarían otros cuatro, y así sucesivamente. Oculté dichos elementos con el ya clásico display:none de CSS. Cual fue mi sorpresa que, cuando hice estos carruseles ocultos otra vez visibles vi que la funcionalidad de carrusel se había perdido. Resumiendo, cada vez que quitaba el display:none de los elementos, estos no volvían a contar con la función que les otorgaba jCarousel.

Tras investigar y tras realizar unas cuantas pruebas pude dar con lo que estaba sucediendo. Y es que el problema no estaba en el display:none en sí (hice pruebas con la propiedad visibility de CSS e incluso metiendo dichos elementos en un wrapper), si no en que se debe recargar el elemento jCarousel cada vez que lo hacemos visible. Para ello incluso existe una función que te permite recargar el elemento.

Para que lo entendáis mejor vamos con un contexto claro. Este sería el código del markup de nuestro elemento. He puesto el CSS como parámetro del HTML para que sea más explicativo.

<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/jquery.jcarousel.min.js"></script>
<div class="jcarousel-wrapper" id="jcarousel-wrapper" class="display:none;">
  <a href="#" class="jcarousel-control-prev"><</a>
  <div class="jcarousel" id="jcarousel-demo">
    <ul>
        
        <li class="item">
          <h3>Elemento 1</h3>
        </li>

        <li class="item">
          <h3>Elemento 2</h3>
        </li>

        <li class="item">
          <h3>Elemento 3</h3>
        </li>

        <li class="item">
          <h3>Elemento 4</h3>
        </li>

        <li class="item">
          <h3>Elemento 5</h3>
        </li>

    </ul>
  </div>
  <a href="#" class="jcarousel-control-next">></a>
</div>

<span onclick="showCarousel()" id="btnshow" class="btn">Ver mas</span>

<script>
  //Inicializamos nuestro carrusel
  var jcarouseldemo = $('#jcarousel-demo');
  jcarouseldemo
    .on('jcarousel:reload jcarousel:create', function () {
        var carousel = $(this),
            width = carousel.innerWidth();

        if (width >= 600) {
            width = width / 4;
        } else if (width >= 350) {
            width = width / 1;
        }

        carousel.jcarousel('items').css('width', Math.ceil(width) + 'px');
    })
    .jcarousel({
        wrap: 'circular'
    });

  $('.jcarousel-control-prev')
    .jcarouselControl({
        target: '-=1'
    });

  $('.jcarousel-control-next')
    .jcarouselControl({
        target: '+=1'
    });

  //Función para mostrar el carrusel
  function showCarousel(){
    if (document.getElementById('jcarousel-wrapper')){
      document.getElementById('jcarousel-wrapper').style.display = '';
    }
  }
</script>

Si dejamos esto así, verás que al hacer visible el carrusel no funciona. Es decir, se muestran los elementos y tal pero no cuenta con la típica función de carrusel en la que puedes pasar los elementos que la integran a placer mediante las flechas.

Como he comentado antes, para que funcione el carrusel de jCarousel hay que volver a recargar el elemento mediante el método reload de la librería. Por lo tanto, habría que añadir en la función showCarousel(), debajo de la línea document.getElementById('jcarousel-wrapper').style.display = ''; este código:

jcarouseldemo.jcarousel('reload');

El código completo sería este:

<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/jquery.jcarousel.min.js"></script>
<div class="jcarousel-wrapper" id="jcarousel-wrapper" class="display:none;">
  <a href="#" class="jcarousel-control-prev"><</a>
  <div class="jcarousel" id="jcarousel-demo">
    <ul>
        
        <li class="item">
          <h3>Elemento 1</h3>
        </li>

        <li class="item">
          <h3>Elemento 2</h3>
        </li>

        <li class="item">
          <h3>Elemento 3</h3>
        </li>

        <li class="item">
          <h3>Elemento 4</h3>
        </li>

        <li class="item">
          <h3>Elemento 5</h3>
        </li>

    </ul>
  </div>
  <a href="#" class="jcarousel-control-next">></a>
</div>

<span onclick="showCarousel()" id="btnshow" class="btn">Ver mas</span>

<script>
  //Inicializamos nuestro carrusel
  var jcarouseldemo = $('#jcarousel-demo');
  jcarouseldemo
    .on('jcarousel:reload jcarousel:create', function () {
        var carousel = $(this),
            width = carousel.innerWidth();

        if (width >= 600) {
            width = width / 4;
        } else if (width >= 350) {
            width = width / 1;
        }

        carousel.jcarousel('items').css('width', Math.ceil(width) + 'px');
    })
    .jcarousel({
        wrap: 'circular'
    });

  $('.jcarousel-control-prev')
    .jcarouselControl({
        target: '-=1'
    });

  $('.jcarousel-control-next')
    .jcarouselControl({
        target: '+=1'
    });

  //Función para mostrar el carrusel
  function showCarousel(){
    if (document.getElementById('jcarousel-wrapper')){
      document.getElementById('jcarousel-wrapper').style.display = '';
      jcarouseldemo.jcarousel('reload');
    }
  }
</script>

Ya sabéis, si alguna vez tenéis problemas al hacer visible un carrusel de jCarousel mediante display:none, recordad que debéis recargarlo.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP