How to capture enter key being pressed on pages containing multiple forms?

MysticBrook picture MysticBrook · Apr 19, 2009 · Viewed 55.6k times · Source

I have inherited a web application where the usual ability to press return in any of the input fields has been disabled for the very good reason that the page contains multiple forms, and the application would not be able to determine (or, so I am told) which form to action. The application has been designed so there are no submit buttons (as in input type="submit") and, instead, the designers have gone for onclick handling. Here are two buttons that are defined on one of the pages, included for illustration

<input type="button" value="LOGIN"  name="btnLoginOk" onclick="submit(); />"

<input type="button" class="button-click-grey" value="Find Link Partners"  
    onclick="raiseEvent('SubmitForm','',this);" style="cursor:pointer;" />

But I really want to be able to allow users to press return if they wish e.g. if they've just typed into a field associated with the LOGIN, then detect that and action the onclick="submit();"

Perhaps there is a solution with jQuery.

Answer

Borgar picture Borgar · Apr 19, 2009

page contains multiple forms, and the application would not be able to determine (or, so I am told) which form to action.

When you press enter on an input control the browser seeks the first submit button in that form and simulates a click on it. In the case of multiple buttons, the first one will be pressed on keyboard enter (this is by no means written in stone and browsers may deviate from this).

If you have two forms, the one that got a keypress will have it's first submit button pressed. Therefore you don't really need any special handling of this. You just have to stop being in the way.

You can simulate this in code, on a form:

 $( 'form' ).bind('keypress', function(e){
   if ( e.keyCode == 13 ) {
     $( this ).find( 'input[type=submit]:first' ).click();
   }
 });

Or window (for a demonstration of what is roughly happening):

 $( window ).bind('keypress', function(e){
   if ( $( e.originalTarget ).is( ':input' ) && e.keyCode == 13 ) {
     $(  e.originalTarget )
       .closest( 'form' )
         .find( 'input[type=submit]:first' )
           .click();
   }
 });

Assuming of course that .preventDefault() has not been called on the event.

Bottom line: If you have the event you can divine from it what element it came from and therefore which form it belongs to. Even in this case:

<input type="button" value="LOGIN" name="btnLoginOk" onclick="submit();">

Here submit() is a global function, but when it is called, its context (this) will be the element and you may do submit(e){ this.form.submit(); }.

The application has been designed so there are no submit buttons (as in input type="submit") and, instead, the designers have gone for onclick handling.

This sounds to me like the designer doesn't fully comprehend DOM / form events and is going the long way around the problem. Another likely reason could be that the program is old and was designed back when these things weren't quite as stable, or properly documented, as they are today.

Replace this:

<form action="/login/" method="POST">
  [...]
  <input type="button" value="LOGIN" name="btnLoginOk" onclick="submit();">
</form>

With this:

<form action="/login/" method="POST">
  [...]
  <input type="submit" value="LOGIN" name="btnLoginOk">
</form>

Then add a key handler to all forms that need it, that detects and suppresses enter if some condition is met (for the forms that you actually do want to disable this on).

// for all forms that POST that have 2+ submit buttons
$( 'form[method=post]:has(:submit:eq(1))' ).bind('keydown', function(e){
  // if target is an enter key, input element, and not a button
  if ( e.keyCode == 13 && e.target.tagName == 'INPUT' && 
       !/^(button|reset|submit)$/i.test( e.target.type ) ) {
    return false;  // kill event
  }
});

Or better still: Use a form validation library (or jQuery plugin) that knows how to do this for you.