Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sync directional controls with swipe events

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>
like image 630
clestcruz Avatar asked Jul 06 '17 00:07

clestcruz


1 Answers

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>
like image 137
Dekel Avatar answered Nov 08 '22 12:11

Dekel