The nothing The nothing - 3 months ago 22
jQuery Question

Change .animate to .css and reset width

I've been looking for the solution to this problem for days without success, I hope your understanding.

I have this code slider image jquery:

https://jsfiddle.net/87ucvsn6/2/

Javascript:

jQuery(document).ready(function ($) {

var slideCount = $('#slider ul li').length;
var slideWidth = $('#slider ul li').width();
var slideHeight = $('#slider ul li').height();
var sliderUlTotal = slideCount * slideWidth;

$('#slider').css({ width: slideWidth, height: slideHeight });

$('#slider ul').css({ width: sliderUlTotal, marginLeft: - slideWidth });

$('#slider ul li:last-child').prependTo('#slider ul');

function toLeft() {
$('#slider ul').animate({
left: + slideWidth
}, 200, function () {
$('#slider ul li:last-child').prependTo('#slider ul');
$('#slider ul').css('left', '');
});
};

function toRight() {
$('#slider ul').animate({
left: - slideWidth
}, 200, function () {
$('#slider ul li:first-child').appendTo('#slider ul');
$('#slider ul').css('left', '');
});
};

$('a.prev').click(function () {
toLeft();
});

$('a.next').click(function () {
toRight();
});

});


I know how all work but I want to change .animate to .css
like this:

function toRight() {
$('#slider ul').animate({
left: - slideWidth
}, 200, function () {
$('#slider ul li:first-child').appendTo('#slider ul');
$('#slider ul').css('left', '');
});
};


To:

function toRight() {
$('#slider ul').css({
left: - slideWidth
}, 200, function () {
$('#slider ul li:first-child').appendTo('#slider ul');
$('#slider ul').css('left', '');
$('#slider ul').addClass('selected');
});
};


But this not work, I think the problem is here:

$('#slider ul').css( {left: - imgWidth});
$('#slider ul').css('left', '');


I have done this before with other slider, but that slider not have infinite loop, that slider go from last slider to first slider, but this slider is infinite and not work why prependTo and appendto.

I want to width reset after click to 0 but not change the position of slider, like .animate

My goal is use different transition css3 with:

$('#slider ul').addClass('selected');
.selected{
transition:all 1.0s ease-in-out;
}


┬┐how can i do that ?

Thanks for reading

Answer

You can change your toLeft and toRight functions to:

function toLeft() {
    $('#slider ul').css({
        left: +slideWidth
    })
    $('#slider ul li:last-child').prependTo('#slider ul');
    $('#slider ul').css('left', '');
};

function toRight() {
    $('#slider ul').css({
        left: -slideWidth
    })
    $('#slider ul li:first-child').appendTo('#slider ul');
    $('#slider ul').css('left', '');
};

However there is no easy way in jQuery to know when the transition was done. For that you will have to listen to more events:

$("#el").bind("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function(){ ... });

(was taken from this question).

The problem with transition is that with any change that you do - that animation will happen, you you will have an infinite loop of transitions (or wrong calculations).

In order to overcome this issue you will have to "unset" the animation between changes to the element, and once the change is done - add the transition again.
Here you come into another problem - you might get into race condition between dom/css changes and the fact that you add/remove the transition from the element.

I overcome all of the above using a class that removes the transiation completely and the setTimeout function to make sure the call for removing that class is called a bit after the css/dom changes are done.

Here is the final snippet:

jQuery(document).ready(function($) {
  var lastAction;
  var slideCount = $('#slider ul li').length;
  var slideWidth = $('#slider ul li').width();
  var slideHeight = $('#slider ul li').height();
  var sliderUlTotal = slideCount * slideWidth;

  $('#slider').css({
    width: slideWidth,
    height: slideHeight
  });

  $('#slider ul').css({
    width: sliderUlTotal,
    marginLeft: -slideWidth
  })

  $('#slider ul li:last-child').prependTo('#slider ul');
  
  function toLeft() {
    $('#slider ul').css({
        marginLeft: 0
    })
    lastAction = 'left';
  };

  function toRight() {
    $('#slider ul').css({
        marginLeft: -slideWidth*2
    })
    lastAction = 'right';
  };

  $("#slider ul").bind("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function(){
    if (lastAction == 'left') {
      $('#slider ul').addClass('notrans')
  	  $('#slider ul li:last-child').prependTo('#slider ul');
      $('#slider ul').css({marginLeft: -500})
      setTimeout(
        function() {
          $('#slider ul').removeClass('notrans')
        }, 1);
    } else if (lastAction == 'right') {
      $('#slider ul').addClass('notrans')
    	$('#slider ul li:first-child').appendTo('#slider ul');
      $('#slider ul').css({marginLeft: -500})
      setTimeout(
        function() {
          $('#slider ul').removeClass('notrans')
        }, 1);
    }
  });

  $('a.prev').click(function() {
    toLeft();
  });

  $('a.next').click(function() {
    toRight();
  });
});
html {
  background: #0d1b73;
  color: #2a2a2a;
}

html,
body {
  margin: 0;
  padding: 0;
}

#slider {
  position: relative;
  overflow: hidden;
  margin: 20px auto 0 auto;
  border-radius: 4px;
}

#slider ul {
  position: absolute;
  margin: 0;
  padding: 0;
  height: 200px;
  list-style: none;
}

#slider ul li {
  position: relative;
  display: block;
  float: left;
  margin: 0;
  padding: 0;
  width: 500px;
  height: 300px;
  background: #ccc;
  text-align: center;
  line-height: 300px;
}

a.prev,
a.next {
  position: absolute;
  top: 40%;
  z-index: 999;
  display: block;
  padding: 4% 3%;
  width: auto;
  height: auto;
  background: #2a2a2a;
  color: #fff;
  text-decoration: none;
  font-weight: 600;
  font-size: 18px;
  opacity: 0.8;
  cursor: pointer;
}

a.prev:hover,
a.next:hover {
  opacity: 1;
  -webkit-transition: all 0.2s ease;
}

a.prev {
  border-radius: 0 2px 2px 0;
}

a.next {
  right: 0;
  border-radius: 2px 0 0 2px;
}

.slider_option {
  position: relative;
  margin: 10px auto;
  width: 160px;
  font-size: 18px;
}
#slider ul {
  transition:all 1.0s ease-in-out;
}
#slider ul.notrans {
  transition: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="slider">
  <a href="#" class="next">&gt;&gt;</a>
  <a href="#" class="prev">
    &lt;&lt;</a>
      <ul>
        <li>SLIDE 1</li>
        <li style="background: #e6e2df;">SLIDE 2</li>
        <li>SLIDE 3</li>
        <li style="background: #e6e2df;">SLIDE 4</li>
      </ul>
</div>