views:

399

answers:

2

I am trying to modify an open source Forum called YetAnotherForum.net in the project they have a custom user control called Yaf:ThemeButton. Now its rendered as an anchor with an onclick method in this code

ThemeButton.cs

 using System;
 using System.Web.UI;
 using System.Web.UI.WebControls;

 namespace YAF.Controls
 {
 /// <summary>
 /// The theme button.
 /// </summary>
 public class ThemeButton : BaseControl, IPostBackEventHandler
{
/// <summary>
/// The _click event.
/// </summary>
protected static object _clickEvent = new object();

/// <summary>
/// The _command event.
/// </summary>
protected static object _commandEvent = new object();

/// <summary>
/// The _attribute collection.
/// </summary>
protected AttributeCollection _attributeCollection;

/// <summary>
/// The _localized label.
/// </summary>
protected LocalizedLabel _localizedLabel = new LocalizedLabel();

/// <summary>
/// The _theme image.
/// </summary>
protected ThemeImage _themeImage = new ThemeImage();

/// <summary>
/// Initializes a new instance of the <see cref="ThemeButton"/> class.
/// </summary>
public ThemeButton()
  : base()
{
  Load += new EventHandler(ThemeButton_Load);
  this._attributeCollection = new AttributeCollection(ViewState);
}

/// <summary>
/// ThemePage for the optional button image
/// </summary>
public string ImageThemePage
{
  get
  {
    return this._themeImage.ThemePage;
  }

  set
  {
    this._themeImage.ThemePage = value;
  }
}

/// <summary>
/// ThemeTag for the optional button image
/// </summary>
public string ImageThemeTag
{
  get
  {
    return this._themeImage.ThemeTag;
  }

  set
  {
    this._themeImage.ThemeTag = value;
  }
}

/// <summary>
/// Localized Page for the optional button text
/// </summary>
public string TextLocalizedPage
{
  get
  {
    return this._localizedLabel.LocalizedPage;
  }

  set
  {
    this._localizedLabel.LocalizedPage = value;
  }
}

/// <summary>
/// Localized Tag for the optional button text
/// </summary>
public string TextLocalizedTag
{
  get
  {
    return this._localizedLabel.LocalizedTag;
  }

  set
  {
    this._localizedLabel.LocalizedTag = value;
  }
}

/// <summary>
/// Defaults to "yafcssbutton"
/// </summary>
public string CssClass
{
  get
  {
    return (ViewState["CssClass"] != null) ? ViewState["CssClass"] as string : "yafcssbutton";
  }

  set
  {
    ViewState["CssClass"] = value;
  }
}

/// <summary>
/// Setting the link property will make this control non-postback.
/// </summary>
public string NavigateUrl
{
  get
  {
    return (ViewState["NavigateUrl"] != null) ? ViewState["NavigateUrl"] as string : string.Empty;
  }

  set
  {
    ViewState["NavigateUrl"] = value;
  }
}

/// <summary>
/// Localized Page for the optional link description (title)
/// </summary>
public string TitleLocalizedPage
{
  get
  {
    return (ViewState["TitleLocalizedPage"] != null) ? ViewState["TitleLocalizedPage"] as string : "BUTTON";
  }

  set
  {
    ViewState["TitleLocalizedPage"] = value;
  }
}

/// <summary>
/// Localized Tag for the optional link description (title)
/// </summary>
public string TitleLocalizedTag
{
  get
  {
    return (ViewState["TitleLocalizedTag"] != null) ? ViewState["TitleLocalizedTag"] as string : string.Empty;
  }

  set
  {
    ViewState["TitleLocalizedTag"] = value;
  }
}

/// <summary>
/// Non-localized Title for optional link description
/// </summary>
public string TitleNonLocalized
{
  get
  {
    return (ViewState["TitleNonLocalized"] != null) ? ViewState["TitleNonLocalized"] as string : string.Empty;
  }

  set
  {
    ViewState["TitleNonLocalized"] = value;
  }
}

/// <summary>
/// Gets Attributes.
/// </summary>
public AttributeCollection Attributes
{
  get
  {
    return this._attributeCollection;
  }
}

/// <summary>
/// Gets or sets CommandName.
/// </summary>
public string CommandName
{
  get
  {
    if (ViewState["commandName"] != null)
    {
      return ViewState["commandName"].ToString();
    }

    return null;
  }

  set
  {
    ViewState["commandName"] = value;
  }
}

/// <summary>
/// Gets or sets CommandArgument.
/// </summary>
public string CommandArgument
{
  get
  {
    if (ViewState["commandArgument"] != null)
    {
      return ViewState["commandArgument"].ToString();
    }

    return null;
  }

  set
  {
    ViewState["commandArgument"] = value;
  }
}

#region IPostBackEventHandler Members

/// <summary>
/// The i post back event handler. raise post back event.
/// </summary>
/// <param name="eventArgument">
/// The event argument.
/// </param>
void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
{
  OnCommand(new CommandEventArgs(CommandName, CommandArgument));
  OnClick(EventArgs.Empty);
}

#endregion

/// <summary>
/// Setup the controls before render
/// </summary>
/// <param name="sender">
/// </param>
/// <param name="e">
/// </param>
private void ThemeButton_Load(object sender, EventArgs e)
{
  if (!String.IsNullOrEmpty(this._themeImage.ThemeTag))
  {
    // add the theme image...
    Controls.Add(this._themeImage);
  }

  // render the text if available
  if (!String.IsNullOrEmpty(this._localizedLabel.LocalizedTag))
  {
    Controls.Add(this._localizedLabel);
  }
}

/// <summary>
/// The render.
/// </summary>
/// <param name="output">
/// The output.
/// </param>
protected override void Render(HtmlTextWriter output)
{
  // get the title...
  string title = GetLocalizedTitle();

  output.BeginRender();
  output.WriteBeginTag("a");
  output.WriteAttribute("id", ClientID);
  if (!String.IsNullOrEmpty(CssClass))
  {
    output.WriteAttribute("class", CssClass);
  }

  if (!String.IsNullOrEmpty(title))
  {
    output.WriteAttribute("title", title);
  }
  else if (!String.IsNullOrEmpty(TitleNonLocalized))
  {
    output.WriteAttribute("title", TitleNonLocalized);
  }

  if (!String.IsNullOrEmpty(NavigateUrl))
  {
    output.WriteAttribute("href", NavigateUrl.Replace("&", "&amp;"));
  }
  else
  {
    // string.Format("javascript:__doPostBack('{0}','{1}')",this.ClientID,""));
    output.WriteAttribute("href", Page.ClientScript.GetPostBackClientHyperlink(this, string.Empty));
  }

  bool wroteOnClick = false;

  // handle additional attributes (if any)
  if (this._attributeCollection.Count > 0)
  {
    // add attributes...
    foreach (string key in this._attributeCollection.Keys)
    {
      // get the attribute and write it...
      if (key.ToLower() == "onclick")
      {
        // special handling... add to it...
        output.WriteAttribute(key, string.Format("{0};{1}", this._attributeCollection[key], "this.blur();this.display='none';"));
        wroteOnClick = true;
      }
      else if (key.ToLower().StartsWith("on") || key.ToLower() == "rel" || key.ToLower() == "target")
      {
        // only write javascript attributes -- and a few other attributes...
        output.WriteAttribute(key, this._attributeCollection[key]);
      }
    }
  }

  // IE fix
  if (!wroteOnClick)
  {
      output.WriteAttribute("onclick", "this.blur();this.style.display='none';");
  }

  output.Write(HtmlTextWriter.TagRightChar);

  output.WriteBeginTag("span");
  output.Write(HtmlTextWriter.TagRightChar);

  // render the optional controls (if any)
  base.Render(output);
  output.WriteEndTag("span");

  output.WriteEndTag("a");
  output.EndRender();
}

/// <summary>
/// The get localized title.
/// </summary>
/// <returns>
/// The get localized title.
/// </returns>
protected string GetLocalizedTitle()
{
  if (Site != null && Site.DesignMode == true && !String.IsNullOrEmpty(TitleLocalizedTag))
  {
    return String.Format("[TITLE:{0}]", TitleLocalizedTag);
  }
  else if (!String.IsNullOrEmpty(TitleLocalizedPage) && !String.IsNullOrEmpty(TitleLocalizedTag))
  {
    return PageContext.Localization.GetText(TitleLocalizedPage, TitleLocalizedTag);
  }
  else if (!String.IsNullOrEmpty(TitleLocalizedTag))
  {
    return PageContext.Localization.GetText(TitleLocalizedTag);
  }

  return null;
}

/// <summary>
/// The on click.
/// </summary>
/// <param name="e">
/// The e.
/// </param>
protected virtual void OnClick(EventArgs e)
{
  var handler = (EventHandler) Events[_clickEvent];
  if (handler != null)
  {
    handler(this, e);
  }
}

/// <summary>
/// The on command.
/// </summary>
/// <param name="e">
/// The e.
/// </param>
protected virtual void OnCommand(CommandEventArgs e)
{
  var handler = (CommandEventHandler) Events[_commandEvent];

  if (handler != null)
  {
    handler(this, e);
  }

  RaiseBubbleEvent(this, e);
}

/// <summary>
/// The click.
/// </summary>
public event EventHandler Click
{
  add
  {
    Events.AddHandler(_clickEvent, value);
  }

  remove
  {
    Events.RemoveHandler(_clickEvent, value);
  }
}

/// <summary>
/// The command.
/// </summary>
public event CommandEventHandler Command
{
  add
  {
    Events.AddHandler(_commandEvent, value);
  }

  remove
  {
    Events.RemoveHandler(_commandEvent, value);
  }
}
}
}

