firefox | Dmytro Shteflyuk's Home https://kpumuk.info In my blog I'll try to describe about interesting technologies, my discovery in IT and some useful things about programming. Tue, 08 Sep 2015 00:01:45 +0000 en-US hourly 1 https://wordpress.org/?v=6.7.1 Using Panel.DefaultButton property with LinkButton control in ASP.NET https://kpumuk.info/asp-net/using-panel-defaultbutton-property-with-linkbutton-control-in-asp-net/ https://kpumuk.info/asp-net/using-panel-defaultbutton-property-with-linkbutton-control-in-asp-net/#comments Sat, 25 Aug 2007 10:53:42 +0000 http://kpumuk.info/asp-net/using-panel-defaultbutton-property-with-linkbutton-control-in-asp-net/ ASP.NET has great limitation — only one server form on the page. Even if you are developing complex page, which looks like several forms with different submit buttons, in fact you have only one form. So we have a problem: How browser understanding which button should be triggered when user pressed ENTER? It uses first […]

The post Using Panel.DefaultButton property with LinkButton control in ASP.NET first appeared on Dmytro Shteflyuk's Home.]]>
ASP.NET has great limitation — only one server form on the page. Even if you are developing complex page, which looks like several forms with different submit buttons, in fact you have only one form. So we have a problem: How browser understanding which button should be triggered when user pressed ENTER? It uses first Button control (usually that’s wrong), and if you have LinkButton‘s, they would never be triggered. In ASP.NET 2.0 new property has been added to the Panel and HtmlForm controls — DefaultButton, which can be used to specify ID of the control, which implements IButtonControl interface (usually Button and LinkButton). This button control would be triggered when user pressed ENTER. But there is one big problem exist: LinkButton control would not be triggered in Firefox on ENTER. In this article I will show why this problem take place and how to solve it.

Let’s look how DefaultButton is working in ASP.NET. Here is simple example:

1
2
3
4
5
<asp:Label runat="server" ID="lblHello" />
<asp:Panel runat="server">
    First name: <asp:TextBox runat="server" ID="txtFirstName" />
    <asp:LinkButton ID="lbHello" runat="server" Text="Click me" OnClick="lbHello_Click" />
</asp:Panel>
1
2
3
4
protected void lbHello_Click(object sender, EventArgs e)
{
    lblHello.Text = String.Format("Hello, {0}", txtFirstName.Text);
}

When you will try to press ENTER button inside the text box, form will be submitted to the server, but LinkButton‘s Click event will not be fired. Let’s try to specify DefaultButton property of the panel:

1
2
3
4
<asp:Panel runat="server" DefaultButton="lbHello">
    First name: <asp:TextBox runat="server" ID="txtFirstName" />
    <asp:LinkButton ID="lbHello" runat="server" Text="Click me" OnClick="lbHello_Click" />
</asp:Panel>

Great! It’s working perfectly in Internet Explorer, but what about Firefox? Oops, we found a problem. You could find solution at the end of the post, but first I want to show why this problem occurs. When you specify DefaultButton property, ASP.NET generates following code:

1
2
<div onkeypress="javascript:return WebForm_FireDefaultButton(event, 'lbHello')">
</div>

Here is WebForm_FireDefaultButton method, defined in ASP.NET JavaScript library:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function WebForm_FireDefaultButton(event, target) {
    if (event.keyCode == 13 && !(event.srcElement && (event.srcElement.tagName.toLowerCase() == "textarea"))) {
        var defaultButton;
        if (__nonMSDOMBrowser) {
            defaultButton = document.getElementById(target);
        }
        else {
            defaultButton = document.all[target];
        }
        if (defaultButton && typeof(defaultButton.click) != "undefined") {
            defaultButton.click();
            event.cancelBubble = true;
            if (event.stopPropagation) event.stopPropagation();
            return false;
        }
    }
    return true;
}

The problem occurs in the code typeof(defaultButton.click) != "undefined" — Firefox does not define click() method for the a element, so the form will be submitted without __EVENTTARGET parameter, and button will not be triggered. The simplest way to solve the problem is to define click() method for the a:

1
2
3
4
5
6
7
8
9
10
var b = document.getElementById('<%= lbHello.ClientID %>');
if (b && typeof(b.click) == 'undefined') {
    b.click = function() { 
        var result = true;
        if (b.onclick) result = b.onclick();
        if (typeof(result) == 'undefined' || result) {
            eval(b.getAttribute('href'));
        }
    }
}

Our click() method imitates a element behavior: first it calls onclick() method (OnClientClick attribute of the LinkButton), and if it returns false — stops processing. Then it evals href attribute (where ASP.NET puts __doPostBack call).

Let’s create custom control which encapsulates this logic:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using System;
using System.Web.UI.WebControls;

namespace App_Code
{
    public class LinkButtonDefault : LinkButton
    {
        protected override void OnLoad(System.EventArgs e)
        {
            Page.ClientScript.RegisterStartupScript(GetType(), "addClickFunctionScript",
                _addClickFunctionScript, true);

            string script = String.Format(_addClickScript, ClientID);
            Page.ClientScript.RegisterStartupScript(GetType(), "click_" + ClientID,
                script, true);
            base.OnLoad(e);
        }

        private const string _addClickScript = "addClickFunction('{0}');";

        private const string _addClickFunctionScript =
            @"  function addClickFunction(id) {{
            var b = document.getElementById(id);
            if (b && typeof(b.click) == 'undefined') b.click = function() {{
                var result = true; if (b.onclick) result = b.onclick();
                if (typeof(result) == 'undefined' || result) {{ eval(b.getAttribute('href')); }}
            }}}};"
;
    }
}

And corresponding .aspx file:

1
2
3
4
5
6
<%@ Register Namespace="App_Code" TagPrefix="ac" %>
<asp:Label runat="server" ID="lblHello" />
<asp:Panel runat="server" DefaultButton="lbHello">
    First name: <asp:TextBox runat="server" ID="txtFirstName" />
    <ac:LinkButtonDefault ID="lbHello" runat="server" Text="Click me" OnClick="lbHello_Click" />
</asp:Panel>

Of course, JavaScript code should be moved out from the C# code, but for my example it’s good enough. If you are using ASP.NET AJAX library, you should use ScriptManager.RegisterStartupScript method instead of ClientScriptManager.RegisterStartupScript.

Hope, this post will help you. Your comments are welcome.

The post Using Panel.DefaultButton property with LinkButton control in ASP.NET first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/asp-net/using-panel-defaultbutton-property-with-linkbutton-control-in-asp-net/feed/ 23