web-dev-qa-db-fra.com

Soumettez la boîte de dialogue jQuery UI sur <Entrée>

J'ai une boîte de dialogue jQuery UI avec un formulaire. J'aimerais simuler un clic sur l'un des boutons de la boîte de dialogue afin que vous n'ayez pas à utiliser la souris ou la tabulation dessus. En d'autres termes, je veux qu'il agisse comme une boîte de dialogue standard avec une interface graphique simulant la frappe du bouton "OK".

Je suppose que cela pourrait être une option simple avec la boîte de dialogue, mais je ne la trouve pas dans le documentation de l'interface utilisateur jQuery . Je pouvais relier chaque entrée de formulaire avec keyup () mais je ne savais pas s'il existait un moyen plus simple/plus clair. Merci.

129
CMB

Je ne sais pas s'il y a une option dans le widget d'interface utilisateur jQuery , mais vous pouvez simplement lier le keypress événement au div qui contient votre dialogue ...

$('#DialogTag').keypress(function(e) {
    if (e.keyCode == $.ui.keyCode.ENTER) {
          //Close dialog and/or submit here...
    }
});

Cela fonctionnera quel que soit l'élément ayant le focus dans votre dialogue, ce qui peut être ou ne pas être une bonne chose en fonction de ce que vous voulez.

Si vous voulez en faire une fonctionnalité par défaut, vous pouvez ajouter ce morceau de code:

// jqueryui defaults
$.extend($.ui.dialog.prototype.options, { 
    create: function() {
        var $this = $(this);

        // focus first button and bind enter to it
        $this.parent().find('.ui-dialog-buttonpane button:first').focus();
        $this.keypress(function(e) {
            if( e.keyCode == $.ui.keyCode.ENTER ) {
                $this.parent().find('.ui-dialog-buttonpane button:first').click();
                return false;
            }
        });
    } 
});

Voici une vue plus détaillée de ce à quoi cela ressemblerait:

$( "#dialog-form" ).dialog({
  buttons: { … },
  open: function() {
    $("#dialog-form").keypress(function(e) {
      if (e.keyCode == $.ui.keyCode.ENTER) {
        $(this).parent().find("button:eq(0)").trigger("click");
      }
    });
  };
});
149
Casey Williams

J'ai résumé les réponses ci-dessus et ajouté des éléments importants

$(document).delegate('.ui-dialog', 'keyup', function(e) {
        var target = e.target;
        var tagName = target.tagName.toLowerCase();

        tagName = (tagName === 'input' && target.type === 'button') 
          ? 'button' 
          : tagName;

        isClickableTag = tagName !== 'textarea' && 
          tagName !== 'select' && 
          tagName !== 'button';

        if (e.which === $.ui.keyCode.ENTER && isClickableTag) {
            $(this).find('.ui-dialog-buttonset button').eq(0).trigger('click');

            return false;
        }
    });

Avantages:

  1. Interdit la touche Entrée sur des éléments non compatibles tels que textarea, select, button ou des entrées avec un bouton type, imaginez qu'un utilisateur clique sur enter sur textarea pour obtenir le formulaire envoyé. au lieu d'avoir une nouvelle ligne!
  2. La liaison est effectuée une fois, évitez d'utiliser la boîte de dialogue 'open' callback pour relier la touche Entrée afin d'éviter de lier la même fonction encore et encore à chaque fois que la boîte de dialogue est 'ouverte'
  3. Évitez de changer le code existant comme le suggèrent certaines des réponses ci-dessus.
  4. Utilisez 'delegate' au lieu de 'live' déconseillé et évitez d'utiliser la nouvelle méthode 'on' pour permettre de travailler avec des versions plus anciennes de jquery
  5. Parce que nous utilisons delegate, cela signifie que le code ci-dessus peut être écrit même avant l’initialisation du dialogue. vous pouvez aussi le mettre dans la balise head même sans $(document).ready
  6. De plus, delegate ne liera qu'un seul gestionnaire à document et ne liera aucun gestionnaire à chaque boîte de dialogue, comme dans le code ci-dessus, pour plus d'efficacité.
  7. Fonctionne même avec des dialogues générés dynamiquement comme $('<div><input type="text"/></div>').dialog({buttons: .});
  8. Travaillé avec ie 7/8/9!
  9. Évitez d'utiliser le sélecteur lent :first
  10. Évitez les hacks comme dans les réponses ici pour créer un bouton d'envoi masqué

