0

I have a series of checkboxes that I want to make a little more mobile-friendly so I'm hiding the checkbox and using labels as buttons. What I want to do is give the user feedback by changing the color of the label from yellow to green when they tap, and then back to yellow when tapping again. I'm pulling my hair out trying to understand why what I'm using isn't working.

<div id="div">
    <label for="checkbox" id="label1" class="bg-warning text-center pointer" style="width:100px; padding:8px">
            <input type="checkbox" name="checkbox1" id="checkbox1" value="checked1" style="display:none">test
        </label>
    </div>

    <label for="checkbox" id="label2" class="bg-warning text-center pointer" style="width:100px; padding:8px">
            <input type="checkbox" name="checkbox2" id="checkbox2" value="checked2" style="display:none">test
        </label>
    </div>
</div>

<script>
    $(document).ready(function(){
        $('#div').on('click', function(e) {
            $('#div').each( function( index, element) {

                var el = $(element);

                if($(el).hasClass('bg-warning')) {
                    $(el).removeClass('bg-warning').addClass('bg-success');
                } else {
                    $(el).removeClass('bg-success').addClass('bg-warning');
                }
            });
        });
    });
</script>
4
  • As I can see, it looks like you have more than one element sharing the same ID div, which is invalid. Commented Aug 24, 2014 at 0:09
  • Also, why are you looping through elements when you actually want to manipulate a single one, which is the one that has been tapped/clicked? Commented Aug 24, 2014 at 0:10
  • @MelanciaUK Because I'm a backend guy trying to learn jQuery :) I don't want to have to write a separate function for each checkbox, which is why I'm looping. Incorrectly, it appears. Commented Aug 24, 2014 at 0:12
  • 1
    Is this what you're looking for? jsfiddle.net/MelanciaUK/4ted9ayf Commented Aug 24, 2014 at 0:14

1 Answer 1

1

First, I would give the divs unique IDs. Then you can set a common class to them (ie: div):

<div id="div1" class="div">
    <label for="checkbox" id="label1" class="bg-warning text-center pointer" style="width:100px; padding:8px">
        <input type="checkbox" name="checkbox1" id="checkbox1" value="checked1" style="display:none" />test
    </label>
</div>
<div id="div2" class="div">
    <label for="checkbox" id="label2" class="bg-warning text-center pointer" style="width:100px; padding:8px">
        <input type="checkbox" name="checkbox2" id="checkbox2" value="checked2" style="display:none" />test
    </label>
</div>

...

$(document).ready(function () {
    $('.div').on('click', function (e) {
        // Find the labels within the clicked div.
        var el = $('label', this);

        // Toggle their classes.
        // No loop needed, as the selector will bring all the elements
        // and apply the change to each one of them.            
        $(el).toggleClass('bg-warning').toggleClass('bg-success');
    });
});

Demo

UPDATE

After our chat in the comments, I think you have two other options here.

Remember to use a # when setting the for attribute for the labels (ie: for="#checkbox2").

First, you keep checking for clicks/taps in the div:

$(function () {    
    $('.div').on('click', function () {
        var label = $('label', this);
        var checkbox = $('input[type=checkbox]', this);

        label.toggleClass('bg-warning bg-success');

        // Checking the label class and deciding if we
        // need to check the checkbox.
        checkbox.prop('checked', label.hasClass('bg-success'));
    });

    $('label input[type=checkbox]').on('click', function(e) {
        // As what's actually clicked is the label, let's
        // ignore the default behavior.
        e.preventDefault();

        // And transfer the click to the div itself.
        $(this).parents('.div').trigger('click');        
    });
});

Demo

Second, you just handle the clicks/taps in the label (which I recommend):

$(function () {    
    $('label').on('click', function () {
        $(this).toggleClass('bg-warning bg-success')
            .find('input[type=checkbox]')
            .prop('checked', $(this).hasClass('bg-success'));
    });
});

Demo

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

10 Comments

Perfect. Simple, elegant and just what I was looking for. Thanks :)
It is shorter : $(el).toggleClass('bg-warning bg-success');
@Football-Is-My-Life thanks for the improvement tip!
Spoke too soon. Clicking the label was not selecting the checkbox, as you had the same for="" on each label, so an ID wasn't being targeted. When updating the for to checkbox1 and checkbox2 it broke.
But I can't see this requirement in your question/code? I worked out just the class toggling...
|

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.