2

I would like to bind the same event to 3 checkboxes but with a different target each time:

  var checkboxes = {
    'selector1' : 'target1',
    'selector2' : 'target2',
    'selector3' : 'target3',
  };

  for (selector in checkboxes) {
    var target = checkboxes[selector];

    if (jQuery(selector).is(':checked')) {
      jQuery(target).show();
    }
    else {
      jQuery(target).hide();
    }

    jQuery(selector).bind('change', function() {
      if ($(this).is(':checked')) {
        jQuery(target).show();
      }
      else {
        jQuery(target).hide();
      }
    });
  };

But it doesn't work: on "change", the 3 selectors show/hide the 3rd target.

3
  • 1
    That construct {'key': 'value'...} is called an Object Literal in JavaScript, not an associative array. Commented Jan 31, 2012 at 14:21
  • What do target1, etc refer to? Checkbox id attributes? Commented Jan 31, 2012 at 14:23
  • 1
    @Michael: Well, the syntax is called an object literal. The code creates an object, which is an associative array. Commented Jan 31, 2012 at 14:24

3 Answers 3

3

That's because the code in the event handler will use the variable target, not the value of the variable as it was when the event handler was created. When the event hander runs, the variable will contain the last value used in the loop.

Use an anonymous function to create a closure, that captures the value of the variable:

for (selector in checkboxes) {
  var target = checkboxes[selector];

  if (jQuery(selector).is(':checked')) {
    jQuery(target).show();
  } else {
    jQuery(target).hide();
  }

  (function(target){

    jQuery(selector).bind('change', function() {
      if ($(this).is(':checked')) {
        jQuery(target).show();
      } else {
        jQuery(target).hide();
      }
    });

  })(target);

};

Side note: You can use the toggle method to make the code simpler:

for (selector in checkboxes) {
  var target = checkboxes[selector];

  jQuery(target).toggle(jQuery(selector).is(':checked'));

  (function(target){

    jQuery(selector).bind('change', function() {
      jQuery(target).toggle($(this).is(':checked'));
    });

  })(target);

};
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much, it works nice (and thanks for the toggle too)
2

It doesn't work because target isn't scoped inside of a function. Blocks DO NOT provide scope in javascript.

But I've reduced it down for you and hopefully this will work out:

$.each(checkboxes, function(selector, target) {
   $(selector).change(function () {
       $(target).toggle($(selector).is(':checked'));
   }).trigger('change');
});

1 Comment

Provided of course that there is no other code that uses the change event on those elements, as you trigger the event when there is no change.
0

target scope is the problem !

You could have simpler code:

  • use data for the handler
  • use .toggle(condition)

    $.each(checkboxes, function(selector, target) {
        $(selector).on('change', {target:target}, function (evt) {
            $(evt.data.target).toggle($(this).is(':checked'));
        }).change();
    });
    

1 Comment

Provided of course that there is no other code that uses the change event on those elements, as you trigger the event when there is no change.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.