0

I'm having trouble repositioning elements that sometimes should have transitions, sometimes not.

The actions works fine isolated but the view doesn't seem to update half-way in the combined action. What's the solution?

$(document).ready(function() {
  $('#goLeft').on('click',function() {
    $('#box').removeClass('soft');
    $('#box').css('left','300px');
  });
  $('#goRight').on('click',function() {
    $('#box').addClass('soft');
    $('#box').css('left','400px');
  });
  $('#goLeftAndRight').on('click',function() {
    //copy
    $('#box').removeClass('soft');
    $('#box').css('left','300px');
    //Need for timeout?
    //copy
    $('#box').addClass('soft');
    $('#box').css('left','400px');    
  });
});
h2 {
  cursor:pointer;
}

#box {
  position: fixed;
  top:100px;
  left:400px;
  height:100px;
  width:100px;
  background-color:#358;
}

#box p {
  padding:5px;
  color:#fff;
  text-align:center;
}

.soft {
  transition: all 0.3s ease-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
  <body>
    <h2 id="goLeft">jump left</h2>
    <h2 id="goRight">slide right</h2>
    <h2 id="goLeftAndRight">jump left and slide right</h2>
    <div id="box"><p>use headers to move</div>
  </body>
</html>
      
Teson
  • 6,644
  • 8
  • 46
  • 69

7 Answers7

2

There is 2 ways you can do it -

1# - Combining your function with CSS animation

$(document).ready(function() {
  $('#goLeft').on('click', function() {
    $('#box').removeClass('soft left-right');
    $('#box').css('left', '300px');
  });
  $('#goRight').on('click', function() {
    $('#box').addClass('soft').removeClass('left-right');
    $('#box').css('left', '400px');
  });
  $('#goLeftAndRight').on('click', function() {
    $('#box').addClass('left-right').removeClass('soft');
  });
});
h2 {
  cursor: pointer;
}

#box {
  position: fixed;
  top: 100px;
  left: 400px;
  height: 100px;
  width: 100px;
  background-color: #358;
}

#box p {
  padding: 5px;
  color: #fff;
  text-align: center;
}

.soft {
  transition: all 0.3s ease-out;
}
@keyframes leftRight{
  0%{left:300px}
  100%{left:400px}
}

.left-right{
  left:400px
  animation: leftRight 0.3s forwards ease-in-out;
  -webkit-animation: leftRight 0.3s forwards ease-in-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>

<body>
  <h2 id="goLeft">jump left</h2>
  <h2 id="goRight">slide right</h2>
  <h2 id="goLeftAndRight">jump left and slide right</h2>
  <div id="box">
    <p>use headers to move</div>
</body>

</html>

2# - Combining your function with setTimeout function.

$(document).ready(function() {
  $('#goLeft').on('click',function() {
    $('#box').removeClass('soft');
    $('#box').css('left','300px');
  });
  $('#goRight').on('click',function() {
    $('#box').addClass('soft');
    $('#box').css('left','400px');
  });
  $('#goLeftAndRight').on('click',function() {
    //copy
    $('#box').removeClass('soft');
    $('#box').css('left','300px');
     setTimeout(function() {
       $('#box').addClass('soft');
       $('#box').css('left','400px'); 
     }, 300);

       
  });
});
h2 {
  cursor:pointer;
}

#box {
  position: fixed;
  top:100px;
  left:400px;
  height:100px;
  width:100px;
  background-color:#358;
}

#box p {
  padding:5px;
  color:#fff;
  text-align:center;
}

