Reputation: 1445
I have a hidden search bar that is made visible when you click on a button. When the search bar appears I would like the input to already have focus, so the user can immediately start typing.
I'm using $('#search-input').focus();
to try and achieve this on click but it isn't working.
Here is a JSFiddle. Click on the red box to trigger the search bar.
My Code:
$('#search-btn').on('click', function() {
$(this).toggleClass('active');
$('#search-input').focus();
$('#search-wrapper').toggleClass('visible');
if ($('#region-wrapper').hasClass('visible')) {
$('#region-wrapper').toggleClass('visible');
}
if ($('#region-select').hasClass('active')) {
$('#region-select').toggleClass('active');
}
});
#menu-side {
width: 200px;
float: right;
position: static;
z-index: 10;
margin-right: 15px;
margin-top: 15px;
}
#search-btn {
background: red;
border: none;
font-size: 1.8rem;
cursor: pointer;
outline: 0;
position: relative;
display: block;
width: 40px;
height: 40px;
transition-duration: 0.3s;
transition-property: all;
}
#search-wrapper {
width: 100%;
position: absolute;
top: 90px;
left: 0;
right: 0;
opacity: 0;
visibility: hidden;
transition-duration: 0.3s;
transition-property: all;
}
#search-wrapper.visible {
opacity: 1;
visibility: visible !important;
}
#search-inner {
background: #e5e5e5;
padding: 35px 80px;
}
#search-input {
border: none;
background: none;
font-size: 1.8rem;
line-height: 1.8rem;
color: black;
float: left;
width: 90%;
}
#search-submit {
background: none;
border: none;
float: right;
width: 10%;
font-size: 1.8rem;
outline: 0;
transition-duration: 0.3s;
transition-property: all;
cursor: pointer;
max-width: 21px;
margin: 0;
padding: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="menu-side" class="clearfix">
<button id="search-btn" class="float-right js-overlay"><i class="fas fa-search float-right"></i></button>
<div id="search-wrapper">
<div class="container">
<div id="search-inner" class="o-bdr-top">
<form role="search" method="get" id="search-form" class="clearfix" action="">
<button id="search-submit"><i class="fas fa-search float-right"></i></button>
<input type="search" id="search-input" placeholder="What are you looking for?" name="s" class="float-left" />
</form>
</div>
</div>
</div>
</div>
Upvotes: 1
Views: 456
Reputation: 67505
(From the official documentation) Take care to only use .focus() on elements that are visible.
You need just to wait for the toggle fired by toggleClass()
to end so the #search-input
input will be visible then you could perform the focus to the input.
Since toggleClass()
method has no complete
callback you could use setTimeout()
for this like:
setTimeout(function() {
$('#search-input').focus();
}, 100);
$('#search-input').focus();
$('#search-btn').on('click', function() {
$(this).toggleClass('active');
$('#search-wrapper').toggleClass('visible');
if ($('#region-wrapper').hasClass('visible')) {
$('#region-wrapper').toggleClass('visible');
}
if ($('#region-select').hasClass('active')) {
$('#region-select').toggleClass('active');
}
setTimeout(function() {
$('#search-input').focus();
}, 100);
});
#menu-side {
width: 200px;
float: right;
position: static;
z-index: 10;
margin-right: 15px;
margin-top: 15px;
}
#search-btn {
background: red;
border: none;
font-size: 1.8rem;
cursor: pointer;
outline: 0;
position: relative;
display: block;
width: 40px;
height: 40px;
transition-duration: 0.3s;
transition-property: all;
}
#search-wrapper {
width: 100%;
position: absolute;
top: 90px;
left: 0;
right: 0;
opacity: 0;
visibility: hidden;
transition-duration: 0.3s;
transition-property: all;
}
#search-wrapper.visible {
opacity: 1;
visibility: visible !important;
}
#search-inner {
background: #e5e5e5;
padding: 35px 80px;
}
#search-input {
border: none;
background: none;
font-size: 1.8rem;
line-height: 1.8rem;
color: black;
float: left;
width: 90%;
}
#search-submit {
background: none;
border: none;
float: right;
width: 10%;
font-size: 1.8rem;
outline: 0;
transition-duration: 0.3s;
transition-property: all;
cursor: pointer;
max-width: 21px;
margin: 0;
padding: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="menu-side" class="clearfix">
<button id="search-btn" class="float-right js-overlay"><i class="fas fa-search float-right"></i></button>
<div id="search-wrapper">
<div class="container">
<div id="search-inner" class="o-bdr-top">
<form role="search" method="get" id="search-form" class="clearfix" action="">
<button id="search-submit"><i class="fas fa-search float-right"></i></button>
<input type="search" id="search-input" placeholder="What are you looking for?" name="s" class="float-left" />
</form>
</div>
</div>
</div>
</div>
Upvotes: 1
Reputation: 67505
I suggest the use of display
instead of visibility/opacity
and toggling the classes, you could use simply display: none
by default then toggle the display using the jQuery toggle()
method then the focus will work:
$('#search-input').focus();
$('#search-btn').on('click', function() {
$(this).toggleClass('active');
$('#search-wrapper').toggle();
$('#search-input').focus();
if ($('#region-wrapper').hasClass('visible')) {
$('#region-wrapper').toggleClass('visible');
}
if ($('#region-select').hasClass('active')) {
$('#region-select').toggleClass('active');
}
$('#search-input').toggleClass('active').focus();
});
#menu-side {
width: 200px;
float: right;
position: static;
z-index: 10;
margin-right: 15px;
margin-top: 15px;
}
#search-btn {
background: red;
border: none;
font-size: 1.8rem;
cursor: pointer;
outline: 0;
position: relative;
display: block;
width: 40px;
height: 40px;
transition-duration: 0.3s;
transition-property: all;
}
#search-wrapper {
width: 100%;
position: absolute;
top: 90px;
left: 0;
right: 0;
display: none;
transition-duration: 0.3s;
transition-property: all;
}
#search-inner {
background: #e5e5e5;
padding: 35px 80px;
}
#search-input {
border: none;
background: none;
font-size: 1.8rem;
line-height: 1.8rem;
color: black;
float: left;
width: 90%;
}
#search-submit {
background: none;
border: none;
float: right;
width: 10%;
font-size: 1.8rem;
outline: 0;
transition-duration: 0.3s;
transition-property: all;
cursor: pointer;
max-width: 21px;
margin: 0;
padding: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="menu-side" class="clearfix">
<button id="search-btn" class="float-right js-overlay"><i class="fas fa-search float-right"></i></button>
<div id="search-wrapper">
<div class="container">
<div id="search-inner" class="o-bdr-top">
<form role="search" method="get" id="search-form" class="clearfix" action="">
<button id="search-submit"><i class="fas fa-search float-right"></i></button>
<input type="search" id="search-input" placeholder="What are you looking for?" name="s" class="float-left" />
</form>
</div>
</div>
</div>
</div>
Upvotes: -1
Reputation: 59
The problem resides on input being hidden initially and browsers prevent operation such as focus on hidden elements.
Common pratice, instead of using display: none
, is to take the component off screen
(IE: Fixed position with negative left and opacity === 0 or visibility hidden).
Using setTimeout (which in this case in undeterministic) is a bad pratice and should be avoided.
Upvotes: 1