The closest selector affects more than one element

I have an asp.net application that uses a grid control with three columns of checkboxes side by side. The boxes in the first column are included; the next two are disabled. I tried to write a JQuery function that will include an adjacent checkbox in the second column when the user checks the field in the first column. Here is my code:

<script type="text/javascript">
        $(document).ready(function() {
            $("[id$='FirstCheckBox']").click(function() {
                var td = $("td", $(this).closest("tr"));
                if ($(this).is(":checked")) {
                    $("input[type=checkbox]", td).prop("disabled", false);
                }
                else {
                    $("input[type=checkbox]", td).prop("disabled", true).prop("checked", false);
                    $(this).prop("disabled", false);
                }    
            });
        });
    </script>

      

This function works great when I only have two checkbox columns. But when I add a third column with the checkboxes disabled, the function also includes a field in that column. I thought the closest selector only selects one element, but it seems to select two. What am I doing wrong?

+3


source to share


2 answers


Instead of navigating to the parent element entirely tr

, just navigate to the closest one td

and find the next cell using the jQuery method next()

.

You can generalize this by changing your code to this:



<script type="text/javascript">
    $(document).ready(function() {
        $("#tableId").on('click', 'input:checkbox:not(:disabled)', function() {
            var $nextTd = $(this).closest("td").next('td');
            if (! $nextTd.length) { return; } // already in last column
            if ($(this).is(":checked")) {
                $("input[type=checkbox]", $nextTd).removeProp("disabled");
            }
            else {
                $("input[type=checkbox]", $nextTd)
                    .prop("disabled", 'disabled')
                    .removeProp("checked");
                $(this).removeProp("disabled");
            }    
        });
    });
</script>

      

+1


source


What if you set checkboxes to an array of item objects and use an index within the array to set which checkbox you want to enable / disable. I thought something like this: DEMO

var chx = $('input[type="checkbox"]');       // Store the elements
chx.change(function(){                       // Set the event listener
    var i = chx.index(this);                 // Get the index of the clicked element
    $(chx[i + 1]).prop('disabled', function(i, val){
        return !val;                         // Return the opposite state of the element indexed after the triggered element
    });
});

      

It has the advantage of being short and sweet, and allows you to manipulate the index rather than conditionals. I suppose you could add a legend if you want more control.

Here is an example of using a condition to restrict the functionality of certain elements in an array. This restricts events from any elements in the array after the first.

var chx = $('input[type="checkbox"]');
chx.change(function(){
    var i = chx.index(this);
    if(i == 0){
        $(chx[i + 1]).prop('disabled', function(i, val){
            return !val;
        });
    }
});

      



This is an even shorter version as you need it to be applied to the first checkbox, but it still allows you to skip DOM traversal.

var chx = $('input[type="checkbox"]');
$(chx[0]).change(function(){
    $(chx[1]).prop('disabled', function(i, val){
        return !val;
    });
});

      

I also updated the script to reflect this change.

Hope this helps! Let me know if you have any questions.

+1


source







All Articles