-2

The problem I am having is that my JQuery checked event only seems to be working once. My aim is for textboxes to be enabled when the corresponding checkbox is checked. Here is a cut down version of the HTML:

<div class="row">
    <div class="form-group">
        <div class="col-lg-3 col-md-3 col-xs-3">
            <input type="checkbox" class="" id="forenameCheck" name="forenameCheck" onchange="valueChanged()"> 
            <label for="forename" class="control-label">Forename</label>
        </div>
        <div class="col-lg-7 col-md-7 col-xs-7">
            <input type="text" class="form-control" id="forename" disabled name="forename" placeholder="Forename">
        </div>
    </div>
</div>

<div class="row">
    <div class="form-group">
        <div class="col-lg-3 col-md-3 col-xs-3">
            <input type="checkbox" class="" id="surnameCheck" name="surnameCheck" onchange="valueChanged()"> 
            <label for="surname" class="control-label">Surname</label>
        </div>
        <div class="col-lg-7 col-md-7 col-xs-7">
            <input type="text" class="form-control" id="surname" disabled name="surname" placeholder="Surname">
        </div>
    </div>
</div>

and this is the JQuery:

function valueChanged()
{
    if($("#forenameCheck").is(":checked")){
        $("#forename").prop("disabled",false);
    }
    else{
        $("#forename").prop("disabled",true);
    }


    if($("#surnameCheck").is(":checked")){
        $("#surname").prop("disabled",false);
    }
    else{
        $("#surname").prop("disabled",true);
    }
}

I am very new to JQuery and have no idea why this isn't working. "Forename" works fine but "Surname" does not. This is the JSFiddle of the code. What's strange is that it does not work at all on JSFiddle. It's also worth noting that i'm using bootstrap with this too.

If anyone can help it would be much appreciated!

Tom Nulty
  • 97
  • 3
  • 13

4 Answers4

2

I would handle each element separately.

