If you initialize a bootstrap datepicker from eternicode with autoclose: true
, two undesirable behaviors happen:
Here's a demo in stack snippets:
*select any field, select a value from the picker, and then hit Tab
According to the answer to Focus the field after selecting the jQuery UI datepicker, you can tap into the onClose
or onSelect
events, but the bootstrap picker doesn't offer those events.
Simply replacing them with hide
doesn't seem to work either, since the refocusing will create an endless loop that always keeps the picker open any time you try to close it.
$(".datepicker").datepicker({
autoclose: true
})
.on('hide', function () {
$(this).focus();
});
Stack Snippet Demo:
$(".datepicker").datepicker({
autoclose: true
})
.on('hide', function () {
$(this).focus();
});
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/css/bootstrap.css" rel="stylesheet"/>
<link href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.3.1/css/datepicker.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/js/bootstrap.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.3.1/js/bootstrap-datepicker.js"></script>
<input type="text" class="datepicker" /><br/>
<input type="text" class="datepicker" /><br/>
<input type="text" class="datepicker" /><br/>
This is a little bit of a hack job, but you can conditionally hide and show the elements to avoid an infinite loop. On hide, check if this is the first time attempting to hide. If the input does not have focus (meaning they have used the dropdown and we've lost our tab order, then refocusing will cause the picker to show. We'll also catch this show and hide from there, entering back into our original code. We'll pass back and forth a property on the object so we can manage state.
That will look like this:
$(".datepicker").datepicker({
autoclose: true
})
.on('hide', function () {
if (!this.firstHide) {
if (!$(this).is(":focus")) {
this.firstHide = true;
// this will inadvertently call show (we're trying to hide!)
this.focus();
}
} else {
this.firstHide = false;
}
})
.on('show', function () {
if (this.firstHide) {
// careful, we have an infinite loop!
$(this).datepicker('hide');
}
})
Stack Snippet Demo:
$(".datepicker").datepicker({
autoclose: true
})
.on('hide', function () {
if (!this.firstHide) {
if (!$(this).is(":focus")) {
this.firstHide = true;
// this will inadvertently call show (we're trying to hide!)
this.focus();
}
} else {
this.firstHide = false;
}
})
.on('show', function () {
if (this.firstHide) {
// careful, we have an infinite loop!
$(this).datepicker('hide');
}
})
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/css/bootstrap.css" rel="stylesheet"/>
<link href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.3.1/css/datepicker.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/js/bootstrap.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.3.1/js/bootstrap-datepicker.js"></script>
<input type="text" class="datepicker" /><br/>
<input type="text" class="datepicker" /><br/>
<input type="text" class="datepicker" /><br/>