.soft {
  transition: all 0.3s ease-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
  <body>
    <h2 id="goLeft">jump left</h2>
    <h2 id="goRight">slide right</h2>
    <h2 id="goLeftAndRight">jump left and slide right</h2>
    <div id="box"><p>use headers to move</div>
  </body>
</html>
Jithin Raj P R
  • 6,667
  • 8
  • 38
  • 69
2

You do not need jQuery for this setup.

If you write one CSS class which contains the .jump-left transition:

.jump-left {
transform: translateX(-100px);
}

and one CSS class which contains the .slide-right animation:

.slide-right {
animation: slide-right-animation 1s ease-out;
}

@keyframes slide-right-animation {
  0% {transform: translateX(-100px);}
100% {transform: translateX(0);}
}

you can use an onclick event listener to apply one class or the other - or one followed by the other.

Working Example:

var box = document.getElementsByClassName('box')[0];
var buttons = document.getElementsByTagName('button');

function buttonPress() {

    switch (true) {

        case (this.classList.contains('go-left')) :   
            box.setAttribute('class', 'box');
            box.classList.add('jump-left');
            break;
            
        case ((this.classList.contains('go-right')) && (box.classList.contains('jump-left'))) : 
            box.setAttribute('class', 'box');
            box.classList.add('slide-right');
            break;
        
        case (this.classList.contains('go-left-then-right')) :
            box.setAttribute('class', 'box');
            box.classList.add('jump-left');
            setTimeout(function(){
                box.classList.remove('jump-left');
                box.classList.add('slide-right');
            }, 300);
            break;
    }
}

for (var i = 0; i < buttons.length; i++) {
    buttons[i].addEventListener('click', buttonPress, false);
}
button {
cursor:pointer;
}

.box {
  position: fixed;
  top:50px;
  left:400px;
  height:100px;
  width:100px;
  background-color:#358;
}

.box p {
  padding:5px;
  color:#fff;
  text-align:center;
}

.jump-left {
transform: translateX(-100px);
}

.slide-right {
animation: slide-right-animation 1s ease-out;
}

@keyframes slide-right-animation {
  0% {transform: translateX(-100px);}
100% {transform: translateX(0);}
}
<button type="button" class="go-left">jump left</button>
<button type="button" class="go-right">slide right</button>
<button type="button" class="go-left-then-right">jump left and slide right</button>

<div class="box"><p>Use buttons to move.</p></div>
Rounin
  • 27,134
  • 9
  • 83
  • 108
1

Fixing the delay is quite simple. You just need to wrap the secondary part of your jump left and slide right function inside a setTimeout() function like this:

setTimeout(function(){
    $('#box').addClass('soft');
    $('#box').css('left','400px');
}, 100);

Below is a working snippet:

$(document).ready(function() {

  $('#goLeft').on('click',function() {
    $('#box').removeClass('soft').css('left','300px');
  });
  
  $('#goRight').on('click',function() {
    $('#box').addClass('soft').css('left','400px');
  });
  
  $('#goLeftAndRight').on('click',function() {
    $('#box').removeClass('soft').css('left','300px');
    
    //wait 100ms
    setTimeout(function(){
     $('#box').addClass('soft').css('left','400px');
    }, 100);
          
  });
});
h2 {
  cursor:pointer;
}

#box {
  position: fixed;
  top:100px;
  left:400px;
  height:100px;
  width:100px;
  background-color:#358;
}

#box p {
  padding:5px;
  color:#fff;
  text-align:center;
}

.soft {
  transition: all 0.3s ease-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
    <h2 id="goLeft">jump left</h2>
    <h2 id="goRight">slide right</h2>
    <h2 id="goLeftAndRight">jump left and slide right</h2>
    <div id="box"><p>use headers to move</div>
  </body>

EDIT:

Thanks to Mohammad for pointing out a simpler way to do the jQuery functions. I have adjusted the snippet above to show that.

Frits
  • 7,341
  • 10
  • 42
  • 60
  • Also you can shorten the code using chaining feature like `$('#box').addClass('soft').css('left','400px')` – Mohammad Aug 02 '17 at 09:32
  • @Mohammad Thanks! Will add that to the code snippet to showcase - thanks for pointing that out :) – Frits Aug 02 '17 at 09:33
1

add soft class by default and use timeout in leftright

$(document).ready(function() {
    $('#goLeft').on('click', function() {
        $('#box').css('left', '300px');
    });
    $('#goRight').on('click', function() {
        $('#box').css('left', '400px');
    });
    $('#goLeftAndRight').on('click', function() {
        //copy
        $('#box').css('left', '300px');
        setTimeout(function() {
            $('#box').css('left', '400px');
        }, 300);
        //Need for timeout?
        //copy
    });
});

