Quirk in ASP.Net CheckBox class

I am writing a lot of javascript lately, and I ran into a quirk in the ASP.Net framework that caused a bit of frustration.

Let’s say we have a user interface requirement that calls for a checkbox to indicate using a default value. If the checkbox is not selected, then additional controls must be displayed to capture the non-default value. This is quite straight-forward with jQuery’s hide/show functions. This paradigm is repeated for numerous items on the page.

Since I don’t want to copy/paste javascript all over the place, I re-factored the script to have an onclick function for every checkbox:

DefaultSelector = {
  containerId: null,
 
  useDefaultClick: function (e) {
    if (e.checked) {
      $(e.id + "[related_control_id]").hide();
    } else {
      $(e.id + "[related_control_id]").show();
    }
  },
  initialize: function (containerId) {
    this.containerId = containerId;
    // attach an on-click event to the "use default" checkboxes
    $("#" + containerId + " input:checkbox").click(function () {
      DefaultSelector.useDefaultClick(this);
    });
  }
};

As you can see in the snippet, I need the id of the control to hide/show. In the server control code, I can use the ClientId property to get that value, but how do I get that value into the useDefaultClick function?

The easiest approach is to put the id into the html as a property. (This is called expando properties.) So, I used the Attributes property of the CheckBox class to add the related control id:

private CheckBox CreateUseDefaultControl(string id, string relatedControlId)
{
  CheckBox result = new CheckBox { ID = id };
  result.Text = "Use Default";
  result.TextAlign = TextAlign.Right;
  result.InputAttributes.Add("relatedcontrol", relatedControlId);
  return result;
}

Now, I just need to grab that property from the element that is clicked:

useDefaultClick: function (e) {
  if (e.checked) {
    $(e.relatedControl).hide();
  } else {
    $(e.relatedControl).show();
  }
},

However, it does not work! Digging into the html, I found this nice bit of malformed XHTML:

<SPAN relatedControl="ctl00_TextBox1">
    <INPUT id=ctl00_useDefault name=ctl00$useDefault value="" type=checkbox>
        <LABEL for=ctl00_useDefault>Use Default</LABEL>
</SPAN>

How nice of the CheckBox class to put the attribute in a containing element. Grrrrr!! The solution: the CheckBox class has to additional attribute collections – InputAttributes and LabelAttributes.