12

I've built two kinds of functionality in controlling the slider that I've built. One is buttons with directional controls and other is touch/swipe events. How can sync both of them so that when i press prev/next the swipe events is also updated and vice versa

$(document).ready(function() {


 $('.prev').on('click', function(e) {
     event.stopPropagation();
     // store variable relevent to clicked slider
     var sliderWrapper      = $(this).closest('.slider-wrapper'),
      slideItems         = sliderWrapper.find('.slide-items'),
         slider             = sliderWrapper.find('.slider'),
         currentSlide       = sliderWrapper.attr('data-slide');

     // Check if data-slide attribute is greater than 0
     if( currentSlide > 0 ) {
   // Decremement current slide
   currentSlide--;
   // Assign CSS position to clicked slider
   slider.css({'right' : currentSlide*slideItems.outerWidth() });
   // Update data-slide attribute
   sliderWrapper.attr('data-slide', currentSlide);
     }
 });

 $('.next').on('click', function(e) {
     event.stopPropagation();
     // store variable relevent to clicked slider

  var sliderWrapper      = $(this).closest('.slider-wrapper'),
      slideItems         = sliderWrapper.find('.slide-items'),
      slider             = sliderWrapper.find('.slider'),
      totalSlides        = slideItems.length,
      currentSlide       = sliderWrapper.attr('data-slide');

  // Check if dataslide is less than the total slides
  if( currentSlide < totalSlides - 1 ) {
      // Increment current slide
      currentSlide++;
      // Assign CSS position to clicked slider
      slider.css({'right' : currentSlide*slideItems.outerWidth() });
      // Update data-slide attribute
      sliderWrapper.attr('data-slide', currentSlide);
  }
 })

 $('.slider-wrapper .slider').each(function(){

     // create a simple instance
     // by default, it only adds horizontal recognizers
  
     var direction;
        var touchSlider = this;
        var activeSlide = 0;
     var mc = new Hammer.Manager(this),
         itemLength = $(this).find('.slide-items').length,
         count = 0,
         slide = $(this);
     
  var sliderWrapper      = slide,
      slideItems         = sliderWrapper.find('.slide-items'),
      slider             = sliderWrapper.find('.slider'),
      totalSlides        = slideItems.length,
      currentSlide       = sliderWrapper.attr('data-slide');
     
     // mc.on("panleft panright", function(ev) {
     //   direction = ev.type;
     // });
        
        mc.add(new Hammer.Pan({ threshold: 0, pointers: 0 }))
     mc.on('pan', function(e) { 
            var percentage = 100 / totalSlides * e.deltaX / window.innerWidth;
            var transformPercentage = percentage - 100 / totalSlides * activeSlide;
            touchSlider.style.transform = 'translateX( ' +  transformPercentage + '% )';

   if( e.isFinal ) { // NEW: this only runs on event end
       if( percentage < 0 )
           goToSlide( activeSlide + 1 );
       else if( percentage > 0 )
           goToSlide( activeSlide - 1 );
       else
           goToSlide( activeSlide );
   }


     });


  var goToSlide = function( number ) {
    if( number < 0 )
      activeSlide = 0;
    else if( number > totalSlides - 1 )
      activeSlide = totalSlides - 1
    else
      activeSlide = number;

    touchSlider.classList.add('slide-animation');
    var percentage = -( 100 / totalSlides ) * activeSlide;
    touchSlider.style.transform = 'translateX( ' + percentage + '% )';
    timer = setTimeout( function() {
        touchSlider.classList.remove('slide-animation');
    }, 400);

  };

    //  mc.on("panend", function(ev) {
    //   if(direction === "panleft") {
    //          console.log('panleft');

    // // Check if dataslide is less than the total slides
    // if( currentSlide < totalSlides - 1 ) {
    //     // Increment current slide
    //     currentSlide++;
    //     // Assign CSS position to clicked slider
    //     slider.css({'right' : currentSlide*slideItems.outerWidth() });
    //     // Update data-slide attribute
    //     sliderWrapper.attr('data-slide', currentSlide);
    // }
    //   }

    //   if(direction === "panright") {
    //          console.log('right');

    //    // Check if data-slide attribute is greater than 0
    //    if( currentSlide > 0 ) {
    //  // Decremement current slide
    //  currentSlide--;
    //  // Assign CSS position to clicked slider
    //  slider.css({'right' : currentSlide*slideItems.outerWidth() });
    //  // Update data-slide attribute
    //  sliderWrapper.attr('data-slide', currentSlide);
    //    }
    //   }
    //  });
 });

});




