views:

31

answers:

2

Hi I am using playing around with the Pretty-checkboxes-plugin and have a problem. The plugin can be seen here http://aaronweyenberg.com/90/pretty-checkboxes-with-jquery

As you can see, this uses two links to select and deselect. I want it to only use one link and then change the class to make it work the other way the next time it is clicked.

It should be simple enough. I have been trying to get it working with toggleClass.

I simply put in the toggleClass statement so the code looks like so:

$(document).ready(function() {

/* see if anything is previously checked and reflect that in the view*/
$(".checklist input:checked").parent().addClass("selected");

/* handle the user selections */
$(".checklist .checkbox-select").click(
function(event) {
  event.preventDefault();
  $(this).parent().addClass("selected");
  $(this).parent().find(":checkbox").attr("checked","checked");
  $(this).toggleClass("checkbox-select checkbox-deselect");

 }

);

$(".checklist .checkbox-deselect").click(
 function(event) {
  event.preventDefault();
   $(this).parent().removeClass("selected");
   $(this).parent().find(":checkbox").removeAttr("checked");
   $(this).toggleClass("checkbox-select checkbox-deselect");
   }

   );

});

This works to some extend. The classes toggle just fine, but the rest of the code only works the first time it is run. All subsequent clicks just toggle the class og the link and nothing else.

Does anyone have any idea why this is?

A: 

The way you've set up your event handlers makes me think that you are imagining that the handlers will be invoked based on the "class" setup dynamically. What you've actually got there is something that statically binds handlers based on the class setting at the time that the "ready" handler is called. The changing of the class assignment does nothing to the way that those handlers are invoked.

Instead of that setup, there are a couple of ways to go. First, you could bind a single event handler and then check the current class inside that handler with a simple "hasClass()" test. That would be pretty simple.

Another approach would be to use the "delegate" or "live" mechanisms, which really do have the dynamic interpretation behavior that your current code seems to wish for.

Pointy
A: 
$(this).toggleClass("checkbox-select checkbox-deselect");

Just changing an element's class doesn't change the event listeners registered on it. You registered the handler for selecting on elements matching $(".checklist .checkbox-select") at ready-time and that handler, not the deselecting handler, is still in place after the element has changed from .checkbox-select to checkbox-deselect.

If you really want event-time binding, you need the live() function instead of plain click() binding. However, I suggest you'd probably be better off with a single function:

$('#checktoggler').click(function() {
    // select all, unless all are already selected, in which case select none
    var selected= $('.checklist input:checked').length!==0;
    selected= !selected;

    $(this).parent().toggleClass('selected', selected);
    $(this).parent().find(":checkbox").attr('checked', selected);
    $(this).toggleClass('checkbox-select checkbox-deselect', selected);
});
bobince
Many thanks. I should have mentioned that I am quite the newbie at javascript and jquery. So I was indeed thinking that it should get evaluated every time. But now I know something about event-listeners so thank you, both you and Pointy.Really nice example, but it had one little hiccup. I dont know if it was intentional, but I could only ever have one element marked as selected, just like radio-buttons.So I changed the line: var selected= $('.checklist input:checked').length!==0;to: var selected= $(this).siblings(':checkbox').attr('checked');And now it works great. :D
Mathias Nielsen