now that is just cs file its handled like this in the .ascx page of the actual website

   <YAF:ThemeButton ID="Save" runat="server" CssClass="yafcssbigbutton leftItem" TextLocalizedTag="SAVE"
OnClick="Save_Click" />

now it is given an OnClick codebehind function that does some serverside function like this

  protected void Save_Click(object sender, EventArgs e)
  {
    //some serverside code here
  }

now I have a problem with the user being able to click multiple times and firing that serverside function multiple times. I have added in the code as of right now an extra onclick="this.style.display='none'" in the .cs code but that is a ugly fix I was wondering if anyone would have a better idea of disabling the ThemeButton clientside?? pls any feedback if I need to give more examples or further explain the question thanks.

A: 

I would try to place an OnClientClick in your button tag.

 <YAF:ThemeButton ID="Save" runat="server" CssClass="yafcssbigbutton leftItem" TextLocalizedTag="SAVE" OnClick="Save_Click" OnClientClick="this.disabled = true;" /> 

This should disable the button once clicked. Once the page reloads form the postBack, the button will be enabled again. Even though this is a custom control to YAF, it probably inheirits from the standard asp:button control which has the OnClienClick attribute.

Just some more info: MSDN

Tommy
nope it doesnt have an onclientclick method
Laurence Burke
+1  A: 

You could do something like this:

function disableClick(domNode) {
    // replace onclick event handler with a "return false"
    domNode.onclick = function() { return false; }

    // have a CSS class 'button-disabled' to set the text colour or whatever
    domNode.className = "button-disabled";
}

...

<a href="..." onclick="whatever; disableClick(this); return true;">click me</a>

That is, set the onclick handler to a function that simply returns false. This is assuming that the <YAF:ThemeButton> control renders as an <a> tag...

Dean Harding
it is rendered as an anchor but it also has an OnClick serverside method
Laurence Burke
output.WriteAttribute("onclick", "this.blur();this.onclick = function(){return false;};return true;"); so I took what you have there and just put it the render function and it works it changes the onclick function to return false so it only fires once serverside THANKS
Laurence Burke