views:

2844

answers:

3

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 (opening and closing angle brackets omitted deliberately)

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.

+1  A: 

Fingers crossed this'll work

$(document).ready(function() {
  var focussed_form;
  $('input').focus(focus_form);
  $('input').blur(unfocus_form);
  $('textarea').focus(focus_form);
  $('textarea').blur(unfocus_form);
  $('select').focus(focus_form);
  $('select').blur(unfocus_form);

  $(document).keypress(function(e) {
    if(e.keyCode == 13) 
    {
      $(focussed_form).trigger('submit'); 
    }
  });

  function focus_form(){
    focussed_form = $(this).closest('form');
  }

  function unfocus_form(){
    focussed_form = NULL;
  }

});
wheresrhys
I think you can consolidate some of that with: $(['input','textarea','select']).focus(focus_form).end().blur(unfocus_form); // Not sure if that end is needed or will work
Matt
This is what I was thinking as well.
Dana the Sane
+2  A: 

I don't think you need jQuery or javascript for this. You can indeed detect which Form a user hits submit on, or even which submit button is hit (in case there are more than one submit button per form).

Here's the code you would use:

<form action="http://foo.com/uri" method="POST">
  <input type="submit" name="action1a" value="add" />
  <input type="submit" name="action1b" value="delete" />
</form>
<form action="http://foo.com/uri" method="POST">
  <input type="submit" name="action2a" value="add" />
  <input type="submit" name="action2b" value="delete" />
  <input type="submit" name="action2c" value="someOtherAction" />
</form>

Then for the form-processing script, you would simply check the name of the submit button, for example:

if (isset($_POST['action1a'])) ... // PHP syntax

Alternatively, you can use images as submit buttons, then you can use the same name for all the submit buttons and just check their values--you can also do this with normal submit buttons if every button has a unique value attribute.


Edit: One more method is to combine POST and GET values, i.e.:

<form action="http://foo.com/uri?form=1" method="POST">
  <input type="submit" name="action" value="add" />
  <input type="submit" name="action" value="delete" />
</form>
<form action="http://foo.com/uri?form=2" method="POST">
  <input type="submit" name="action" value="add" />
  <input type="submit" name="action" value="delete" />
</form>
Calvin
A: 

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.

Borgar
It all sounds like excellent advice. I will reserve some time early this week to try out the suggestions. Watch this space if I have any further comments! I will comment on how I get on, at least.
MysticBrook