Search code examples
javascriptjquerybxslider

bx slider with custom pager having issues moving between slides on hover


So, I'm using the bx slider plugin for a custom slideshow. I made a custom pager because the requirements are for the slideshow to be in the center of several blocks of content which will act as the pager, and I need to have the items on different sides of the slideshow. The slideshow will auto rotate until a user hover's over a content block, which will move to and freeze the slide on the one related to that item.

Prototype: https://codepen.io/Denzy/pen/OqBXxq

I almost have it working. In my example above, it works briefly but if I move my mouse quickly between items the whole thing freezes up. If I change the pager's 'on' event to be 'click' everything works as intended, but I need it to be when you hover over an item, not click. This leads me to believe that the problem has something to do with hovering over a different item before the slider finishes moving from the first item, and things get broken.

My current mouse events look like this:

$('#slide-container .pager-list a').on('mouseenter', function() {
    slider.goToSlide(this.getAttribute('data-slide-index'));
    slider.stopAuto();
});

$('#slide-container .pager-list a').on('mouseleave', function() {
    slider.startAuto();
});

*Edit: Rest of the jQuery:

var slider = $('.bxslider').bxSlider({
    pagerCustom: '#slide-container',
    slideWidth: 400,
    controls: false,
    auto: true,
    autoHover: true,
    pause: 2000
});

slider.bxSlider();

If that is the issue, what can I do to prevent the slide from moving until the first sliding action is complete?


Solution

  • Relevant Changes

    1. Remove extra instantiation of .bxSlider(), you only need one on ul.bxslider

    2. Remove pagerCustom option because it will expect the links to be clicked (which OP request that behavior to be excluded explicitly).

    3. Add pager: false. We will rely on jQuery event delegation to invoke bxSlider methods.

    4. Narrow down the selectors for mouse events:

         $('.pager').on(MOUSEEVENT, 'a', function() {...
      
    5. Change mouseenter event to mouseover event. mouseenter only covers when mouse crosses over an element border, while mouseover covers the border crossing and the duration in which the pointer is within said element.

    6. Change:

        ...(this.getAttribute('data-slide-index')) // Result is a String ex. "1"<br>
      

      to:

        ...($(this).data('slide-index')) // Result is a Number ex. 1
      

    Optional Changes

    1. Each link href attribute value is set to #/ which prevents <a> jumping behavior.

    2. Each <img> URL parameter for text has been changed to this pattern:

       &text=Slide%20N
      

      %20 = a space and N = a number 1 to 6


    Demo

    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset='utf-8'>
      <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet">
      <link href="https://cdnjs.cloudflare.com/ajax/libs/bxslider/4.2.15/jquery.bxslider.min.css" rel="stylesheet">
      <style>
        ul {
          list-style: none;
        }
        
        li {
          padding: 20px 0;
        }
        
        .active {
          color: red;
        }
        
        a {
          color: #fff;
          padding: 10px;
          background-color: #64758a;
        }
        
        a:hover {
          color: red;
        }
      </style>
    </head>
    
    <body>
      <main class="slide-container">
        <ul class="pager">
          <li> <a data-slide-index="0" href="#/">Slide 1</a>
          </li>
          <li> <a data-slide-index="1" href="#/">Slide 2</a>
          </li>
          <li> <a data-slide-index="2" href="#/">Slide 3</a>
          </li>
        </ul>
        <ul class="bxslider">
          <li>
            <img src="http://placehold.it/800x250/5E7074/FFFFFF&text=Slide%201" />
          </li>
          <li>
            <img src="http://placehold.it/800x250/5E7074/FFFFFF&text=Slide%202" />
          </li>
          <li>
            <img src="http://placehold.it/800x250/5E7074/FFFFFF&text=Slide%203" />
          </li>
          <li>
            <img src="http://placehold.it/800x250/5E7074/FFFFFF&text=Slide%204" />
          </li>
          <li>
            <img src="http://placehold.it/800x250/5E7074/FFFFFF&text=Slide%205" />
          </li>
          <li>
            <img src="http://placehold.it/800x250/5E7074/FFFFFF&text=Slide%206" />
          </li>
        </ul>
        <ul class="pager">
          <li> <a data-slide-index="3" href="#/">Slide 4</a>
          </li>
          <li> <a data-slide-index="4" href="#/">Slide 5</a>
          </li>
          <li> <a data-slide-index="5" href="#/">Slide 6</a>
          </li>
        </ul>
      </main>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/js/bootstrap.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/bxslider/4.2.15/jquery.bxslider.min.js"></script>
      <script>
        var slider = $('.bxslider').bxSlider({
          slideWidth: 400,
          controls: false,
          auto: true, //should be set to true
          autoHover: true,
          pause: 2000,
          pager: false
        });
    
        $('.pager').on('mouseover', 'a', function() {
          slider.goToSlide($(this).data('slide-index'));
          slider.stopAuto();
        });
    
        $('.pager').on('mouseleave', 'a', function() {
          slider.startAuto();
        });
      </script>
    </body>
    
    </html>