Soumettre la boîte de dialogue de l'interface utilisateur jQuery sur <Entrée>


131

J'ai une boîte de dialogue de l'interface utilisateur jQuery avec un formulaire. Je voudrais 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 GUI régulière où simule le fait d'appuyer sur le bouton "OK".

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


Si vous souhaitez éviter d'utiliser un formulaire et voulez du code réutilisable, j'ai fourni une bonne réponse ici: stackoverflow.com/a/9628800/329367
Darren

Réponses:


153

Je ne sais pas s'il y a une option dans le widget jQuery UI , mais vous pouvez simplement lier l' keypressévénement au div qui contient votre boîte de 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 qui a le focus dans votre boîte de dialogue, ce qui peut ou non être une bonne chose selon ce que vous voulez.

Si vous souhaitez en faire la 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");
      }
    });
  };
});

2
Nevermind, je l'ai trouvé: ajoutez "open" à la boîte de dialogue (comme close, modal, bgiframe, etc.) et accrochez le gestionnaire de touches là-bas.
Milan Babuškov

5
Pour Webkit (Safari / Chrome), cela ne fonctionne que si je fais "keydown" au lieu de "keyup". Je ne sais pas s'il s'agit d'un changement récent ou s'il est important que ma page comporte également un vrai formulaire. Pourtant, merci pour le tuyau!
Nicholas Piasecki

12
Au lieu de if (e.keyCode == 13), vous pouvez faire if (e.keyCode === $ .ui.keyCode.ENTER) pour augmenter la lisibilité.
A. Murray le

2
J'ai voté contre cette réponse. Bien qu'il soit court et soigné, dans Firefox 7.0.1 cela déclenchera également votre bouton "OK" si l'utilisateur sélectionne quelque chose dans la liste déroulante de saisie semi-automatique, par exemple une adresse e-mail précédemment saisie.
cburgmer

2
C'est une mauvaise idée de se lier à des événements dans "open:". Cela provoquera une nouvelle liaison à chaque ouverture de la boîte de dialogue, ce qui signifie que si la boîte de dialogue est ouverte deux fois, le gestionnaire d'événements sera appelé deux fois.
Elezar

67

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. DISALLOW touche Entrée éléments non compatibles tels que textarea, select, buttonou entrées avec le bouton de type, imaginez en cliquant utilisateur d' entrer sur textareaet obtenir le formulaire soumis au lieu d'obtenir une nouvelle ligne!
  2. La liaison est effectuée une fois, évitez d'utiliser le callback de dialogue `` open '' pour lier la touche Entrée pour éviter de lier la même fonction encore et encore à chaque fois que la boîte de dialogue est `` ouverte ''
  3. Évitez de modifier le code existant comme le suggèrent certaines réponses ci-dessus
  4. Utilisez 'delegate' au lieu du obsolète 'live' et évitez d'utiliser la nouvelle méthode 'on' pour permettre de travailler avec les anciennes versions de jquery
  5. Parce que nous utilisons des délégués, cela signifie que le code ci-dessus peut être écrit avant même d'initialiser le dialogue. vous pouvez également le mettre dans la balise head même sans$(document).ready
  6. De plus, le délégué liera un seul gestionnaire à documentet ne liera pas le gestionnaire à chaque boîte de dialogue comme dans le code ci-dessus, pour plus d'efficacité
  7. Fonctionne même avec des boîtes de dialogue générées 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 d'utiliser des hacks comme dans les réponses ici pour créer un bouton d'envoi caché

Désavantages:

  1. Exécutez le premier bouton par défaut, vous pouvez choisir un autre bouton avec eq()ou appeler une fonction à l'intérieur de l'instruction if
  2. Toutes les boîtes de dialogue 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 j'ai eu le même besoin, alors j'ai partagé la solution que j'ai utilisée.


4
Le fait que ce ne soit pas la réponse acceptée et n'ait pas plus de votes me rend triste, très instructif et n'ajoute pas continuellement de gestionnaires. +1
Chris O'Kelly

1
excellente réponse, avoir le rappel ouvert pour ajouter des liaisons est quelque chose que vous voulez éviter
Jay Rizzi

1
pour moi, cela fonctionne lorsque l'événement est keydown et que je supprime toutes les conditions de tagName et supprime le déclencheur de clic
Isaiyavan Babu Karan