$(window).on('load', function() {
  $('.slider-wrapper').each(function() {
    var slideItems = $(this).find('.slide-items'),
    items = slideItems.length,
    sliderBox = $(this).find('.slider'),
    sliderWrapperWidth = $(this).width();
    
    slideItems.outerWidth( sliderWrapperWidth );
    
    sliderBox.width( slideItems.outerWidth() * items  );
  });

});
/* http://meyerweb.com/eric/tools/css/reset/
 v2.0 | 20110126
 License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline; }

/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
  display: block; }

body {
  line-height: 1; }

ol, ul {
  list-style: none; }

blockquote, q {
  quotes: none; }

blockquote:before, blockquote:after,
q:before, q:after {
  content: '';
  content: none; }

table {
  border-collapse: collapse;
  border-spacing: 0; }

* {
  box-sizing: border-box; }

.container {
  max-width: 1280px;
  margin: 0 auto; }

.container .slider-wrapper {
  margin-bottom: 40px;
  background-color: grey;
  overflow: hidden;
  display: block; }

.container .slider-wrapper .slider {
  position: relative;
  right: 0;
  display: flex;
  flex-wrap: wrap;
  overflow: hidden;
  /*-webkit-transition : transform 0.3s linear;*/ }
  .container .slider-wrapper .slider.slide-animation {
    -webkit-transition: transform 0.3s linear; }

.container .slider-wrapper .slider > div {
  padding: 10px;
  background-color: #e5d0d0;
  height: 200px; }

.container .slider-wrapper .slider > div p {
  color: purple; }

.container .slider-wrapper .buttons {
  display: flex;
  justify-content: space-between;
  background: beige;
  padding: 10px 0; }

.container .slider-wrapper .buttons div {
  background-color: cyan; }

/*# sourceMappingURL=style.css.map */
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.7/hammer.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="slider-wrapper" data-slide="0">
    <div class="slider">
        <div class="slide-items">
            <p>1</p>
        </div>

        <div class="slide-items">
            <p>2</p>
        </div>

        <div class="slide-items">
            <p>3</p>
        </div>
    </div>
    <div class="buttons">
        <div class="prev">prev</div>
        <div class="next">next</div>
    </div>
  </div>
  <div class="slider-wrapper" data-slide="0">
    <div class="slider">
        <div class="slide-items">
            <p>1</p>
        </div>
    </div>
    <div class="buttons">
        <div class="prev">prev</div>
        <div class="next">next</div>
    </div>
  </div>

  <div class="slider-wrapper" data-slide="0">
    <div class="slider">
        <div class="slide-items">
            <p>2</p>
        </div>
        <div class="slide-items">
            <p>3</p>
        </div>
    </div>
    <div class="buttons">
        <div class="prev">prev</div>
        <div class="next">next</div>
    </div>
  </div>
  <div class="slider-wrapper" data-slide="0">
    <div class="slider">
        <div class="slide-items">
            <p>1</p>
        </div>
    </div>
    <div class="buttons">
        <div class="prev">prev</div>
        <div class="next">next</div>
    </div>
  </div>
  <div class="slider-wrapper" data-slide="0">
    <div class="slider">
        <div class="slide-items">
            <p>1</p>
        </div>

        <div class="slide-items">
            <p>2</p>
        </div>
    </div>
    <div class="buttons">
        <div class="prev">prev</div>
        <div class="next">next</div>
    </div>
  </div>