Inconvénients:

  1. Exécutez le premier bouton comme bouton par défaut, vous pouvez choisir un autre bouton avec eq() ou appeler une fonction dans l'instruction if
  2. Tous les dialogues auront le même comportement que vous pouvez filtrer en rendant votre sélecteur plus spécifique, c'est-à-dire '#dialog' au lieu de '.ui-dialog'

Je sais que la question est ancienne mais que j'ai le même besoin, j'ai donc partagé la solution que j'ai utilisée.

65
Basemm
$('#dialogBox').dialog('open');
$('.ui-dialog-buttonpane > button:last').focus();

Cela fonctionne à merveille avec la dernière version de JQuery UI (1.8.1). Vous pouvez également utiliser: first au lieu de: last en fonction du bouton que vous souhaitez définir par défaut.

Cette solution, comparée à celle sélectionnée ci-dessus, présente l'avantage de montrer quel bouton est le bouton par défaut pour l'utilisateur. L'utilisateur peut également utiliser la touche TAB entre les boutons et appuyer sur la touche ENTREE pour cliquer sur le bouton actuellement mis au point.

À votre santé.

13
Mario Awad

Un moyen simple mais efficace de rendre ce travail plus générique:

$.fn.dlg = function(options) {
    return this.each(function() {
             $(this).dialog(options);
             $(this).keyup(function(e){
                  if (e.keyCode == 13) {                
                       $('.ui-dialog').find('button:first').trigger('click');
                  }
             });
    });
}

Ensuite, lorsque vous créez une nouvelle boîte de dialogue, vous pouvez procéder comme suit:

$('#a-dialog').mydlg({...options...})

Et utilisez-le comme un dialogue jquery normal par la suite:

$('#a-dialog').dialog('close')

Il existe des moyens d'améliorer cela pour le faire fonctionner dans des cas plus particuliers. Avec le code ci-dessus, le premier bouton de la boîte de dialogue sera automatiquement sélectionné comme bouton à déclencher lorsque vous entrez. En outre, il suppose qu’il n’ya qu’un seul dialogue actif à la fois, ce qui peut ne pas être le cas. Mais vous avez l'idée.

Remarque: comme mentionné ci-dessus, le bouton sur lequel vous avez appuyé sur Entrée dépend de votre configuration. Ainsi, dans certains cas, vous voudrez peut-être utiliser le sélecteur: first dans la méthode .find et dans d'autres, vous pouvez utiliser le sélecteur: last.

6
Karim

Plutôt que d'écouter les codes de clé comme dans cette réponse (que je n'ai pas pu me mettre au travail), vous pouvez créer un lien vers l'événement submit du formulaire dans la boîte de dialogue, puis procédez comme suit:

$("#my_form").parents('.ui-dialog').first().find('.ui-button').first().click();

Donc, le tout ressemblerait à ceci

$("#my_form").dialog({
  open: function(){
    //Clear out any old bindings
    $("#my_form").unbind('submit');
    $("#my_form").submit(function(){
      //simulate click on create button
      $("#my_form").parents('.ui-dialog').first().find('.ui-button').first().click();
      return false;
    });
  },
  buttons: {
    'Create': function() {
      //Do something
    },
    'Cancel': function() {
      $(this).dialog('close');
    }
  }
});

Notez que différents navigateurs traitent la touche Entrée différemment, et que certains ne le font pas toujours.

6
Salida Software

