Reputation: 2134
I have a function that should scroll a user back to a search input at the top of the page, and then place focus on it (so the cursor is blinking). For some reason, it seems to apply the focus to the search input first. This creates a very quick jump/spazzy movement of the page to the search bar, jumps back to the bottom, and then scrolls up slowly.
The Javascript:
function goToSearch(){
$('html,body').animate({scrollTop: $('#search').offset().top},'medium');
$('#search').focus()
}
The HTML:
<input type="text" id="search" placeholder="search">
...
<a href="#" onclick="goToSearch()">Search</a>
I've tried setting .delay() functions to no avail; it seems to always apply the .focus() first. Why is this happening?
Upvotes: 2
Views: 2561
Reputation: 133
If you found this question like me, you were probably looking for a CSS related issue coupled with the js focus() and you might think you're out of luck. Well, think again - the good news is that there IS a way to have a callback when a CSS animation or transition ends and then fire your event.
You can make use of jQuery's one
method and use either webkitTransitionEnd
otransitionend
oTransitionEnd
msTransitionEnd
transitionend
for transitions or webkitAnimationEnd
oanimationend
msAnimationEnd
animationend
for animations.
An example:
JS:
var myButton = $('#button'),
myBox = $('#box');
myButton.click(function () {
myBox.addClass('change-size');
myBox.one('webkitAnimationEnd oanimationend msAnimationEnd animationend',
function(e) {
// code to execute after animation ends
myBox.removeClass('change-size');
});
});
CSS:
.box {
width: 100px;
height: 100px;
background: hotpink;
}
@keyframes growBox {
to {
width: 300px;
height: 200px;
}
}
.change-size {
animation: growBox 3s linear 0s 1 normal;
}
The solution is not mine, I just found it after a couple of wasted hours, and I'm posting it in case you find this question first.
Source: http://blog.teamtreehouse.com/using-jquery-to-detect-when-css3-animations-and-transitions-end
Upvotes: 1
Reputation: 150050
"Why is this happening?"
The animation effect is asynchronous. That is, the .animate()
function returns immediately after "scheduling" the animation (so to speak) and execution continues immediately with the next statement - in your case, the .focus()
statement. The actual animation will take place after the current JS completes.
Fortunately the .animate()
method provides an option for you to pass a callback function that will be called when the animation is complete, so you can do the focus within that callback function:
$('html,body').animate({scrollTop: $('#search').offset().top},'medium', function(){
$('#search').focus();
});
Upvotes: 14
Reputation: 2609
You should call the focus function when the animation is complete, like so:
function goToSearch(){
$('html,body').animate({scrollTop: $('#search').offset().top},'medium',function(){
$('#search').focus();
});
}
Upvotes: 4