Submit jQuery UI dialog on <Enter>
Asked Answered
C

23

131

I have a jQuery UI dialog box with a form. I would like to simulate a click on one of the dialog's buttons so you don't have to use the mouse or tab over to it. In other words, I want it to act like a regular GUI dialog box where simulates hitting the "OK" button.

I assume this might be a simple option with the dialog, but I can't find it in the jQuery UI documentation. I could bind each form input with keyup() but didn't know if there was a simpler/cleaner way. Thanks.

Corneliacornelian answered 15/5, 2009 at 14:9 Comment(1)
If you wish to avoid using a form and want reuseable code, I have provided a good answer here: https://mcmap.net/q/175127/-jquery-ui-dialog-make-a-button-in-the-dialog-the-default-action-enter-keyRamachandra
C
154

I don't know if there's an option in the jQuery UI widget, but you could simply bind the keypress event to the div that contains your dialog...

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

This'll run no matter what element has the focus in your dialog, which may or may not be a good thing depending on what you want.

If you want to make this the default functionality, you can add this piece of 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;
            }
        });
    } 
});

Here's a more detailed view of what it would look like:

$( "#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");
      }
    });
  };
});
Cupid answered 15/5, 2009 at 14:23 Comment(14)
How to do this if dialog is created on-the-fly as in $('<div title="my title">Message</div>').dialog()... ?Orford
Nevermind, I found it: add "open" to dialog (like like close, modal, bgiframe, etc.) and hook the keyup handler there.Orford
This works well in conjunction with the close callback option on the dialog; your various buttons and this method can all close the dialog, and then the close callback can check to see if it should act upon the dialog's information.Khajeh
For Webkit (Safari/Chrome), this only works if I do "keydown" instead of "keyup". Not sure if this is a recent change or if it matters that my page also has a real form on it. Still, thanks for the tip!Bunion
If you do this in IE the form gets submitted TWICE!.Haunch
Instead of if (e.keyCode == 13) you could do if (e.keyCode === $.ui.keyCode.ENTER) to increase readability.Hyman
I down voted this answer. While it is short and neat, in Firefox 7.0.1 this will also trigger your "OK" button if the user selects something from the autocomplete drop down box, e.g. a previously entered email address.Heres
Instead I believe the way to go is binding to submit() and using something like #478191.Heres
This actually only works with keypress, not keyup or keydown, at least on Chromium..Mattress
@Casey Williams Is it possible to specify the button name, rather than the button position, to allow it to apply to a variety of dialogs? Presumably, most coders will be consistent with the Okay button's name.Joanjoana
@gibberish This might be the way to do it: $(this).parent().find('button:contains("Print")'). See this answer at jQuery forumsJoanjoana
It's a bad idea to bind to events in "open:". This will cause it to rebind every time the dialog is opened, which means if the dialog is opened twice, the event handler will be called twice.Cresida
@Cresida True, I am sure there is some nicer way but I solved that by using $("#dialog-form").off('keypress').on('keypress', function (e) { ... to remove and reattach it.Exorbitance
To get around multiple registrations, you can override dialog.close in the same way and de-register there... dialog.off("keypress"). I'm not sure there's a better place to bind. Binding to "submit" is a non-starter because not all dialogs have forms that get submitted.Jadajadd
M
67

I have summed up the answers above & added important stuff

$(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;
        }
    });

Advantages:

  1. Disallow enter key on non compatible elements like textarea , select , button or inputs with type button , imagine user clicking enter on textarea and get the form submitted instead of getting new line!
  2. The binding is done once , avoid using the dialog 'open' callback to bind enter key to avoid binding the same function again and again each time the dialog is 'open'ed
  3. Avoid changing existing code as some answers above suggest
  4. Use 'delegate' instead of the deprecated 'live' & avoid using the new 'on' method to allow working with older versions of jquery
  5. Because we use delegate , that mean the code above can be written even before initializing dialog. you can also put it in head tag even without $(document).ready
  6. Also delegate will bind only one handler to document and will not bind handler to each dialog as in some code above , for more efficiency
  7. Works even with dynamically generated dialogs like $('<div><input type="text"/></div>').dialog({buttons: .});
  8. Worked with ie 7/8/9!
  9. Avoid using the slow selector :first
  10. Avoid using hacks like in answers here to make a hidden submit button

Disadvantages:

  1. Run the first button as the default one , you can choose another button with eq() or call a function inside the if statement
  2. All of dialogs will have same behavior you can filter it by making your selector more specific ie '#dialog' instead of '.ui-dialog'

I know the question is old but I have had the same need, so, I shared the solution I've used.

