One of the fundamental problems with ASP.NET WebForms is the fact that you can only have one form per page. This jumps up and bites you when you have a set of fields and a button and you want the enter key to submit the form.

In ASP.NET 2.0 they came out with a "fix" for this. You can wrap your fields in a Panel and set the default button:

<asp:Panel ID="_pnlLogin" DefaultButton="_btnLogin" runat="server">
UserName: <asp:TextBox ID="_txtUserName" runat="server" />
Password: <asp:TextBox ID="_txtPassword" runat="server" />
<asp:LinkButton ID="_btnLogin" Text="Login" runat="server"/>
</asp:Panel>

Some of you will know limitation here. This works with a Button, but not a LinkButton. Let's see why. Here is the resulting HTML:

<div id="_pnlLogin" onkeypress="javascript:return WebForm_FireDefaultButton(event, &amp;#x27;_btnLogin&amp;#x27;)">
UserName: <input name="_txtUsername" type="text" id="_txtUsername" />
Password: <input name="ctl00$mainContent$_txtPassword" type="text" id="_txtPassword" />
<a id="_btnLogin" href="javascript:__doPostBack('_btnLogin','')">Login</a>
</div>


The Panel renders as a div, and on any key pressed will call WebForm_FireDefaultButton:

function WebForm_FireDefaultButton(event, target) {
    if (!__defaultFired &amp;&amp; event.keyCode == 13 &amp;&amp; !(event.srcElement &amp;&amp; (event.srcElement.tagName.toLowerCase() == "textarea"))) {
        var defaultButton;
        if (__nonMSDOMBrowser) {
            defaultButton = document.getElementById(target);
        } else {
            defaultButton = document.all[target];
        }
        if (defaultButton &amp;&amp; typeof(defaultButton.click) != "undefined") {
            __defaultFired = true;
            defaultButton.click();
            event.cancelBubble = true;
        if (event.stopPropagation) event.stopPropagation();
            return false;
        }
    }
    return true;
}


This method checks for the enter key and then calls click on the default button. All good except for one thing: the LinkButton renders as an "a" tag. Anchor tags don't have a click() method unfortunately. At least not in Firefox.

So let's fix it! I've recently been reading "Learning jQuery" which is a great book on this cool javascript library. I'll use jQuery instead of straight javascript as it is much easier to write cross browser code and it's a lot more concise. Plus there are heaps of plugins for it, and it's a pretty small download for your page.

I want to improve the markup of my page at the same time so I'll try to minimise the amount of server controls I use and get rid of that inline javascript call. My new aspx looks like this:

<div class="form">
UserName: <asp:TextBox ID="_txtUsername" runat="server" />
Password: <asp:TextBox ID="_txtPassword" runat="server" />
<asp:LinkButton ID="_btnLogin" Text="Login" runat="server" CssClass="form_submit"/>
</div>


So if I have a div with the class "form", the default submit button is the first element with the "form_submit" class. Nice, simple and unobtrusive.

Here's the javascript I ended up with:

$(document).ready(function(){
    var $btn = $('.form_submit');
    var $form = $btn.parents('.form');

    $form.keypress(function(e){
        if (e.which == 13 &amp;&amp; e.target.type != 'textarea') {
            if ($btn[0].type == 'submit')
                $btn[0].click();
            else
                eval($btn[0].href);
            return false;
        }
    });
});

Basically it's going to find any .form_submit elements, find a parent form, and add a keypress handler for the form. When the keypress is triggered, if it's the enter key and we're not in a textarea, we'll click the default submit button if it IS a button, if it's a link we'll Eval the href attribute, which is going to be our javascript postback call.

Cool, I can keep it tucked away in an js file include, and i've improved my markup.