</div>
clestcruz
  • 1,081
  • 3
  • 31
  • 75

1 Answers1

4

You had multiple problems there:

  1. You used two different approaches for position the slide (the hammer plugin you used positioned it using translateX, while you tried to position using css right.
  2. Each method used different source to determine which slide is the active one (you used the attr of the .slider-wrapper while the hammer used the activeSlide variable.

I fixed both to use the translateX, moved the activeSlide variable outside the scope of the $('.slider-wrapper .slider').each function and made sure that every change will affect both variables.

Node that we can remove one of the variables and use only the attr value, but I will leave that for you :)

Here is the working snippet:

$(document).ready(function() {

    var activeSlide = 0;

    $('.prev').on('click', function(e) {
        event.stopPropagation();
        // store variable relevent to clicked slider
        var sliderWrapper = $(this).closest('.slider-wrapper'),
            slideItems = sliderWrapper.find('.slide-items'),
            totalSlides = slideItems.length,
            slider = sliderWrapper.find('.slider'),
            currentSlide = parseInt(sliderWrapper.attr('data-slide'));

        // Check if data-slide attribute is greater than 0
        if (currentSlide > 0) {
            // Decremement current slide
            currentSlide--;
            // Assign CSS position to clicked slider
            var transformPercentage = -1 * currentSlide / totalSlides * 100;
            slider.css('transform', 'translateX(' + transformPercentage + '% )');
            // Update data-slide attribute
            sliderWrapper.attr('data-slide', currentSlide);
            activeSlide = currentSlide;
        }
    });

    $('.next').on('click', function(e) {
        event.stopPropagation();
        // store variable relevent to clicked slider

        var sliderWrapper = $(this).closest('.slider-wrapper'),
            slideItems = sliderWrapper.find('.slide-items'),
            slider = sliderWrapper.find('.slider'),
            totalSlides = slideItems.length,
            currentSlide = parseInt(sliderWrapper.attr('data-slide'));

        // Check if dataslide is less than the total slides
        if (currentSlide < totalSlides - 1) {
            // Increment current slide
            currentSlide++;
            // Assign CSS position to clicked slider
            var transformPercentage = -1 * currentSlide / totalSlides * 100;
            slider.css('transform', 'translateX(' + transformPercentage + '% )');
            // Update data-slide attribute
            sliderWrapper.attr('data-slide', currentSlide);
            activeSlide = currentSlide;
        }
    })

    $('.slider-wrapper .slider').each(function() {

        // create a simple instance
        // by default, it only adds horizontal recognizers

        var direction;
        var touchSlider = this;
        var mc = new Hammer.Manager(this),
            itemLength = $(this).find('.slide-items').length,
            count = 0,
            slide = $(this);

        var sliderWrapper = slide,
            slideItems = sliderWrapper.find('.slide-items'),
            slider = sliderWrapper.find('.slider'),
            totalSlides = slideItems.length,
            currentSlide = parseInt(sliderWrapper.attr('data-slide'));

        // mc.on("panleft panright", function(ev) {
        //   direction = ev.type;
        // });

        mc.add(new Hammer.Pan({
            threshold: 0,
            pointers: 0
        }))
        mc.on('pan', function(e) {
            var percentage = 100 / totalSlides * e.deltaX / window.innerWidth;
            var transformPercentage = percentage - 100 / totalSlides * activeSlide;
            touchSlider.style.transform = 'translateX( ' + transformPercentage + '% )';
            var sliderWrapper = $(e.target).closest('.slider-wrapper')


            if (e.isFinal) { // NEW: this only runs on event end

                var newSlide = activeSlide;
                if (percentage < 0)
                    newSlide = activeSlide + 1;
                else if (percentage > 0)
                    newSlide = activeSlide - 1;
                goToSlide(newSlide, sliderWrapper);
            }
        });


        var goToSlide = function(number, sliderWrapper) {
            if (number < 0)
                activeSlide = 0;
            else if (number > totalSlides - 1)
                activeSlide = totalSlides - 1
            else
                activeSlide = number;

            sliderWrapper.attr('data-slide', activeSlide);

            touchSlider.classList.add('slide-animation');
            var percentage = -(100 / totalSlides) * activeSlide;
            touchSlider.style.transform = 'translateX( ' + percentage + '% )';
            timer = setTimeout(function() {
                touchSlider.classList.remove('slide-animation');
            }, 400);

        };

    });

});




$(window).on('load', function() {
    $('.slider-wrapper').each(function() {
        var slideItems = $(this).find('.slide-items'),
            items = slideItems.length,
            sliderBox = $(this).find('.slider'),
            sliderWrapperWidth = $(this).width();

        slideItems.outerWidth(sliderWrapperWidth);

        sliderBox.width(slideItems.outerWidth() * items);
    });

});
/* http://meyerweb.com/eric/tools/css/reset/
 v2.0 | 20110126
 License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline; }

/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
  display: block; }

body {
  line-height: 1; }

ol, ul {
  list-style: none; }

blockquote, q {
  quotes: none; }

blockquote:before, blockquote:after,
q:before, q:after {
  content: '';
  content: none; }

table {
  border-collapse: collapse;
  border-spacing: 0; }

* {
  box-sizing: border-box; }

.container {
  max-width: 1280px;
  margin: 0 auto; }

.container .slider-wrapper {
  margin-bottom: 40px;
  background-color: grey;
  overflow: hidden;
  display: block; }

.container .slider-wrapper .slider {
  position: relative;
  right: 0;
  display: flex;
  flex-wrap: wrap;
  overflow: hidden;
  /*-webkit-transition : transform 0.3s linear;*/ }
  .container .slider-wrapper .slider.slide-animation {
    -webkit-transition: transform 0.3s linear; }

