Saturday 20 October 2012

Press Enter to Submit

As is so often the case with my blog, this post is in response to repeated questions on the same topic on the Developerforce Discussion Boards. This is one that has been cropping up for 3-4 years now, and concerns form behaviour when pressing the enter key in an <apex:inputField/> or <apex:inputText/> component.

The only reference to the expected behaviour can be found in the HTML 2.0, which states:

When there is only one single-line text input field in a form, the user agent should accept Enter in that field as a request to submit the form.

Over the years browsers have interpreted the enter key in different ways. Early versions of Firefox required an <input type=’submit’> element in the form for the submission to take place. Internet explorer would submit the form but if there was only a single field it would omit the name/value from the submit button, but if there was more than one field the button information would be included.

Modern browsers now share common behaviour, in that the enter key is interpreted as a request to submit the form via the first submit button. However, if you want to use a different button to submit the form, or you have to contend with old (and unsupported) browsers you need another solution.

In my case, I have a form that is used to search for duplicate accounts before creation. This has a number of text input fields to capture the search criteria and a couple of buttons to clear the criteria or execute the search. A screenshot is show below:

Screen Shot 2012 10 20 at 11 17 25

When the user hits the enter key, I want to carry out the search via the second button rather than the first so the default browser behaviour won't work for me in this case.

The solution is to bind a javascript handler to the onkeypress event of each of the inputs. In my case I've named it 'noenter':

<apex:inputText id="name" value="{!searchCriteria.name}" onkeypress="return noenter(event);"/> 

the noenter function has some code at the end to get at the actual code of the key pressed, taking into account the number of different ways that browsers may present it, and then if the code is 13, aka the enter key, then the search button element is located on the form and its click method executed.  Note that if the enter key is detected, the function returns false - this is a vital part of the solution as it tells the browser not to continue with the default behaviour, which was to submit the form via the first button.  If false isn't returned, you are into an interesting race condition with two form submissions battling it out for supremacy.

    <script>
      function noenter(ev)
      {
         if (window.event)
         {
             ev=window.event;
         }
         
         var keyCode;
         if (ev.keyCode)
         {
            keyCode=ev.keyCode;
         }
         else
         {
            keyCode=ev.charCode;
         }
         
         if (keyCode == 13)
         {
            var ele=document.getElementById('{!$Component.form.crit_block.crit_section.searchbtn}');
            ele.click();
            return false;
         }
         else
         {
            return true;
         }
      }
   </script>

I've tested this on Chrome, Firefox, Opera and Safari and it behaves as expected - if you encounter any problems, please let me know via the comments section below.   

4 comments:

  1. Hi,

    I'm new to SF. So from my little experince no matter how many input fields in we have, on click Enter we will have Submit of it.
    And it will be submitted except that time's when we have not filled in required fields.
    To face with this I made jQuery code bind on onkeydown:

    < apex:inputField onkeydown="preventSubmit(event)" id="emailEnterInput"/ >
    < script>
    function preventSubmit(e){ // you can add here preventSubmit(e , someIdField), someIdField - where to tad focus
    if( e.which == 13 ){
    e.preventDefault();
    $("input[id*='inputSubject']").focus(); // inputSubject - next input
    }
    }
    < /script>

    Also you can use .bind insted of onkeydown="preventSubmit(event)" in apex.

    ReplyDelete
  2. Thank you for sharing this info. it works. :)

    ReplyDelete
  3. Is it possible to avoid enter keypress for the whole form. I have like 75-100 input fields in my page and I dont want to add this listener for each and every inputfield line - so like is it possible to have this at the form level or something?

    ReplyDelete