h2 {
cursor:pointer;
}
#box {
position: fixed;
top:100px;
left:400px;
height:100px;
width:100px;
background-color:#358;
}
#box p {
padding:5px;
color:#fff;
text-align:center;
}
.soft {
transition: all 0.3s ease-out;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
   <body>
      <h2 id="goLeft">jump left</h2>
      <h2 id="goRight">slide right</h2>
      <h2 id="goLeftAndRight">jump left and slide right</h2>
      <div id="box" class="soft">
         <p>use headers to move
      </div>
   </body>
</html>

Refer this demo

MyTwoCents
  • 7,284
  • 3
  • 24
  • 52
0

Adding timeout of 100 ms is working fine.

Below is the code which i have used to recreate your mentioned scenario and tested.

<html>
<head>
<style>
h2 {
  cursor:pointer;
}

#box {
  position: fixed;
  top:100px;
  left:400px;
  height:100px;
  width:100px;
  background-color:#358;
}

#box p {
  padding:5px;
  color:#fff;
  text-align:center;
}

.soft {
  transition: all 0.3s ease-out;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
  $('#goLeft').on('click',function() {
    $('#box').removeClass('soft');
    $('#box').css('left','300px');
  });
  $('#goRight').on('click',function() {
    $('#box').addClass('soft');
    $('#box').css('left','400px');
  });
  $('#goLeftAndRight').on('click',function() {
    //copy
    $('#box').removeClass('soft');
    $('#box').css('left','300px');
    //Need for timeout?
    //copy
    setTimeout(function(){
       $('#box').addClass('soft');
       $('#box').css('left','400px'); 
    }, 100);

  });
});
</script>
</head>
  <body>
    <h2 id="goLeft">jump left</h2>
    <h2 id="goRight">slide right</h2>
    <h2 id="goLeftAndRight">jump left and slide right</h2>
    <div id="box"><p>use headers to move</div>
  </body>
</html>

Please mark it as an answer if it is as per your need.

amit wadhwani
  • 1,140
  • 1
  • 7
  • 12
0

$('#goLeftAndRight').on('click',function() {
  //that part actually sets the initial position
  $('#box').removeClass('soft');
  $('#box').css('left','300px');

  // see below
  setTimeout(function() {
    $('#box').addClass('soft');
    $('#box').css('left','400px'); 
  },0);
});

The setTimeout here just wait for the next browser available time

If you plan to do advanced animation with different cue points, you might be interested by something like https://greensock.com/timelinelite

Cyrille
  • 48
  • 1
  • 6
-1

addClass should be done when animation is starting.

$(document).ready(function() {
  $('#goLeft').on('click',function() {
    $('#box').removeClass('soft');
    $('#box').stop().animate({left:'300px'},{queue: false, duration:0});
  });
  $('#goRight').on('click',function() {
    $('#box').addClass('soft');
    $('#box').stop().animate({left:'400px'},{queue: false});
  });
  $('#goLeftAndRight').on('click',function() {
    //copy
    $('#box').removeClass('soft');
$('#box').stop().animate({left:'300px'}, { 
    queue: false, duration:0}).animate({left:'400px'},{ queue: false, start:
 function(){$('#box').addClass('soft'); } });


  });

});
h2 {
  cursor:pointer;
}

#box {
  position: fixed;
  top:100px;
  left:400px;
  height:100px;
  width:100px;
  background-color:#358;
}

#box p {
  padding:5px;
  color:#fff;
  text-align:center;
}

.soft {
  transition: all 0.3s ease-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
  <body>
    <h2 id="goLeft">jump left</h2>
    <h2 id="goRight">slide right</h2>
    <h2 id="goLeftAndRight">jump left and slide right</h2>
    <div id="box"><p>use headers to move</div>
  </body>
</html>
      
Anil
  • 3,722
  • 2
  • 24
  • 49
  • Question is about jumping left and slide right but your code slide left and then slide right. – Mohammad Aug 02 '17 at 09:37
  • @Teson. to make it jump use duration as 0 (as default is 400) and add the soft class in start function of animation. `start: function(){$('#box').addClass('soft'); }` – Anil Aug 02 '17 at 10:32