Metatherian answered 23/11, 2012 at 2:31 Comment(7)
The fact that this is not the accepted answer and doesn't have more votes makes me sad, most informative and does not continuously add handlers. +1Amain
excellent answer, having the open callback to add bindings is something you want to avoidHumbuggery
for me this works when the event is keydown and i remove all the conditions of tagName and remove the click triggerKwapong
@Isaiyavan you can work without the tagName conditions but you will run into problems if the dialog has textarea , text inputs or buttons. but i can't understand how it's working without the trigger! probably u have another event bind that do the sameMetatherian
I also had to change to "keydown" to make this work (tested on OS X 10.8.4, Chrome 29 and Firefox 23).Muttonchops
You could make the button configurable by putting this in the if-body: var options = $(this).children(".ui-dialog-content").dialog("option"); if(typeof options.defaultButton !== "undefined") options.defaultButton();Inlaid
Since this is an older answer, it's worth noting that .delegate() was deprecated in jQuery 3.0, so .on() (available since 1.7) is probably the route to go at this point.Stoss
C
13
$('#dialogBox').dialog('open');
$('.ui-dialog-buttonpane > button:last').focus();

It works beautifully with the latest version of JQuery UI (1.8.1). You may also use :first instead of :last depending on which button you want to set as the default.

This solution, compared to the selected one above, has the advantage of showing which button is the default one for the user. The user can also TAB between buttons and pressing ENTER will click the button currently under focus.

Cheers.

Csc answered 14/5, 2010 at 14:9 Comment(2)
And what if your dialog has one or more text entry fields? I want ENTER to submit the login dialog when the user is in the user name and password fields.Seawards
@David if you're using the jQuery Dialog buttons, then just hide the normal input submit button on the form. eg. visibility: hidden;Bookcraft
I
7

Ben Clayton's is the neatest and shortest and it can be placed at the top of your index page before any jquery dialogs have been initialized. However, i'd like to point out that ".live" has been deprecated. The preferred action is now ".on". If you want ".on" to function like ".live", you'll have to use delegated events to attach the event handler. Also, a few other things...

  1. I prefer to use the ui.keycode.ENTER method to test for the enter key since you don't have to remember the actual key code.

  2. Using "$('.ui-dialog-buttonpane button:first', $(this))" for the click selector makes the whole method generic.

  3. You want to add "return false;" to prevent default and stop propagation.

In this case...

$('body').on('keypress', '.ui-dialog', function(event) { 
    if (event.keyCode === $.ui.keyCode.ENTER) { 
        $('.ui-dialog-buttonpane button:first', $(this)).click();
        return false;
    }
});
Infidel answered 19/6, 2012 at 16:26 Comment(0)
N
6

A crude but effective way to make this work more generically:

$.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');
                  }
             });
    });
}

Then when you create a new dialog you can do this:

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

And use it like a normal jquery dialog thereafter:

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

There are ways to improve that to make it work in more special cases. With the above code it will automatically pick the first button in the dialog as the button to trigger when enter is hit. Also it assumes that there is only one active dialog at any given time which may not be the case. But you get the idea.

Note: As mentioned above, the button that is pressed on enter is dependent on your setup. So, in some cases you would want to use the :first selector in .find method and in others you may want to use the :last selector.

Nervous answered 2/12, 2009 at 22:35 Comment(2)
I think there should be a .first() in there as in $('.ui-dialog').find('button').first().trigger('click'); Otherwise you'll trigger the click of all the buttons of the dialog if there are more than one.Raynata
@thejh - No, it attaches a keyup event handler to every dialog, but only the dialog that contains the element with focus when the key is pressed will receive the event.Seawards
D
6

Rather than listening for key codes like in this answer (which I couldn't get to work) you can bind to the submit event of the form within the dialog and then do this:

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

So, the whole thing would look like this

$("#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');
    }
  }
});

Note that different browsers handle the enter key differently, and some do not always do a submit on enter.

Derogate answered 13/5, 2011 at 17:53 Comment(2)
This seems like the most elegant answer.Stopper
This doesn't work when I have three or more inputs on the same dialog. Don't know why.Vixen
D
4

I don't know about simpler, but ordinarily you would track which button has the current focus. If the focus is changed to a different control, then the "button focus" would remain on the button that had focus last. Ordinarily, the "button focus" would start on your default button. Tabbing to a different button would change the "button focus". You'd have to decide if navigating to a different form element would reset the "button focus" to the default button again. You'll also probably need some visual indicator other than the browser default to indicate the focused button as it loses the real focus in the window.

Once you have the button focus logic down and implemented, then I would probably add a key handler to the dialog itself and have it invoke the action associated with the currently "focused" button.

EDIT: I'm making the assumption that you want to be able hit enter anytime you are filling out form elements and have the "current" button action take precedence. If you only want this behavior when the button is actually focused, my answer is too complicated.

