web-dev-qa-db-fra.com

JQuery UI Datepicker perd le focus lors de la sélection de date avec la souris

J'utilise JQuery UI avec Datepicker et lorsqu'un utilisateur appuie sur un champ, il fait apparaître le calendrier de manière appropriée.

  1. Onglets utilisateur (via la touche dans le champ)
  2. L'utilisateur sélectionne la date avec un clic de souris
  3. Onglets d'utilisateur
  4. Tabindex recommence à une heure (au début de la forme)

Voici le code. (Peut aussi avoir l'index d'onglets défini)

<input type="text" name="demo" />
<input type="text" class="date" />

Le code jQuery est:

$(".date").datepicker();

Avez-vous des suggestions sur la manière de résoudre ce problème (bonus à la solution la plus courte)?

37
Jeff Ancel

Abonnez-vous à l'événement onClose ou onSelect:

$("#someinput").datepicker(
{
    // other options goes here
    onSelect: function ()
    {
        // The "this" keyword refers to the input (in this case: #someinput)
        this.focus();
    }
});

Ou dans le cas de onClose:

$("#someinput").datepicker(
{
    onClose: function ()
    {
        this.focus();
    }
});
37
cllpse

Voir la discussion sur ce problème à l'adresse http://bugs.jqueryui.com/ticket/7266 Avec une solution à http://jsfiddle.net/lankarden/9FtnW/

3
Dave Carmean

Merci pour la suggestion Jeff, j'ai modifié votre fonction onSelect afin d'utiliser le filtre d'attribut pour récupérer uniquement les éléments avec le tabindex spécifié par "nexttab".

$(function(){
  $(".date").datepicker({
      onSelect: function(){
          currenttab = $(el).attr("tabindex");
          nexttab = currenttab * 1 + 1;
          $("[tabindex='" + nexttab + "']").focus();
      }
  });
});

PS: Si vous n’avez pas spécifié de tabindex dans votre code, comme j’ai négligé de le faire plus tôt, ajoutez simplement le code suivant:

$('input, select').each(function(i, val){
    $(this).attr('tabindex', i + 1);
});
3
johnnynotsolucky

Semblable à l'approche de Jimmy, mais cela met l'accent sur l'icône du calendrier (en supposant que votre calendrier utilise une icône), j'ai trouvé cette méthode plus appropriée lorsque j'avais plusieurs sélecteurs de date côte à côte.

Définissez les options de date par défaut de manière à ce que l'icône se ferme lorsque la fenêtre contextuelle du calendrier se ferme:

    $(".date").datepicker({
        onClose: function() {
            $(this).next('a').focus(); 
        }
    });

Ajoutez une balise à l'icône du calendrier pour qu'elle puisse être mise au point:

    $(".date").each(function() {
        $($(this).next('img')).wrap($("<A/>").attr("href","#"));
    });
2
Oli B

Si vous ne vous souciez vraiment pas de l'ordre des tabulations, c'est-à-dire de ne pas l'avoir attribué pour qu'il suive le déroulement de la page, vous pouvez faire quelque chose comme ceci.

jQuery('.date').datepicker({
    'onSelect': function(){
        $(this).nextAll('input, button, textarea, a').filter(':first').focus();
    }
});

Cela fonctionne sur l'hypothèse que lorsque l'utilisateur sélectionne la date, il en a terminé avec ce champ et passe au suivant, de sorte qu'il sélectionne simplement le champ suivant.

1
Jimmy Stenke

J'ai pu mettre le focus sur le champ de saisie suivant après avoir appuyé sur Entrée (qui sélectionne la date du jour par défaut) ou en cliquant sur une date du calendrier à l'aide de cette option.

$(".jqDateField").datepicker('option', {
    dateFormat: 'mm/dd/y', onClose: function () {
        $(':input:eq(' + ($(':input').index(this) + 1) + ')').focus();
    }
});

Cela peut être nécessaire pour définir le focus sur la prochaine saisie de texte si vous avez un bouton de sélection ou de saisie dans le "chemin"

$(':input[type="text"]:eq(' + ($(':input[type="text"]').index(this) + 1) + ')')
0
AdamRoof

Vous pouvez probablement utiliser l'événement onClose pour remettre le focus sur votre entrée à la fermeture du sélecteur de date, car this fait référence au champ de saisie associé dans ce rappel. Par exemple:

$('.date').datepicker({
   onClose: function() { this.focus(); }
});
0
Adam Bellaire

Le fait de se concentrer sur la même boîte provoque finalement le réaffichage du sélecteur de date et ce que nous souhaitons réellement, c'est qu'il passe au champ suivant. Voici la solution imaginée:

  1. Requiert que l'attribut tabindex soit défini sur vos champs.
  2. Ceci transforme une chaîne en int en javascript (le * 1).
  3. Cela déplace le champ sélectionné sur l'élément suivant, au lieu du focus actuel

    $(function(){
      $(".date").datepicker({
          onSelect: function(){
              currenttab = $(this).attr("tabindex");
              nexttab = currenttab * 1 + 1;
              $(":input").each(function(){
                  if ($(this).attr("tabindex") == nexttab)
                     $(this).focus();
              });
      }
      });
    });
    

Toutes les suggestions pour améliorer cette technique sont appréciées.

0
Jeff Ancel

J'ai dû résoudre ce problème aussi et j'ai trouvé que les réponses données n'étaient pas exactement ce que je cherchais. Voici ce que j'ai fait.

Un blog a mentionné une fonction jQuery qui vous permettrait de sélectionner le prochain élément de formulaire à l'écran. Je l'ai importé dans mon projet et je l'ai appelé à la fermeture de la boîte de dialogue Datepicker.

Dans le cas où le lien est coupé, voici la fonction

$.fn.focusNextInputField = function() {
    return this.each(function() {
        var fields = $(this).parents('form:eq(0),body').find('button,input,textarea,select');
        var index = fields.index( this );
        if ( index > -1 && ( index + 1 ) < fields.length ) {
            fields.eq( index + 1 ).focus();
        }
        return false;
    });
};

Puis simplement appelé onClose du datepicker

$(this).datepicker({
    onClose: function () {
       $(this).focusNextInputField();
    }
});

J'espère que cela aide les futurs visiteurs.

0
Brian Dishaw