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?
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?
Share Improve this question asked Sep 10, 2012 at 0:21 kennysongkennysong 2,1347 gold badges25 silver badges40 bronze badges3 Answers
Reset to default 14"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 pletes.
Fortunately the .animate()
method provides an option for you to pass a callback function that will be called when the animation is plete, so you can do the focus within that callback function:
$('html,body').animate({scrollTop: $('#search').offset().top},'medium', function(){
$('#search').focus();
});
You should call the focus function when the animation is plete, like so:
function goToSearch(){
$('html,body').animate({scrollTop: $('#search').offset().top},'medium',function(){
$('#search').focus();
});
}
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./using-jquery-to-detect-when-css3-animations-and-transitions-end