Fixing the Enter Key on AHAH Forms

Update: I've modified the suggested JavaScript code to not break #autocomplete enter presses.

The #ahah element introduced in Drupal 6 makes setting up dynamic JavaScript-driven forms much simpler than with Drupal 5. To see this in action, take a look at the Poll module. When adding more choices to a form, clicking the "Add another choice" button doesn't reload the page if JavaScript is enabled. However, there is one problem with such a form: by adding a submit button above other submit elements, it becomes the default action when pressing the enter key. Unfortunately, browsers don't have a method to specify the default submit action, and usually just use the first submit element on the form. To see this issue, try pressing the enter key inside the Title field on a Poll node. The page reloads, and the JS-disabled fallback is executed, instead of the Preview action as may be expected.

This might be behaving as intended with the Poll module, but I wanted to ensure that the enter key action was consistent with a similar feature I was adding to the Skeleton Outline module. Most JavaScript code online will recommend doing something similar to the following:

function processKey(e) {
    if (null == e)
        e = window.event ;
    if (e.keyCode == 13)  {
        $("#foobar").click();
        return false;
    }
}

This can then be bound to the appropriate event handler on the form elements. This works perfectly for elements created during page load, but there doesn't seem to be a way to easily bind the function to elements inserted with AHAH. So, any additional textfields inserted would still trigger the unwanted action.

There's another, much simpler way to achieve the same effect on your forms. Include the following on your form page with drupal_add_js(), modified to match the ID's of your elements:

$(document).ready(function() {
  // If JS is enabled, then override the submit handler so that enter presses
  // on textfields don't trigger the no-JS fallback.
  $("form#skeleton-create-instance-form #edit-add-introduction").click(function (){
    // If any autocomplete fields are open, don't submit so the enter key can
    // be used to select an option.
    if ($("#autocomplete").length == 0) {
      $("form#skeleton-create-instance-form #edit-submit").click();
    }
    return false;
  });
});

If you actually click the submit button, the AHAH handler is called, avoiding the above function. When enter is pressed on a form element, the above click handler is called, which then calls the submit button we want to handle the action. False is returned to prevent a double submit. This won't help make submit buttons more consistent for those without JavaScript, but for the vast majority of users it's a very simple way to ensure consistency in your forms.

Comments

AHAH Helper

AHAH Helper also helps you alot in these issues.

as seen in following example from http://drupal.org/project/ahah_helper we have a little snippet from the example code. If I'm right this code makes sure of the Enter Key submit is submitted by the ajax call and not a new page load. Make sure you check that module because it really is a handy tool for AJAX Forms and it works splendidly :-)

$form['billing_info']['update_usage'] = array(
'#type' => 'submit',
'#value' => t('Update usage'),
// Note that we can simply use the generic submit callback provided by the
// ahah_helper module here!
// All it does, is set $form_state['rebuild'] = TRUE.
'#submit' => array('ahah_helper_generic_submit'),
// We set the 'no-js' class, which means this submit button will be hidden
// automatically by Drupal if JS is enabled.
'#attributes' => array('class' => 'no-js'),
);

Mousedown handler

I found that the click event didn't work (it still triggered the non-JS submit), but using the mousedown event worked to solve this problem:
$("#edit-submit").trigger("mousedown");