The World’s Leading Microsoft .NET Magazine
   
 
timstall

Donate Today!

Search Box

 

Calendar

««Jul 2009»»
SMTWTFS
    12
3
4
567891011
12131415161718
19202122232425
262728293031

My RSS Feeds








Mailing List

Most Popular Tags

                                                           

Multiple Onclick JavaScript Events on a Single Control

posted Friday, 3 June 2005

Change History: This post was updated on July 5, 2005. See Update at bottom.

You can't add two identical events to the same Html control. For example, if you have a button with an onclick event, and you add another onclick at the server, the second event will overwrite the first. This becomes a problem if you need to add an event to some variable control, but you don't know what events that control already has. However, .Net provides a way to handle this.

We can:

  1. See if the variable html control already has an onclick event.
  2. If it does, then dynamically register a new script that calls both the original onclick script as well as the new script.
  3. Replace the variable control's onclick value with that new script.

The following code snippets this. This first block shows a simple JavaScript (with a parameter) being called by a button's onclick event.

function DoStuff1(var1) {
    alert('1: ' + var1);
}

...

<INPUT id="Button1" onclick="DoStuff1('Hello1')" type="button" value="Button" name="Button1" runat="server">

...

This snippet shows the server code to check if an onclick event already exists, and add a new wrapper if needed. Note that it persists the onclick values in viewstate to ensure that the wrapper function doesn't wrap itself upon postback. For example, if the first onclick event called DoStuff1(), and we wanted to dynamically add a new onclick function DoStuff2(), we could create a wrapper function Wrapper1() that called both functions, and was called from the onclick. Wrapper1() becomes the new value of the button's onclick.

private void Page_Load(object sender, System.EventArgs e)
{
    string s = this.Button1.Attributes["onclick"];
    if (!Page.IsPostBack)
        OriginalJSFunction = s;
    if (s == null)
        this.Button1.Attributes.Add("onclick","DoStuff2()");
    else
    {
        if (!Page.IsClientScriptBlockRegistered("JS1"))
            Page.RegisterClientScriptBlock("JS1",GetJS(OriginalJSFunction));
        this.Button1.Attributes.Add("onclick","Wrapper1()");
    }
}

private string OriginalJSFunction
{
    get
    {
        object o = ViewState["OriginalJSFunction"];
        if (o == null)
            return "";
        else
            return o.ToString();
    }
    set
    {
        ViewState["OriginalJSFunction"] = value;
    }
}

private string GetJS(string strOriginalFn) //will handle initial JS with params
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    sb.Append(@"
        <script language='javascript'>
        function Wrapper1() {
        " + strOriginalFn + @";
        DoStuff2();
        }
        </script>
    ");

    return sb.ToString();
}

 While this approach is tedious, it lets you dynamically add an event to a control without overwriting that control's existing event. This is useful when making your own custom controls that integrate with existing Html controls already on the page.

UPDATE July 5, 2005

Since writing this post, I've come across a cleaner technique. You can run multiple JavaScripts simply by listing them in the onclick event:

 id="Button1" onclick="DoStuff1('Hello1');Method2();Method3()"

Therefore we can simplify our codebehind. This has two main changes: (1) It modifies OriginalJSFunction to append the ";" to the end of a non-function, (2) It then always adds an onclick method, as opposed to checking if there already exists an onclick method.

private void Page_Load(object sender, System.EventArgs e)
{
  string s = this.Button1.Attributes["onclick"];
  if (!Page.IsPostBack)
    OriginalJSFunction = s;
   
  this.Button1.Attributes.Add("onclick",OriginalJSFunction + ";DoStuff2()");
}

private string OriginalJSFunction
{
  get
  {
    object o = ViewState["OriginalJSFunction"];
    if (o == null)
      return "";
    else
      return o.ToString() + ";";
  }
  set
  {
    ViewState["OriginalJSFunction"] = value;
  }
}

links: digg this    technorati    




1. Chris left...
Sunday, 1 January 2006 5:05 am

That method you used to run multiple events under one onClick saved my life. I spent forever trying to figure out a way to make it do multiple things, like display a new picture, and erase an old one at the same time. Thanx a ton

Cw


2. Sudhir left...
Tuesday, 23 January 2007 11:09 am

How can i append an existing attribute. For example: cmd.Attributes.add("onClick","alert('Something.');"); Then how can i add another attribute appending to the existing onClick Attribute. Somthing like cmd.Attribute.Append("onClick","alert('Another thing')"); Which i know is wrong.. but i hope u got my point. Any one knows it. Say my thanks to him before he tells me :-) er_sudhir_yadav@gmail.com Sudhir Yadav


3. Sudhir left...
Tuesday, 23 January 2007 11:10 am

Sorry the mail id was incorrect Let me correct it, its: er.sudhir.yadav@gmail.com Sudhir Yadav


4. Tim Stall left...
Tuesday, 23 January 2007 9:59 pm

Hey Sudhir, you can "append" by (1) getting the original event's method, and then doing a string append to that. I mention this in the blog snippet:

private void Page_Load(object sender, System.EventArgs e) {

  • string s = this.Button1.Attributes;

  • if (!Page.IsPostBack)

    • OriginalJSFunction = s;

  • this.Button1.Attributes.Add("onclick",OriginalJSFunction + ";DoStuff2()");

}


5. Newbie left...
Sunday, 28 January 2007 1:47 pm :: http://www.vegetariansareevil.com

I am trying to run a routine which will insert an image and remove the text at the same time...

<a href="javascript:void(0); "onclick="document.execCommand('InsertImage',true)">Add your image</a>

Unfortunately, this puts the image in the middle of the text which says, "Add your image". How could I make it replace the text with the image?