$("#forenameCheck").change(function() {
    var isDisabled = !$(this).is(":checked");
    $("#forename").prop("disabled", isDisabled);
});
Dave
  • 3,658
  • 1
  • 16
  • 9
  • Please don't use jQuery for that, `!$(this).is(`:checked')`? Why would you not just use the DOM: `!this.checked`, it's available in every browser, doesn't require use of a library and is faster/cheaper because it doesn't need a library and returns the same Boolean. – David Thomas Feb 28 '15 at 17:37
1

It would be better to handle each element separately in your case. Here is the code:

$("#forenameCheck").change(function() {
    var isDisabled = !$(this).is(":checked");
    $("#forename").prop("disabled", isDisabled);
});

$("#surnameCheck").change(function() {
    var isDisabled = !$(this).is(":checked");
    $("#surname").prop("disabled", isDisabled);
});

Here is an updated JSFiddle

Update

I just tried the following code (not in JSFiddle, just in a plain html file) and it works.

<script type='text/javascript' src='http://code.jquery.com/jquery-compat-git.js'></script>
<script>
function valueChanged()
{
    if($("#forenameCheck").is(":checked")){
        $("#forename").prop("disabled",false);
    }
    else{
        $("#forename").prop("disabled",true);
    }


    if($("#surnameCheck").is(":checked")){
        $("#surname").prop("disabled",false);
    }
    else{
        $("#surname").prop("disabled",true);
    }
}
</script>
<div class="row">
    <div class="form-group">
        <div class="col-lg-3 col-md-3 col-xs-3">
            <input type="checkbox" class="" id="forenameCheck" name="forenameCheck" onchange="valueChanged()"> 
            <label for="forename" class="control-label">Forename</label>
        </div>
        <div class="col-lg-7 col-md-7 col-xs-7">
            <input type="text" class="form-control" id="forename" disabled name="forename" placeholder="Forename">
        </div>
    </div>
</div>

<div class="row">
    <div class="form-group">
        <div class="col-lg-3 col-md-3 col-xs-3">
            <input type="checkbox" class="" id="surnameCheck" name="surnameCheck" onchange="valueChanged()"> 
            <label for="surname" class="control-label">Surname</label>
        </div>
        <div class="col-lg-7 col-md-7 col-xs-7">
            <input type="text" class="form-control" id="surname" disabled name="surname" placeholder="Surname">
        </div>
    </div>
</div>

It seems it is not working in JSFiddle because of how the code is loaded in it. It is giving the following JavaScript error:

Uncaught ReferenceError: valueChanged is not defined

If you view the source of the JSFiddle output you will see that the JavaScript code is wrapped in window.onload=function(){ and this might be causing issues.

Virendra
  • 2,560
  • 3
  • 23
  • 37
  • Thanks a lot! It works :) I'm just wondering if you know why it doesn't work my way? (using onchange etc). – Tom Nulty Feb 28 '15 at 17:16
  • I just tried your code and it works if you remove `()` at the end of your jQuery calls. It does not works in JSFiddle, probably because of the way how JSFiddle loads the code. in JSFiddle you get a JavaScript error: `Uncaught ReferenceError: valueChanged is not defined`. – Virendra Feb 28 '15 at 17:22
  • @Nicael: if you feel the answer is too complicated feel free to down-vote, or, ideally, explain the complexity and why it's a problem. Tom: to explain why it doesn't work your way, we'd need to see your code (without the extraneous 'automatically-inserted' parenetheses). Can you copy and paste that code into your question? Because as it is you seem to have accepted an answer that doesn't answer the question you tried to ask (which is, of course, your prerogative). – David Thomas Feb 28 '15 at 17:24
  • It seems your code also works, I updated my answer with more details. – Virendra Feb 28 '15 at 17:28
  • Nice copy and paste on my answer. – Dave Feb 28 '15 at 17:33
  • @DavidThomas I accepted the answer because it solves my problem. Plus, it seems like a better way to go about my problem. – Tom Nulty Feb 28 '15 at 17:38
  • As noted, it's entirely your prerogative. But I'm personally more interested in solving, or at least explaining/addressing, the problem you reported about your code not working, which we can't reproduce without the code that you attempted to use. However I will say that every posted solution, so far, is unnecessarily complex and repetitive. – David Thomas Feb 28 '15 at 17:41
  • @DavidThomas I have edited my question to remove the extra parentheses. If a less complex answer is submitted I will accept that answer. – Tom Nulty Feb 28 '15 at 17:49
0

Your code is far too complicated. Replace onchange="valueChanged()" with onchange="valueChanged(this)" and use this javascript:

function valueChanged(button) {
     button.parentNode.nextElementSibling.childNodes[1].disabled=!button.checked;
}

Result:

function valueChanged(button) {
    button.parentNode.nextElementSibling.childNodes[1].disabled=!button.checked;
}
<div class="row">
    <div class="form-group">
        <div class="col-lg-3 col-md-3 col-xs-3">
            <input type="checkbox" class="" id="forenameCheck" name="forenameCheck" onchange="valueChanged(this)"> 
            <label for="forename" class="control-label">Forename</label>
        </div>
        <div class="col-lg-7 col-md-7 col-xs-7">
            <input type="text" class="form-control" id="forename" disabled name="forename" placeholder="Forename">
        </div>
    </div>
</div>

<div class="row">
    <div class="form-group">
        <div class="col-lg-3 col-md-3 col-xs-3">
            <input type="checkbox" class="" id="surnameCheck" name="surnameCheck" onchange="valueChanged(this)"> 
            <label for="surname" class="control-label">Surname</label>
        </div>
        <div class="col-lg-7 col-md-7 col-xs-7">
            <input type="text" class="form-control" id="surname" disabled name="surname" placeholder="Surname">
        </div>
    </div>
nicael
  • 18,550
  • 13
  • 57
  • 90
0

While we're unable to answer the question of "why isn't my code working," since the code in your question is apparently dissimilar to the code you attempted to type1, I'd like to offer a simple plain JavaScript alternative to the posted solutions.

This approach binds the event-handler using JavaScript itself, in order for easier future maintenance (since it prevents having to search the HTML to update the function calls) and applies the same function to each of the check-boxes. This approach allows for the same function to handle the change event of each check-box, rather than individually binding a change event-handler to every check-box element on the page, which is unnecessarily repetitive (and rapidly inflates the document size).

This is dependant upon the relationship of the check-box ids and their associated <input /> elements' id (though an alternative, below, is posted which uses the structure of the HTML):

// re-naming the function according what it does, this is
// entirely personal, so change, or revert, according to taste:
function changeToggle() {
  // the changed check-box ('this' is passed in
  // via the use of addEventListener(), later:
  var checkbox = this,
      // replacing the 'Check' from the element's id
      // with an empty string (to get the id of the 
      // associated <input />:
      id = checkbox.id.replace('Check', ''),
      // retrieving the associated <input />:
      input = document.getElementById(id);

  // updating the disabled property of the <input />,
  // to be the opposite of the checked state of
  // the check-box:
  input.disabled = !checkbox.checked;

}

// retrieving all <input /> elements that are descendants of
// an element with the class of 'row':
var checkboxes = document.querySelectorAll('.row input[type=checkbox]');

// using Array.prototype.forEach, and Function.prototype.call,
// to iterate over the NodeList returned by querySelectorAll():    
Array.prototype.forEach.call(checkboxes, function(check) {
  // check is the array-element of the array we're currently
  // iterating, in this case the check-box nodes; here we're
  // binding a change event-handler, naming the function
  // created earlier:
  check.addEventListener('change', changeToggle);
});

function changeToggle() {
  var checkbox = this,
    id = checkbox.id.replace('Check', ''),
    input = document.getElementById(id);

  input.disabled = !checkbox.checked;

}

var checkboxes = document.querySelectorAll('.row input[type=checkbox]');

Array.prototype.forEach.call(checkboxes, function(check) {
  check.addEventListener('change', changeToggle);
});
<div class="row">
  <div class="form-group">
    <div class="col-lg-3 col-md-3 col-xs-3">
      <input type="checkbox" class="" id="forenameCheck" name="forenameCheck" />
      <label for="forename" class="control-label">Forename</label>
    </div>
    <div class="col-lg-7 col-md-7 col-xs-7">
      <input type="text" class="form-control" id="forename" disabled name="forename" placeholder="Forename" />
    </div>
  </div>
</div>

<div class="row">
  <div class="form-group">
    <div class="col-lg-3 col-md-3 col-xs-3">
      <input type="checkbox" class="" id="surnameCheck" name="surnameCheck" />
      <label for="surname" class="control-label">Surname</label>
    </div>
    <div class="col-lg-7 col-md-7 col-xs-7">
      <input type="text" class="form-control" id="surname" disabled name="surname" placeholder="Surname" />
    </div>
  </div>
</div>

To use the HTML structure, particularly that the <label> for the associated <input /> is the next element-sibling to the check-box:

function changeToggle() {
  var checkbox = this,
      // retrieving the nextElementSibling (the first
      // element that follows as a sibling, rather than
      // nextSibling, which includes comment, and text,
      // nodes):
      label = checkbox.nextElementSibling,
      // accessing the HTMLLabelElement's htmlFor
      // property, to retrieve the string from its
      // 'for' attribute (getAttribute('for') would
      // also work):
      id = label.htmlFor,
      input = document.getElementById(id);

  // as above:
  input.disabled = !checkbox.checked;

}

function changeToggle() {
  var checkbox = this,
    label = checkbox.nextElementSibling,
    id = label.htmlFor,
    input = document.getElementById(id);

  input.disabled = !checkbox.checked;

}

var checkboxes = document.querySelectorAll('.row input[type=checkbox]');

Array.prototype.forEach.call(checkboxes, function(check) {
  check.addEventListener('change', changeToggle);
});
<div class="row">
  <div class="form-group">
    <div class="col-lg-3 col-md-3 col-xs-3">
      <input type="checkbox" class="" id="forenameCheck" name="forenameCheck" />
      <label for="forename" class="control-label">Forename</label>
    </div>
    <div class="col-lg-7 col-md-7 col-xs-7">
      <input type="text" class="form-control" id="forename" disabled name="forename" placeholder="Forename" />
    </div>
  </div>
</div>

<div class="row">
  <div class="form-group">
    <div class="col-lg-3 col-md-3 col-xs-3">
      <input type="checkbox" class="" id="surnameCheck" name="surnameCheck" />
      <label for="surname" class="control-label">Surname</label>
    </div>
    <div class="col-lg-7 col-md-7 col-xs-7">
      <input type="text" class="form-control" id="surname" disabled name="surname" placeholder="Surname" />
    </div>
  </div>
</div>

References:


Footnotes:

  1. Your comment, below the question, addressing Pointy:

@Pointy Thank you for pointing that out. I didn't see that there. The text editor must have automatically put them there as I was typing.

Source.

Community
  • 1
  • 1
David Thomas
  • 249,100
  • 51
  • 377
  • 410