1
J'ai également dû passer en "keydown" pour que cela fonctionne (testé sur OS X 10.8.4, Chrome 29 et Firefox 23).
natebeaty

1
Comme il s'agit d'une réponse plus ancienne, il convient de noter qu'elle .delegate()était obsolète dans jQuery 3.0, donc .on()(disponible depuis la version 1.7) est probablement la voie à suivre à ce stade.
jinglesthula

13
$('#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: premier au lieu de: dernier selon le bouton que vous souhaitez définir par défaut.

Cette solution, comparée à celle sélectionnée ci-dessus, a l'avantage de montrer quel bouton est le bouton par défaut pour l'utilisateur. L'utilisateur peut également TAB entre les boutons et appuyer sur ENTRÉE cliquera sur le bouton actuellement sous le focus.

À votre santé.


Et si votre boîte de dialogue comporte un ou plusieurs champs de saisie de texte? Je veux que ENTER soumette la boîte de dialogue de connexion lorsque l'utilisateur est dans les champs du nom d'utilisateur et du mot de passe.
David Harkness

1
@David si vous utilisez les boutons de la boîte de dialogue jQuery, masquez simplement le bouton d'envoi d'entrée normal sur le formulaire. par exemple. visibilité: cachée;
Damo

6

Un moyen brut 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 le faire:

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

Et utilisez-le comme une boîte de dialogue jquery normale par la suite:

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

Il existe des moyens d'améliorer cela pour que cela fonctionne dans des cas plus particuliers. Avec le code ci-dessus, il choisira automatiquement le premier bouton de la boîte de dialogue comme bouton à déclencher lorsque vous appuyez sur Entrée. Il suppose également qu'il n'y a qu'un seul dialogue actif à un moment donné, ce qui peut ne pas être le cas. Mais vous voyez l'idée.

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


Je pense qu'il devrait y avoir un .first () là-dedans comme dans $ ('. Ui-dialog'). Find ('button'). First (). Trigger ('click'); Sinon, vous déclencherez le clic de tous les boutons de la boîte de dialogue s'il y en a plus d'un.
JustinStolle

@thejh - Non, il attache un gestionnaire d'événements keyup à chaque boîte de dialogue, mais seule la boîte de dialogue qui contient l'élément avec le focus lorsque la touche est enfoncée recevra l'événement.
David Harkness

6

Plutôt que d'écouter les codes clés comme dans cette réponse (que je n'ai pas pu mettre au travail), vous pouvez vous lier à l'événement submit du formulaire dans la boîte de dialogue, puis faire ceci:

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

Donc, tout ressemblerait à ça

$("#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 gèrent la clé d'entrée différemment, et certains ne font pas toujours une soumission lors de l'entrée.


Cela semble être la réponse la plus élégante.
Dan

Cela ne fonctionne pas lorsque j'ai trois entrées ou plus dans la même boîte de dialogue. Je ne sais pas pourquoi.
programad

6

Ben Clayton est le plus net et le plus court et il peut être placé en haut de votre page d'index avant que toute boîte de dialogue jquery ait été initialisée. Cependant, je tiens à souligner que ".live" est obsolète. L'action préférée est désormais ".on". Si vous voulez que ".on" fonctionne comme ".live", vous devrez utiliser des événements délégués pour attacher le gestionnaire d'événements. Aussi, quelques autres choses ...

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

  2. Utiliser "$ ('. Ui-dialog-buttonpane button: first', $ (this))" pour le sélecteur de clic rend l'ensemble de la méthode générique.

  3. Vous voulez ajouter "return false;" pour empêcher la valeur par défaut 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;
    }
});

4

Je ne sais pas ce qui est plus simple, mais normalement, vous suivrez quel bouton a le focus actuel. Si le focus est modifié en un contrôle différent, le "focus bouton" resterait alors sur le bouton qui avait le focus en dernier. Normalement, le "focus du bouton" démarre sur votre bouton par défaut. La tabulation vers un bouton différent changerait le "focus du bouton". Vous devrez décider si la navigation vers un élément de formulaire différent réinitialisera à nouveau le "focus du bouton" sur le bouton par défaut. Vous aurez probablement également besoin d'un indicateur visuel autre que le navigateur par défaut pour indiquer le bouton focalisé car il perd le focus réel dans la fenêtre.

