views:

1313

answers:

2

I would like to apply some logic to a page containing a CheckBoxList control when the user checks or unchecks individual checkbox items. Say, for instance to dynamically show or hide a related control.

I came up with a way using ASP.Net 2.0 callback mechanism (AJAX) with a combination of client-side Javascript and server-side logic in the code-behind. However, this solution is not very bullet-proof (i.e. most likely suffers from timing issues). It is not portable, because the code needs to know the sequential ids of individual items, etc.

The code I came up with is separated in two functions, one handling the onclick event, and the other processing the returned callback string :

<script type="text/javascript">

function OnCheckBoxClicked()
{
    // gathers the semi-colon separated list of labels,
    // associated with the currently checked items

    var texts = '';

    // iterate over each individual checkbox item
    // items in a checkboxlist are sequential, so
    // stop iteration at the first missing sequence number

    for (var index = 0; index < 99; index++)
    {
        var checkbox = document.getElementById('ctl00_cphAdmin_cblCategories_' + index);
        if (checkbox == null)
            break;

        if (checkbox.checked)
        {

            // find label associated with the current checkbox item

            var labels = document.getElementsByTagName('label');
            for (var index_ = 0; index_ < labels.length; index_ ++)
            {
                if (labels[index_].htmlFor == checkbox.id)
                {
                    texts = texts + labels[index_].innerHTML + ';';
                    break;
                }
            }
        }
    }

    // perform callback request
    // result will be processed by the UpdateCheckBoxes function

    WebForm_DoCallback('__Page', '_checkbox' + texts, UpdateCheckBoxes, 'checkbox', null, true /* synchronous */);
}
</script>

In this example, my checkboxes match categories of a blog post.

I need to process the resulting callback string as containing a list of semicolon-separated names of checkboxes to check/uncheck, in order to make sure that related parent/child categories are synchronized correctly. This string results from logic executed on the server.

In other cases, the resulting callback string might be something else.

<script type="text/javascript">

function UpdateCheckBoxes(returnmessage, context)
{
    if (returnmessage == null || returnmessage == '')
        return ;

    // iterate over each individual checkbox item
    // items in a checkboxlist are sequential, so
    // stop iteration at the first missing sequence number

    for (var index = 0; index < 99; index++)
    {
        var checkbox = document.getElementById('ctl00_cphAdmin_cblCategories_' + index);
        if (checkbox == null)
            break;

        // find label associated with the current checkbox item

        var label = '';
        var labels = document.getElementsByTagName('label');
        for (var index_ = 0; index_ < labels.length; index_ ++)
        {
            if (labels[index_].htmlFor == checkbox.id)
            {
                label = ';' + labels[index_].innerHTML + ';';
                break;
        }
    }

        // perform custom processing based on the contents
        // of the returned callback string

        // for instance, here we check whether the returnmessage
        // contains the string ';' + label + ';'


        if (returnmessage.indexOf(label, 1) > 0)
        {
            // do something
        }        
    }
}

</script>

Isn't there a more elegant solution to this problem?

+1  A: 

I'd do a couple of things. One, I'd figure out a way to pass the value that needs to be passed back to the client-side onclick handler. Depending on how you are populating your CheckBoxList, this might be as simple as adding an "onclick" attribute to the ListItem for that checkbox that calls your function with the same value assigned to the label, say 'OnCheckBoxClicked(this,'Label'). That would eliminate the need to derive the label, although you could probably do this on the client side as well pretty easily by referencing the previous element of the checkbox if you just passed a reference to it (or parent, maybe, depends on whether the label precedes the input or the input is contained in it).

Two, I would also change it so that it only passes back the current item that is being clicked and handle them one at a time.

Assuming that you checkboxes (when rendered) look something like:

  <label for="something">CheckBox 1</label>
  <input type='checkbox' id='ctl00_....' value='1' onclick="OnCheckBoxClicked(this,'CheckBox_1');" />

Your functions might look like:

function OnCheckBoxClicked(checkbox,identifier)
{
  // do something based on the checkbox clicked

  WebForm_DoCallback('__Page', identifer, UpdateCheckBoxes, {checkbox: checkbox.id, label: identifier } , null, true /* synchronous */);
}

function UpdateCheckBoxes(result,context)
{
   var checkbox = document.getElementById(context.checkbox);
   var identifier = context.label;

   if (result)  // AJAX method now returns true/false as context holds info on controls
   {
       ... do something...
   }
}
tvanfosson
A: 

you can add an event to the checkbox control on the onclick() event. and send the id of the control as a parameter and then update the attributes of the desired control

<input type='checkbox' id='ctl00_....' value='1' onclick="OnCheckBoxClicked('ctrl_toUpdateID');" />



<script type="text/javascript">

function OnCheckBoxClicked(ctrlID)
{
  var ctrl = document.getElementById(ctrlID);
  if(ctrl.getAttribute('disabled')
 ctrl.removeAttribute('disabled')
else
    ctrl.setAttribute('disabled','disabled')


}
</script>
Oscar Cabrero