Ben Clayton est le plus propre et le plus court, et il peut être placé en haut de votre page d’index avant l’initialisation des boîtes de dialogue JQuery. Cependant, je voudrais signaler que ".live" est obsolète. L'action préférée est maintenant ".on". Si vous voulez que ".on" fonctionne comme ".live", vous devrez utiliser des événements délégués pour associer le gestionnaire d'événements. En outre, quelques autres choses ...

  1. Je préfère utiliser la méthode ui.keycode.ENTER pour tester la touche Entrée, car vous n'avez pas à vous souvenir du code de la clé.

  2. L'utilisation de "$ ('. Bouton de la fenêtre-bouton-dialogue-ui: premier', $ (ceci))" pour le sélecteur de clic rend la méthode entière générique.

  3. Vous voulez ajouter "return false"; pour empêcher les défauts et arrêter la propagation.

Dans ce cas...

$('body').on('keypress', '.ui-dialog', function(event) { 
    if (event.keyCode === $.ui.keyCode.ENTER) { 
        $('.ui-dialog-buttonpane button:first', $(this)).click();
        return false;
    }
});
5
Nelson M

Je ne sais pas si c'est plus simple, mais vous devriez normalement savoir quel bouton a le focus actuel. Si la mise au point est modifiée sur un contrôle différent, la "mise au point du bouton" reste sur le bouton qui a eu la mise au point en dernier. Normalement, la "mise au point" commence sur votre bouton par défaut. La tabulation sur un bouton différent changerait la "mise au point du bouton". Vous devez décider si le fait de naviguer vers un élément de formulaire différent réinitialise à nouveau le "focus de bouton" sur le bouton par défaut. Vous aurez également probablement besoin d'un indicateur visuel autre que celui par défaut du navigateur pour indiquer le bouton sélectionné lorsqu'il perd le véritable objectif dans la fenêtre.

Une fois que vous avez mis en œuvre et implémenté la logique de la focalisation des boutons, j'ajouterais probablement un gestionnaire de clés à la boîte de dialogue elle-même et l'invoquerais pour l'action associée au bouton "focalisé" en cours.

EDIT : Je suppose que vous voulez pouvoir appuyer sur Entrée à chaque fois que vous remplissez des éléments de formulaire et que l'action du bouton "actuel" est prioritaire. . Si vous ne souhaitez ce comportement que lorsque le bouton est réellement centré, ma réponse est trop compliquée.

4
tvanfosson

Parfois, nous oublions la base de ce que le navigateur supporte déjà:

<input type="submit" style="visibility:hidden" />

Cela entraînera la ENTER clé pour soumettre le formulaire.

3
Seifu

J'ai trouvé cette solution, ça marche sur IE8, Chrome 23.0 et Firefox 16.0

Il est basé sur le commentaire de Robert Schmidt.

$("#id_dialog").dialog({
    buttons: [{
        text: "Accept",
        click: function() {
            // My function
        },
        id: 'dialog_accept_button'
    }]
}).keyup(function(e) {
    if (e.keyCode == $.ui.keyCode.ENTER)
        $('#dialog_accept_button').click();
});

J'espère que cela aidera n'importe qui.

3
Pablo Oña

Cela devrait fonctionner pour déclencher le clic du gestionnaire de clic du bouton. Cet exemple suppose que vous avez déjà configuré le formulaire dans la boîte de dialogue pour utiliser le plug-in jquery.validate. mais pourrait être facilement adapté.

open: function(e,ui) {
    $(this).keyup(function(e) {
        if (e.keyCode == 13) {
           $('.ui-dialog-buttonpane button:last').trigger('click');
        }
    });
},
buttons: {
    "Submit Form" : function() {
            var isValid = $('#yourFormsID').valid();
            // if valid do ajax call
            if(isValid){
               //do  your ajax call here. with serialize form or something...

            }
}
2
timbrown

Je l'ai fait de cette façon ...;) J'espère que ça va être utile à quelqu'un ..

$(window).keypress(function(e) {
    if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
        $(".ui-dialog:visible").find('.ui-dialog-buttonpane').find('button:first').click();
        return false;
    }
});
2

