Bootstrap datepicker return focus after select

為{幸葍}努か 提交于 2019-12-07 05:12:23

问题


If you initialize a bootstrap datepicker from eternicode with autoclose: true, two undesirable behaviors happen:

  1. After the picker closes, when you tab into the next field, you'll start at the beginning of the document again. This can be quite cumbersome on long forms.
  2. Because the picker changes the value programatically, any listeners that you have that care about the blur event on the input won't behave properly. The blur actually occurs when you select the picker value and the input's value hasn't changed. Then the bootstrap-datepicker programmatically updates the field so blur is never fired with the new value.

Here's a demo in stack snippets:
*select any field, select a value from the picker, and then hit Tab

$(".datepicker").datepicker({
  autoclose: true
});
<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/>

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/>

回答1:


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/>



回答2:


I am trying to achieve the same thing but somehow the solution is a little buggy. For example, if you click the same date picker again, it is not responding. The browser will stop responding if you click multiple times. I have a better solution which is below.

My solution is to trick the datepicker to focus on the next element within the DIV. I have parsley validation, it adds the <UL> for me automatically.

<div>   
<input type="text" class="datepicker" />
<ul class="error-message"></ul>
</div>

$('.datepicker').datepicker({
        autoclose: true
    }).on('hide', function () {
        $(this).next('ul').attr('tabindex',-1).focus();
    });



回答3:


Current date selected features added with @KyleMit solutions

var date = new Date();
  var today = new Date(date.getFullYear(), date.getMonth(), date.getDate());
  var end = new Date(date.getFullYear(), date.getMonth(), date.getDate());

$(".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'); 
  }
})
$('.datepicker').datepicker('setDate', today);
<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/>


来源:https://stackoverflow.com/questions/28172785/bootstrap-datepicker-return-focus-after-select

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!