Doy answered 15/5, 2009 at 14:18 Comment(0)
S
4

I found this solution, it work's on IE8, Chrome 23.0 and Firefox 16.0

It's based on Robert Schmidt comment.

$("#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();
});

I hope it help anyone.

Starbuck answered 13/12, 2012 at 15:37 Comment(1)
Simple and effective. The best answer here. Why on earth there isn't an option to make a button the default, I've no idea.Quirt
C
3

Sometimes we forget the fundamental of what the browser already supports:

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

This will cause the ENTER key to submit the form.

Comitia answered 28/2, 2013 at 19:24 Comment(0)
E
2

I did such way... ;) Hope it will helpful for somebody..

$(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;
    }
});
Extortion answered 23/12, 2010 at 13:49 Comment(0)
P
2

This should work to trigger the click of the button's click handler. this example assumes you have already set up the form in the dialog to use the jquery.validate plugin. but could be easily adapted.

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

            }
}
Pragmatics answered 14/2, 2011 at 20:37 Comment(0)
K
1

done and done

  $('#login input').keyup(function(e) {
      if (e.keyCode == 13) {
          $('#login form').submit();
      }
   }
Keratitis answered 7/10, 2010 at 23:42 Comment(0)
F
1

I realise there are a lot of answers already, but I reckon naturally that my solution is the neatest, and possibly the shortest. It has the advantage that it works on any dialogs created any time in the future.

$(".ui-dialog").live("keyup", function(e) {
    if (e.keyCode === 13) {
        $('.ok-button', $(this) ).first().click();
    }
});
Fluviomarine answered 9/10, 2011 at 16:4 Comment(3)
Hey thanks for updating, just a small question, what is ".ok-button" here? is it the class you have to apply on the default button which you want to click with enter?Representationalism
Sorry if you find the question sily.. m too new in JS/jQueryRepresentationalism
@BenClayton : This answer could be improved if you would put it in the context of jQueryUI Dialog.Ezekielezell
S
1

Here is what I did:

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

In this case, myForm is a jQuery object containing the form's html (note, there aren't any "form" tags in there... if you put those in the whole screen will refresh when you press "enter").

Whenever the user presses "enter" from within the form it will be the equivalent of clicking the "ok" button.

This also avoids the issue of having the form open with the "ok" button already highlighted. While that would be good for forms with no fields, if you need the user to fill in stuff, then you probably want the first field to be highlighted.

Stralsund answered 30/12, 2011 at 16:12 Comment(1)
This is the most logical solution. Even better if you declare your button with an id and pass in the selector to the find() but either way works. +1Lobule
F
0

if you know the button element selector :

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

Should do the trick for you. This will focus the ok button, and enter will 'click' it, as you would expect. This is the same technique used in native UI dialogs.

Fabricant answered 15/5, 2009 at 14:16 Comment(0)
F
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();}
   });
Finedrawn answered 28/1, 2011 at 11:47 Comment(0)
C
0

I found a quite simple solution for this problem:

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();
    }
});
Considerate answered 4/4, 2011 at 14:42 Comment(0)
P
0
$('#DialogID').dialog("option", "buttons")["TheButton"].apply()

This worked great for me..

Paraformaldehyde answered 23/6, 2011 at 14:29 Comment(1)
You would do well to include a reference to $('#DialogID').dialog() as an argument to apply. Otherwise $(this).close() will not have the correct context inside of TheButton.Unifilar
A
0

None of these solutions seemed to work for me in IE9. I ended up with this..

$('#my-dialog').dialog({
    ...
    open: function () {
        $(this).parent()
               .find("button:eq(0)")
               .focus()
               .keyup(function (e) {
                   if (e.keyCode == $.ui.keyCode.ENTER) {
                       $(this).trigger("click");
                   };
               });
    }
});
Aronoff answered 19/9, 2012 at 16:3 Comment(0)
B
0

Below body is used because dialog DIV added on body,so body now listen the keyboard event. It tested on 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; 
     }
  }); 
}
Bidet answered 24/7, 2014 at 16:23 Comment(0)
N
0

Because I don't have enough reputation to post comments.

$(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();
  }
});

Modified answer by Basemm #35 too add in Escape to close the dialog.

Nipa answered 10/9, 2014 at 23:13 Comment(0)
S
-1

It works fine Thank You!!!

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

Scaly answered 17/9, 2013 at 11:52 Comment(1)
hmm ... anything new (compared to earlier answers) in your post?Montemayor
L
-1

Give your buttons classes and select them the usual way:

$('#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();
      }

    });

  }
});
Letterpress answered 1/3, 2018 at 5:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.