fait et fait

  $('#login input').keyup(function(e) {
      if (e.keyCode == 13) {
          $('#login form').submit();
      }
   }
1
kevin

Je me rends compte qu’il ya déjà beaucoup de réponses, mais j’estime naturellement que ma solution est la plus nette et peut-être la plus courte. Il présente l'avantage de fonctionner avec tous les dialogues créés à tout moment.

$(".ui-dialog").live("keyup", function(e) {
    if (e.keyCode === 13) {
        $('.ok-button', $(this) ).first().click();
    }
});
1
Ben Clayton

Voici ce que j'ai fait:

myForm.dialog({
  "ok": function(){
    ...blah...
  }
  Cancel: function(){
    ...blah...
  }
}).keyup(function(e){
  if( e.keyCode == 13 ){
   $(this).parent().find('button:nth-child(1)').trigger("click");
  }
});

Dans ce cas, myForm est un objet jQuery contenant le code HTML du formulaire (remarque, il n'y a pas de balises "form" dans ce fichier ... si vous les mettez dans tout l'écran, elles s'actualiseront lorsque vous appuierez sur "entrée").

Chaque fois que l'utilisateur appuie sur "entrer" dans le formulaire, cela équivaut à cliquer sur le bouton "ok".

Cela évite également d'avoir à ouvrir le formulaire avec le bouton "ok" déjà mis en surbrillance. Bien que cela soit utile pour les formulaires sans champs, si vous souhaitez que l'utilisateur remplisse des éléments, vous souhaitez probablement que le premier champ soit mis en surbrillance.

1
Tyler

J'ai trouvé une solution assez simple à ce problème:

var d = $('<div title="My dialog form"><input /></div>').dialog(
    buttons: [{
        text: "Ok",
        click: function(){
            // do something
            alert('it works');
        },
        className: 'dialog_default_button'
    }]
});

$(d).find('input').keypress(function(e){
    if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
        e.preventDefault();
        $('.dialog_default_button').click();
    }
});
0
Robert Schmidt

si vous connaissez le sélecteur d'élément de bouton:

$('#dialogBox').dialog('open');
$('#okButton').focus();

Devrait faire le tour pour vous. Cela mettra l'accent sur le bouton ok et entrera "cliquera" dessus, comme vous vous en doutez. C'est la même technique que celle utilisée dans les boîtes de dialogue de l'interface utilisateur native.

0
sandesh247

Au-dessous du corps est utilisé parce que la boîte de dialogue DIV a été ajoutée au corps, alors corps écoute maintenant l'événement de clavier. Il a testé sur IE8,9,10, Mojila, Chrome.

open: function() {
$('body').keypress(function (e) { 
     if (e.keyCode == 13) {   
     $(this).parent().find(".ui-dialog-buttonpane button:eq(0)").trigger("click");
     return false; 
     }
  }); 
}
0
LoopCoder

Aucune de ces solutions ne semblait fonctionner pour moi dans IE9. J'ai fini avec ça ..

$('#my-dialog').dialog({
    ...
    open: function () {
        $(this).parent()
               .find("button:eq(0)")
               .focus()
               .keyup(function (e) {
                   if (e.keyCode == $.ui.keyCode.ENTER) {
                       $(this).trigger("click");
                   };
               });
    }
});
0
Paul Martin

Parce que je n'ai pas assez de réputation pour poster des commentaires.

$(document).delegate('.ui-dialog', 'keyup', function(e) {
  var tagName = e.target.tagName.toLowerCase();

  tagName = (tagName === 'input' && e.target.type === 'button') ? 'button' : tagName;

  if (e.which === $.ui.keyCode.ENTER && tagName !== 'textarea' && tagName !== 'select' && tagName !== 'button') {
      $(this).find('.ui-dialog-buttonset button').eq(0).trigger('click');
    return false;
  } else if (e.which === $.ui.keyCode.ESCAPE) {
      $(this).close();
  }
});

Réponse modifiée par Basemm # 35 aussi ajouter Echap pour fermer la boîte de dialogue.

0
Liam Mitchell
$('#DialogID').dialog("option", "buttons")["TheButton"].apply()

Cela a bien fonctionné pour moi ..

0
Peter
   $("#LogOn").dialog({
       modal: true,
       autoOpen: false,
       title: 'Please Log On',
       width: 370,
       height: 260,
       buttons: { "Log On": function () { alert('Hello world'); } },
       open: function() { $(this).parents('.ui-dialog-buttonpane button:eq(0)').focus();}
   });
0
LeCram