views:

149

answers:

4

Is there a way to detect when the disabled attribute of an input changes in JQuery. I want to toggle the style based on the value.

I can copy/paste the same enable/disable code for each change event (as I did below) but I was looking for a more generic approach.

Can I create a custom event that will monitor the disabled attribute of specified inputs?

Example:

 <style type="text/css">.disabled{ background-color:#dcdcdc; }</style>


<fieldset>
    <legend>Option 1</legend>
    <input type="radio" name="Group1" id="Radio1" value="Yes" />Yes
    <input type="radio" name="Group1" id="Radio2" value="No" checked="checked" />No
    <div id="Group1Fields" style="margin-left: 20px;">
        Percentage 1:
        <input type="text" id="Percentage1" disabled="disabled" /><br />
        Percentage 2:
        <input type="text" id="Percentage2" disabled="disabled" /><br />
    </div>
</fieldset>
<fieldset>
    <legend>Option 2</legend>
    <input type="radio" name="Group2" id="Radio3" value="Yes" checked="checked" />Yes
    <input type="radio" name="Group2" id="Radio4" value="No" />No
    <div id="Group2Fields" style="margin-left: 20px;">
        Percentage 1:
        <input type="text" id="Text1" /><br />
        Percentage 2:
        <input type="text" id="Text2" /><br />
    </div>
</fieldset>
<script type="text/javascript">
    $(document).ready(function () {

        //apply disabled style to all disabled controls
        $("input:disabled").addClass("disabled");

        $("input[name='Group1']").change(function () {
            var disabled = ($(this).val() == "No") ? "disabled" : "";
            $("#Group1Fields input").attr("disabled", disabled);

            //apply disabled style to all disabled controls
            $("input:disabled").addClass("disabled");

            //remove disabled style to all enabled controls
            $("input:not(:disabled)").removeClass("disabled");

        });
        $("input[name='Group2']").change(function () {
            var disabled = ($(this).val() == "No") ? "disabled" : "";
            $("#Group2Fields input").attr("disabled", disabled);

            //apply disabled style to all disabled controls
            $("input:disabled").addClass("disabled");

            //remove disabled style to all enabled controls
            $("input:not(:disabled)").removeClass("disabled");
        });           

    });
</script>
A: 

I assume that you want to enable the text inputs in the same fieldset, eh? Give this a try:

$('input[type="radio"]').change(function() {
  if (this.value == "No") {
    $('input[type="text"]', $(this).parents('fieldset')).attr('disabled', 'disabled');
  } else {
    $('input[type="text"]', $(this).parents('fieldset')).attr('disabled', '');
  }
});
Please re-read the question. I am looking to detect when the disabled attribute changes for any input on the page. I will have a significant number of inputs on the page and don't want to repeat the same logic in each change event handler.
Rokal
+1  A: 

Although there are more efficient ways of tackling this problem, one way of handling this is by running a function every xx seconds that will set the required CSS classes on disabled elements:

window.setInterval(1000,function() {
    $("input:disabled").addClass("disabled");
    $("input:enabled").removeClass("disabled");
});

This will check all input elements every second. But again, this is a VERY bad solution. You would be better off restructuring your code.

Without changing too much of your code and HTML, I would do something like this (didn't test it though):

$("input[name^=Group]").change(function () {
        var disabled = ($(this).val() == "No") ? "disabled" : "";
        var groupName = $(this).attr("name");

        $("#" + groupName + "Fields input")
             .attr("disabled", disabled)
             .addClass("disabled");

        //remove disabled style to all enabled controls
        $("input:enabled)").removeClass("disabled");
    });
Philippe Leybaert
Thanks for answering. I suppose your solution does work but it definitely seems like a hack. Hopefully, there is a better way!
Rokal
A: 

You can take advantage of your layout and make all of your handlers find things relatively, shortening all your current code this:

$(function() {
    $("input:disabled").addClass("disabled");

    $(":radio").change(function() {
        var disabled = this.checked && this.value == "No";
        $(this).siblings("div").find("input")
            .attr('disabled', disabled)
            .toggleClass('disabled', disabled);
    });
});

You can view a demo here, also since you know which class, elements and whether you want it on or off, you can use .toggleClass(class, bool) to shorten things up a but further. If you want this to be more precise, you can give those radio buttons a class, for example:

<input type="radio" name="Group1" id="Radio1" value="Yes" class="toggler" />

Then you can do $(".toggler") instead of $(":radio"), same for the div, you could give it a class and do .siblings(".fields") instead of .siblings("div")...the point is if your layout is consistent, use that to your advantage when DRY coding.

Nick Craver
Thanks for answering Nick. I am no so concerned with the DRYness of the code. This was only an example, and I don't think my layout would be flexible enough where this would work in all situations. I was hoping to use an eventing strategy to solve the problem.
Rokal
A: 

After further researching this issue, I stumbled upon a blog post by Rick Strahl in which we demonstrates a jQuery plug-in that allows for monitoring of CSS properties: jQuery CSS Property Monitoring Plug-in updated

Rokal