Une fois que vous avez la logique de mise au point du bouton vers le bas et implémentée, alors j'ajouterais probablement un gestionnaire de clé au dialogue lui-même et lui demanderais d'appeler l'action associée au bouton actuellement "concentré".

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" a la priorité. Si vous ne voulez ce comportement que lorsque le bouton est réellement focalisé, ma réponse est trop compliquée.


3

J'ai trouvé cette solution, elle fonctionne 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.


Merci! Cela m'a fait gagner beaucoup de temps! :)
Rahul Desai

3

Parfois, nous oublions les fondamentaux de ce que le navigateur prend déjà en charge:

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

Cela amènera la ENTERclé à soumettre le formulaire.


2

J'ai fait de cette façon ...;) J'espère que cela sera utile pour 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

Cela devrait fonctionner pour déclencher le clic du gestionnaire de clics du bouton. cet exemple suppose que vous avez déjà configuré le formulaire dans la boîte de dialogue pour utiliser le plugin 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...

            }
}

1

Je me rends compte qu'il y a déjà beaucoup de réponses, mais je pense naturellement que ma solution est la plus soignée, et peut-être la plus courte. Il a l'avantage de fonctionner sur toutes les boîtes de dialogue créées à tout moment dans le futur.

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

1
Hé merci pour la mise à jour, juste une petite question, qu'est-ce que ".ok-button" ici? est-ce la classe que vous devez appliquer sur le bouton par défaut sur lequel vous voulez cliquer avec enter?
UID

Désolé si vous trouvez la question sily .. m trop nouveau dans JS / jQuery
UID

@BenClayton: Cette réponse pourrait être améliorée si vous la mettiez dans le contexte de jQueryUI Dialog.
Michael Potter

1

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 html du formulaire (notez qu'il n'y a pas de balises "form" là-dedans ... si vous les mettez dans tout l'écran, il sera actualisé lorsque vous appuyez sur "Entrée").

Chaque fois que l'utilisateur appuie sur "Entrée" à partir du formulaire, cela équivaudra à cliquer sur le bouton "OK".

Cela évite également le problème d'avoir le formulaire ouvert avec le bouton "ok" déjà mis en évidence. Bien que cela convienne aux formulaires sans champs, si vous avez besoin que l'utilisateur remplisse des éléments, vous souhaitez probablement que le premier champ soit mis en surbrillance.


C'est la solution la plus logique. Encore mieux si vous déclarez votre bouton avec un identifiant et passez le sélecteur à find () mais dans les deux cas fonctionne. +1
Vincent

1

fait et fait

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

0

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

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

Devrait faire l'affaire pour vous. Cela mettra l'accent sur le bouton ok, et entrer "cliquera" dessus, comme vous vous en doutez. Il s'agit de la même technique utilisée dans les boîtes de dialogue natives de l'interface utilisateur.


0
   $("#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

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
$('#DialogID').dialog("option", "buttons")["TheButton"].apply()

Cela a très bien fonctionné pour moi.


Vous feriez bien d'inclure une référence à $ ('# DialogID'). Dialog () comme argument à appliquer. Sinon, $ (this) .close () n'aura pas le bon contexte à l'intérieur de TheButton.
Dave le

0

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

Le corps ci-dessous est utilisé car la boîte de dialogue DIV a été ajoutée sur le corps, donc body écoute maintenant l'événement 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

Parce que je n'ai pas assez de réputation pour publier 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 dans Escape pour fermer la boîte de dialogue.


-1

Cela fonctionne bien Merci !!!

open: function () { debugger; $("#dialogDiv").keypress(function (e) { if (e.keyCode == 13) { $(this).parent().find("#btnLoginSubmit").trigger("click"); } }); },


hmm ... quelque chose de nouveau (par rapport aux réponses précédentes) dans votre message?
kleopatra

-1

Donnez à vos boutons des classes et sélectionnez-les de la manière habituelle:

$('#DialogTag').dialog({
  closeOnEscape: true,
  buttons: [
    {
      text: 'Cancel',
      class: 'myCancelButton',
      click: function() {
        // Close dialog fct
      }
    },
    {
      text: 'Ok',
      class: 'myOKButton',
      click: function() {
        // OK fct
      }
    }
  ],
  open: function() {

    $(document).keyup(function(event) {

      if (event.keyCode === 13) {
        $('.myOKButton').click();
      }

    });

  }
});
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.