.container .slider-wrapper .slider > div {
  padding: 10px;
  background-color: #e5d0d0;
  height: 200px; }

.container .slider-wrapper .slider > div p {
  color: purple; }

.container .slider-wrapper .buttons {
  display: flex;
  justify-content: space-between;
  background: beige;
  padding: 10px 0; }

.container .slider-wrapper .buttons div {
  background-color: cyan; }

/*# sourceMappingURL=style.css.map */
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.7/hammer.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
    <div class="slider-wrapper" data-slide="0">
        <div class="slider">
            <div class="slide-items">
                <p>1</p>
            </div>

            <div class="slide-items">
                <p>2</p>
            </div>

            <div class="slide-items">
                <p>3</p>
            </div>
        </div>
        <div class="buttons">
            <div class="prev">prev</div>
            <div class="next">next</div>
        </div>
    </div>
    <div class="slider-wrapper" data-slide="0">
        <div class="slider">
            <div class="slide-items">
                <p>1</p>
            </div>
        </div>
        <div class="buttons">
            <div class="prev">prev</div>
            <div class="next">next</div>
        </div>
    </div>

    <div class="slider-wrapper" data-slide="0">
        <div class="slider">
            <div class="slide-items">
                <p>2</p>
            </div>
            <div class="slide-items">
                <p>3</p>
            </div>
        </div>
        <div class="buttons">
            <div class="prev">prev</div>
            <div class="next">next</div>
        </div>
    </div>
    <div class="slider-wrapper" data-slide="0">
        <div class="slider">
            <div class="slide-items">
                <p>1</p>
            </div>
        </div>
        <div class="buttons">
            <div class="prev">prev</div>
            <div class="next">next</div>
        </div>
    </div>
    <div class="slider-wrapper" data-slide="0">
        <div class="slider">
            <div class="slide-items">
                <p>1</p>
            </div>

            <div class="slide-items">
                <p>2</p>
            </div>
        </div>
        <div class="buttons">
            <div class="prev">prev</div>
            <div class="next">next</div>
        </div>
    </div>
</div>
Dekel
  • 60,707
  • 10
  • 101
  • 129